{"owner":"antvis","repo":"G6","hasSkills":true,"totalSkillsCount":298,"totalTokensCount":600323,"categories":["cursor-rule","plugin-manifest","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".cursor/rules/translation.mdc","packages/cli/README.md","packages/g6-extension-3d/README.md","packages/g6-extension-react/README.md","packages/g6-ssr/README.md","packages/g6/src/plugins/hull/hull/README.md","packages/site/docs/api/behavior.en.md","packages/site/docs/api/behavior.zh.md","packages/site/docs/api/canvas.en.md","packages/site/docs/api/canvas.zh.md","packages/site/docs/api/coordinate.en.md","packages/site/docs/api/coordinate.zh.md","packages/site/docs/api/data.en.md","packages/site/docs/api/data.zh.md","packages/site/docs/api/element.en.md","packages/site/docs/api/element.zh.md","packages/site/docs/api/event.en.md","packages/site/docs/api/event.zh.md","packages/site/docs/api/export-image.en.md","packages/site/docs/api/export-image.zh.md","packages/site/docs/api/graph.en.md","packages/site/docs/api/graph.zh.md","packages/site/docs/api/layout.en.md","packages/site/docs/api/layout.zh.md","packages/site/docs/api/option.en.md","packages/site/docs/api/option.zh.md","packages/site/docs/api/plugin.en.md","packages/site/docs/api/plugin.zh.md","packages/site/docs/api/render.en.md","packages/site/docs/api/render.zh.md","packages/site/docs/api/theme.en.md","packages/site/docs/api/theme.zh.md","packages/site/docs/api/transform.en.md","packages/site/docs/api/transform.zh.md","packages/site/docs/api/viewport.en.md","packages/site/docs/api/viewport.zh.md","packages/site/docs/backup/CameraSetting.en.md","packages/site/docs/backup/CameraSetting.zh.md","packages/site/docs/manual/animation/animation.en.md","packages/site/docs/manual/animation/animation.zh.md","packages/site/docs/manual/animation/custom-animation.en.md","packages/site/docs/manual/animation/custom-animation.zh.md","packages/site/docs/manual/behavior/AutoAdaptLabel.en.md","packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md","packages/site/docs/manual/behavior/BrushSelect.en.md","packages/site/docs/manual/behavior/BrushSelect.zh.md","packages/site/docs/manual/behavior/ClickSelect.en.md","packages/site/docs/manual/behavior/ClickSelect.zh.md","packages/site/docs/manual/behavior/CollapseExpand.en.md","packages/site/docs/manual/behavior/CollapseExpand.zh.md","packages/site/docs/manual/behavior/CreateEdge.en.md","packages/site/docs/manual/behavior/CreateEdge.zh.md","packages/site/docs/manual/behavior/DragCanvas.en.md","packages/site/docs/manual/behavior/DragCanvas.zh.md","packages/site/docs/manual/behavior/DragElement.en.md","packages/site/docs/manual/behavior/DragElement.zh.md","packages/site/docs/manual/behavior/DragElementForce.en.md","packages/site/docs/manual/behavior/DragElementForce.zh.md","packages/site/docs/manual/behavior/FixElementSize.en.md","packages/site/docs/manual/behavior/FixElementSize.zh.md","packages/site/docs/manual/behavior/FocusElement.en.md","packages/site/docs/manual/behavior/FocusElement.zh.md","packages/site/docs/manual/behavior/HoverActivate.en.md","packages/site/docs/manual/behavior/HoverActivate.zh.md","packages/site/docs/manual/behavior/LassoSelect.en.md","packages/site/docs/manual/behavior/LassoSelect.zh.md","packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md","packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md","packages/site/docs/manual/behavior/ScrollCanvas.en.md","packages/site/docs/manual/behavior/ScrollCanvas.zh.md","packages/site/docs/manual/behavior/ZoomCanvas.en.md","packages/site/docs/manual/behavior/ZoomCanvas.zh.md","packages/site/docs/manual/behavior/custom-behavior.en.md","packages/site/docs/manual/behavior/custom-behavior.zh.md","packages/site/docs/manual/behavior/overview.en.md","packages/site/docs/manual/behavior/overview.zh.md","packages/site/docs/manual/contribute.en.md","packages/site/docs/manual/contribute.zh.md","packages/site/docs/manual/data.en.md","packages/site/docs/manual/data.zh.md","packages/site/docs/manual/element/combo/BaseCombo.en.md","packages/site/docs/manual/element/combo/BaseCombo.zh.md","packages/site/docs/manual/element/combo/CircleCombo.en.md","packages/site/docs/manual/element/combo/CircleCombo.zh.md","packages/site/docs/manual/element/combo/RectCombo.en.md","packages/site/docs/manual/element/combo/RectCombo.zh.md","packages/site/docs/manual/element/combo/custom-combo.en.md","packages/site/docs/manual/element/combo/custom-combo.zh.md","packages/site/docs/manual/element/combo/overview.en.md","packages/site/docs/manual/element/combo/overview.zh.md","packages/site/docs/manual/element/edge/BaseEdge.en.md","packages/site/docs/manual/element/edge/BaseEdge.zh.md","packages/site/docs/manual/element/edge/Cubic.en.md","packages/site/docs/manual/element/edge/Cubic.zh.md","packages/site/docs/manual/element/edge/CubicHorizontal.en.md","packages/site/docs/manual/element/edge/CubicHorizontal.zh.md","packages/site/docs/manual/element/edge/CubicVertical.en.md","packages/site/docs/manual/element/edge/CubicVertical.zh.md","packages/site/docs/manual/element/edge/Line.en.md","packages/site/docs/manual/element/edge/Line.zh.md","packages/site/docs/manual/element/edge/Polyline.en.md","packages/site/docs/manual/element/edge/Polyline.zh.md","packages/site/docs/manual/element/edge/Quadratic.en.md","packages/site/docs/manual/element/edge/Quadratic.zh.md","packages/site/docs/manual/element/edge/custom-edge.en.md","packages/site/docs/manual/element/edge/custom-edge.zh.md","packages/site/docs/manual/element/edge/overview.en.md","packages/site/docs/manual/element/edge/overview.zh.md","packages/site/docs/manual/element/node/BaseNode.en.md","packages/site/docs/manual/element/node/BaseNode.zh.md","packages/site/docs/manual/element/node/Circle.en.md","packages/site/docs/manual/element/node/Circle.zh.md","packages/site/docs/manual/element/node/Diamond.en.md","packages/site/docs/manual/element/node/Diamond.zh.md","packages/site/docs/manual/element/node/Donut.en.md","packages/site/docs/manual/element/node/Donut.zh.md","packages/site/docs/manual/element/node/Ellipse.en.md","packages/site/docs/manual/element/node/Ellipse.zh.md","packages/site/docs/manual/element/node/Hexagon.en.md","packages/site/docs/manual/element/node/Hexagon.zh.md","packages/site/docs/manual/element/node/Html.en.md","packages/site/docs/manual/element/node/Html.zh.md","packages/site/docs/manual/element/node/Image.en.md","packages/site/docs/manual/element/node/Image.zh.md","packages/site/docs/manual/element/node/Rect.en.md","packages/site/docs/manual/element/node/Rect.zh.md","packages/site/docs/manual/element/node/Star.en.md","packages/site/docs/manual/element/node/Star.zh.md","packages/site/docs/manual/element/node/Triangle.en.md","packages/site/docs/manual/element/node/Triangle.zh.md","packages/site/docs/manual/element/node/custom-node.en.md","packages/site/docs/manual/element/node/custom-node.zh.md","packages/site/docs/manual/element/node/overview.en.md","packages/site/docs/manual/element/node/overview.zh.md","packages/site/docs/manual/element/node/react-node.en.md","packages/site/docs/manual/element/node/react-node.zh.md","packages/site/docs/manual/element/node/vue-node.en.md","packages/site/docs/manual/element/node/vue-node.zh.md","packages/site/docs/manual/element/overview.en.md","packages/site/docs/manual/element/overview.zh.md","packages/site/docs/manual/element/shape/label-shape.en.md","packages/site/docs/manual/element/shape/label-shape.zh.md","packages/site/docs/manual/element/shape/overview.en.md","packages/site/docs/manual/element/shape/overview.zh.md","packages/site/docs/manual/element/shape/properties.en.md","packages/site/docs/manual/element/shape/properties.zh.md","packages/site/docs/manual/element/state.en.md","packages/site/docs/manual/element/state.zh.md","packages/site/docs/manual/extension/3d.en.md","packages/site/docs/manual/extension/3d.zh.md","packages/site/docs/manual/faq.en.md","packages/site/docs/manual/faq.zh.md","packages/site/docs/manual/further-reading/3d.en.md","packages/site/docs/manual/further-reading/3d.zh.md","packages/site/docs/manual/further-reading/bundle.en.md","packages/site/docs/manual/further-reading/bundle.zh.md","packages/site/docs/manual/further-reading/coordinate.en.md","packages/site/docs/manual/further-reading/coordinate.zh.md","packages/site/docs/manual/further-reading/download-image.en.md","packages/site/docs/manual/further-reading/download-image.zh.md","packages/site/docs/manual/further-reading/event.en.md","packages/site/docs/manual/further-reading/event.zh.md","packages/site/docs/manual/further-reading/iconfont.en.md","packages/site/docs/manual/further-reading/iconfont.zh.md","packages/site/docs/manual/further-reading/renderer.en.md","packages/site/docs/manual/further-reading/renderer.zh.md","packages/site/docs/manual/getting-started/installation.en.md","packages/site/docs/manual/getting-started/installation.zh.md","packages/site/docs/manual/getting-started/integration/angular.en.md","packages/site/docs/manual/getting-started/integration/angular.zh.md","packages/site/docs/manual/getting-started/integration/react.en.md","packages/site/docs/manual/getting-started/integration/react.zh.md","packages/site/docs/manual/getting-started/integration/vue.en.md","packages/site/docs/manual/getting-started/integration/vue.zh.md","packages/site/docs/manual/getting-started/quick-start.en.md","packages/site/docs/manual/getting-started/quick-start.zh.md","packages/site/docs/manual/getting-started/step-by-step.en.md","packages/site/docs/manual/getting-started/step-by-step.zh.md","packages/site/docs/manual/graph/extension.en.md","packages/site/docs/manual/graph/extension.zh.md","packages/site/docs/manual/graph/extensions.en.md","packages/site/docs/manual/graph/extensions.zh.md","packages/site/docs/manual/graph/graph.en.md","packages/site/docs/manual/graph/graph.zh.md","packages/site/docs/manual/graph/option.en.md","packages/site/docs/manual/graph/option.zh.md","packages/site/docs/manual/introduction.en.md","packages/site/docs/manual/introduction.zh.md","packages/site/docs/manual/layout/AntvDagreLayout.en.md","packages/site/docs/manual/layout/AntvDagreLayout.zh.md","packages/site/docs/manual/layout/BaseLayout.en.md","packages/site/docs/manual/layout/BaseLayout.zh.md","packages/site/docs/manual/layout/CircularLayout.en.md","packages/site/docs/manual/layout/CircularLayout.zh.md","packages/site/docs/manual/layout/ComboCombinedLayout.en.md","packages/site/docs/manual/layout/ComboCombinedLayout.zh.md","packages/site/docs/manual/layout/CompactBoxLayout.en.md","packages/site/docs/manual/layout/CompactBoxLayout.zh.md","packages/site/docs/manual/layout/ConcentricLayout.en.md","packages/site/docs/manual/layout/ConcentricLayout.zh.md","packages/site/docs/manual/layout/D3Force3DLayout.en.md","packages/site/docs/manual/layout/D3Force3DLayout.zh.md","packages/site/docs/manual/layout/D3ForceLayout.en.md","packages/site/docs/manual/layout/D3ForceLayout.zh.md","packages/site/docs/manual/layout/DagreLayout.en.md","packages/site/docs/manual/layout/DagreLayout.zh.md","packages/site/docs/manual/layout/DendrogramLayout.en.md","packages/site/docs/manual/layout/DendrogramLayout.zh.md","packages/site/docs/manual/layout/Fishbone.en.md","packages/site/docs/manual/layout/Fishbone.zh.md","packages/site/docs/manual/layout/ForceAtlas2Layout.en.md","packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md","packages/site/docs/manual/layout/ForceLayout.en.md","packages/site/docs/manual/layout/ForceLayout.zh.md","packages/site/docs/manual/layout/FruchtermanLayout.en.md","packages/site/docs/manual/layout/FruchtermanLayout.zh.md","packages/site/docs/manual/layout/GridLayout.en.md","packages/site/docs/manual/layout/GridLayout.zh.md","packages/site/docs/manual/layout/IndentedLayout.en.md","packages/site/docs/manual/layout/IndentedLayout.zh.md","packages/site/docs/manual/layout/MdsLayout.en.md","packages/site/docs/manual/layout/MdsLayout.zh.md","packages/site/docs/manual/layout/MindmapLayout.en.md","packages/site/docs/manual/layout/MindmapLayout.zh.md","packages/site/docs/manual/layout/RadialLayout.en.md","packages/site/docs/manual/layout/RadialLayout.zh.md","packages/site/docs/manual/layout/RandomLayout.en.md","packages/site/docs/manual/layout/RandomLayout.zh.md","packages/site/docs/manual/layout/Snake.en.md","packages/site/docs/manual/layout/Snake.zh.md","packages/site/docs/manual/layout/custom-layout.en.md","packages/site/docs/manual/layout/custom-layout.zh.md","packages/site/docs/manual/layout/overview.en.md","packages/site/docs/manual/layout/overview.zh.md","packages/site/docs/manual/plugin/Background.en.md","packages/site/docs/manual/plugin/Background.zh.md","packages/site/docs/manual/plugin/BubbleSets.en.md","packages/site/docs/manual/plugin/BubbleSets.zh.md","packages/site/docs/manual/plugin/Contextmenu.en.md","packages/site/docs/manual/plugin/Contextmenu.zh.md","packages/site/docs/manual/plugin/EdgeBundling.en.md","packages/site/docs/manual/plugin/EdgeBundling.zh.md","packages/site/docs/manual/plugin/EdgeFilterLens.en.md","packages/site/docs/manual/plugin/EdgeFilterLens.zh.md","packages/site/docs/manual/plugin/Fisheye.en.md","packages/site/docs/manual/plugin/Fisheye.zh.md","packages/site/docs/manual/plugin/Fullscreen.en.md","packages/site/docs/manual/plugin/Fullscreen.zh.md","packages/site/docs/manual/plugin/GridLine.en.md","packages/site/docs/manual/plugin/GridLine.zh.md","packages/site/docs/manual/plugin/History.en.md","packages/site/docs/manual/plugin/History.zh.md","packages/site/docs/manual/plugin/Hull.en.md","packages/site/docs/manual/plugin/Hull.zh.md","packages/site/docs/manual/plugin/Legend.en.md","packages/site/docs/manual/plugin/Legend.zh.md","packages/site/docs/manual/plugin/Minimap.en.md","packages/site/docs/manual/plugin/Minimap.zh.md","packages/site/docs/manual/plugin/Snapline.en.md","packages/site/docs/manual/plugin/Snapline.zh.md","packages/site/docs/manual/plugin/Timebar.en.md","packages/site/docs/manual/plugin/Timebar.zh.md","packages/site/docs/manual/plugin/Title.en.md","packages/site/docs/manual/plugin/Title.zh.md","packages/site/docs/manual/plugin/Toolbar.en.md","packages/site/docs/manual/plugin/Toolbar.zh.md","packages/site/docs/manual/plugin/Tooltip.en.md","packages/site/docs/manual/plugin/Tooltip.zh.md","packages/site/docs/manual/plugin/Watermark.en.md","packages/site/docs/manual/plugin/Watermark.zh.md","packages/site/docs/manual/plugin/custom-plugin.en.md","packages/site/docs/manual/plugin/custom-plugin.zh.md","packages/site/docs/manual/plugin/overview.en.md","packages/site/docs/manual/plugin/overview.zh.md","packages/site/docs/manual/theme/custom-palette.en.md","packages/site/docs/manual/theme/custom-palette.zh.md","packages/site/docs/manual/theme/custom-theme.en.md","packages/site/docs/manual/theme/custom-theme.zh.md","packages/site/docs/manual/theme/overview.en.md","packages/site/docs/manual/theme/overview.zh.md","packages/site/docs/manual/theme/palette.en.md","packages/site/docs/manual/theme/palette.zh.md","packages/site/docs/manual/transform/MapNodeSize.en.md","packages/site/docs/manual/transform/MapNodeSize.zh.md","packages/site/docs/manual/transform/PlaceRadialLabels.en.md","packages/site/docs/manual/transform/PlaceRadialLabels.zh.md","packages/site/docs/manual/transform/ProcessParallelEdges.en.md","packages/site/docs/manual/transform/ProcessParallelEdges.zh.md","packages/site/docs/manual/transform/custom-transform.en.md","packages/site/docs/manual/transform/custom-transform.zh.md","packages/site/docs/manual/transform/overview.en.md","packages/site/docs/manual/transform/overview.zh.md","packages/site/docs/manual/whats-new/feature.en.md","packages/site/docs/manual/whats-new/feature.zh.md","packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md","packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md","packages/site/docs/manual/whats-new/upgrade.en.md","packages/site/docs/manual/whats-new/upgrade.zh.md"],"skills":{".cursor/rules/translation.mdc":"---\ndescription: 翻译\nglobs:\nalwaysApply: false\n---\n# Translation Guidelines for site/docs\n\nWhen translating files under the `site/docs` directory, please adhere to the following guidelines:\n\n1. **Consistency in Terminology**: Ensure that terminology is consistent throughout the document. Use a glossary if available to maintain uniformity in terms.\n\n   **Glossary**:\n\n   - 画布 (Canvas)\n   - 元素 (Element)\n   - 节点 (Node)\n   - 边 (Edge)\n   - 组合 (Combo)\n   - 交互 (Behavior)\n   - 布局 (Layout)\n   - 插件 (Plugin)\n   - 动画 (Animation)\n   - 数据处理 (Transform)\n   - 色板 (Palette)\n   - 配置项 (Option)\n   - 图数据 (Graph Data)\n   - 树图 (Tree Graph)\n   - 属性 (Property)\n   - 描述 (Description)\n   - 类型 (Type)\n   - 默认值 (Default Value)\n   - 必选 (Required)\n\n2. **Adjust Hyperlinks**: Review and adjust hyperlinks to ensure they point to the correct translated sections or documents. Verify that all links are functional and correctly formatted.\n\n   - **Internal Links**: In the English version, all internal links should have a `/en` prefix, while the Chinese version should not have any prefix. Ensure this prefix is added to all internal links in English documents to avoid any oversight.\n   - **Anchor Points**: For anchor points following a `#`, if they contain Chinese characters, they should be adjusted to match the corresponding title in the English version rather than being directly translated.\n   - **External Links**: Convert external links appropriately to ensure they align with the language and context of the document.\n\n3. **Direct Writing to Translated Documents**: Translations should be stored in corresponding `.en.md` or `.zh.md` files within the same directory. Ensure that the translated content is placed in the correct location within the document.\n\n   - When translating from Chinese to English, create or update the `.en.md` file in the same directory.\n   - When translating from English to Chinese, create or update the `.zh.md` file in the same directory.\n\n4. **Support for Partial Content Translation**: Allow for the selection and translation of specific sections of content. Translated sections should be inserted into the appropriate location within the document, maintaining the logical flow and structure.\n\n   - **Full Document Translation**: If the entire document is selected for translation, replace the entire content with the translated version.\n   - **Partial Content Translation**: If only specific sections are selected, find the appropriate place to replace or insert the translated content, ensuring the document's logical flow and structure are maintained.\n\n5. **Contextual Translation**: Avoid literal translations. Ensure that the translation fits the English context and conveys the intended meaning accurately.\n\n6. **Direct Modification**: Translations should be directly modified in the corresponding `.en.md` or `.zh.md` files without returning the translated content separately. Ensure that the changes are saved in the correct file and location.\n\n7. **Preserve Metadata Order**: Do not modify the `order` attribute in the page metadata during translation. This ensures that the document order remains consistent across different language versions.\n\n8. **Add '/en' Prefix to Internal Links**: Ensure that all internal links in English documentation have the '/en' prefix to maintain consistency and correct navigation.\n\nBy following these guidelines, translations will be more accurate and consistent, facilitating easier review and integration into the documentation.\n","packages/cli/README.md":"# @antv/g6-cli\n\n`@antv/g6-cli` is a G6 template generation tool that comes with several templates.\n\nCurrently, it owns a built-in template called `extension`. This template handles the boilerplate setup, which encompasses a seamless local development environment, linting, code formatting, Jest for snapshot testing and bundling with Rollup etc.\n\n`@antv/g6-cli` i\n\n## Getting Started\n\nTo start using `@antv/g6-cli`, you'll first need to install it globally.\n\n```bash\nnpm i @antv/g6-cli -g\n```\n\nOnce installed, you can easily scaffold a new project:\n\n```bash\ncreate-g6\n```\n\nThen follow the prompts!\n\n![prompts](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*09BKQrIcZUMAAAAAAAAAAAAADmJ7AQ/original)\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a **G6 Extension** project, run:\n\n```bash\ncreate-g6 g6-extension-test --template extension\n```\n","packages/g6-extension-3d/README.md":"## 3D extension for G6\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*lEL3TrCLnPsAAAAAAAAAAAAADmJ7AQ/original\" />\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yFa5RKilu6kAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension package provides 3D elements, behaviors and plugins for G6.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-3d\n```\n\n2. Import and Register\n\n> Where renderer, elements and lighting are necessary\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { DragCanvas3D, Light, Line3D, Sphere, renderer } from '@antv/g6-extension-3d';\n\n// 3d light plugin\nregister(ExtensionCategory.PLUGIN, '3d-light', Light);\n// sphere node element\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\n// line edge element\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\n// drag canvas in 3d scene\nregister(ExtensionCategory.BEHAVIOR, 'drag-canvas-3d', DragCanvas3D);\n// camera setting plugin\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting);\n```\n\n3. Use\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  renderer, // use 3d renderer\n  data: {\n    // your data\n  },\n  node: {\n    type: 'sphere', // use sphere node\n  },\n  edge: {\n    type: 'line3d', // use 3d line edge\n  },\n  behaviors: ['drag-canvas-3d'],\n  plugins: [\n    // set camera configs, see: https://g.antv.antgroup.com/en/api/camera/intro\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n    // add directional light\n    {\n      type: '3d-light',\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n```\n\n## Resources\n\n- [Lite Solar System](https://g6.antv.antgroup.com/en/examples/feature/default/#lite-solar-system)\n- [3D Node](https://g6.antv.antgroup.com/en/examples/element/node/#3d-node)\n","packages/g6-extension-react/README.md":"## React extension for G6\n\n<img width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rWSiT6dnwfcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension allows you to define G6 node by React component and JSX syntax.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-react\n```\n\n2. Import and Register\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n```\n\n3. Define Node\n\nReact Node:\n\n```jsx\nconst ReactNode = () => {\n  return <div>node</div>;\n};\n```\n\nG Node:\n\n```jsx\nimport { Group, Rect, Text } from '@antv/g6-extension-react';\n\nconst GNode = () => {\n  return <Group>\n    <Rect width={100} height={100}></Rect>\n    <Text text={\"node\"} />\n  <Group>\n};\n```\n\n4. Use\n\nUse ReactNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'react',\n    style: {\n      component: () => <ReactNode />,\n    },\n  },\n});\n```\n\nUse GNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'g',\n    style: {\n      component: () => <GNode />,\n    },\n  },\n});\n```\n\n## Q&A\n\n1. Difference between ReactNode and GNode\n\nReactNode is a React component, while GNode support jsx syntax but can only use G tag node.\n\n## Resources\n\n- [React node](https://g6.antv.antgroup.com/examples/element/custom-node/#react-node)\n- [G node with JSX syntax](https://g6.antv.antgroup.com/en/examples/element/custom-node/#react-g)\n","packages/g6-ssr/README.md":"## SSR extension for G6 5.0\n\nThis extension package provides SSR support for G6 5.0, which supports canvas rendering in server side.\n\n## Usage\n\n### Install\n\n```bash\nnpm install @antv/g6-ssr\n```\n\n### Render in JavaScript API\n\n> For complete options, please refer to [G6 Graph Options](https://g6.antv.antgroup.com/api/graph/option)\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  imageType: 'png', // or 'jpeg'\n  data: {\n    // data\n  },\n  // other options\n});\n\ngraph.exportToFile('image');\n// -> image.png\n\ngraph.toBuffer();\n// -> get buffer\n```\n\n### Render in CLI\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./image\n```\n\n### Export SVG / PDF\n\nWhen render in JavaScript API, you can pass `outputType` option to export SVG or PDF.\n\n```js\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  data: {\n    // data\n  },\n  outputType: 'svg', // or 'pdf'\n  // other options\n});\n```\n\nWhen render in CLI, you can pass `-t` or `--type` option to export SVG or PDF.\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./file -t pdf\n```\n\n### Register Custom G6 Extensions\n\nIf you need to register custom extensions of G6, please use the `registry` function exported from `@antv/g6-ssr`.\n\n```js\nimport { createGraph, registry } from '@antv/g6-ssr';\nimport { BaseNode, ExtensionCategory } from '@antv/g6';\n\nclass CustomNode extends BaseNode {\n  // custom node\n}\n\nregistry(ExtensionCategory.Node, 'custom-node', CustomNode);\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  node: {\n    type: 'custom-node',\n    // other options\n  },\n  // other options\n});\n```\n\n### Use Plugins\n\nWhen using G6-SSR, you can also use G render plugins. Here's how to use plugins in server-side rendering:\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\nimport { Plugin as RoughCanvasPlugin } from '@antv/g-plugin-rough-canvas-renderer';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  renderPlugins: [new RoughCanvasPlugin()],\n  data: {\n    // data\n  },\n});\n```\n\n## License\n\nMIT\n","packages/g6/src/plugins/hull/hull/README.md":"> Code copied from [hull-js](https://github.com/hull/hull-js), and fix the issue [[Bug]: hull.js Code Injection Vulnerability #6605](https://github.com/antvis/G6/issues/6605).\n","packages/site/docs/api/behavior.en.md":"---\ntitle: Behavior\norder: 8\n---\n\n## Overview of Behavior\n\nBehavior is a core building block of G6, precisely defining the interaction between users and the graph. Each Behavior plugin is a highly encapsulated functional unit, integrating event listening, state management, and response handling logic for specific scenarios.\n\nG6's built-in Behaviors cover most common interaction needs and provide a flexible extension mechanism, allowing developers to create customized interaction experiences based on business scenarios. For a complete list of behavior types, configuration options, and development examples, please refer to the [Behavior Overview](/en/manual/behavior/overview) section.\n\n## API Reference\n\n### Graph.getBehaviors()\n\nGet all configured behaviors in the current graph.\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**Return Value**\n\n- **Type**: [BehaviorOptions](#behavioroptions)\n- **Description**: All configured behaviors in the current graph\n\n**Example**\n\n```typescript\n// Get all current behaviors\nconst behaviors = graph.getBehaviors();\nconsole.log('Current graph behaviors:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\nSet the behaviors of the graph, replacing all existing behaviors.\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                    | Type                                                                              | Default | Required |\n| --------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------- | -------- |\n| behaviors | New behavior configuration, or a function returning new configuration based on the current one | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -       | ✓        |\n\n**Note**\n\nThe set behaviors will completely replace the original ones. To add new behaviors, you can use functional updates:\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**Example 1**: Set basic behaviors\n\n```typescript\n// Set basic behaviors\ngraph.setBehaviors([\n  'drag-canvas', // Drag canvas\n  'zoom-canvas', // Zoom canvas\n  'drag-element', // Drag element\n]);\n```\n\n**Example 2**: Set behaviors with configuration\n\n```typescript\ngraph.setBehaviors([\n  // String form (using default configuration)\n  'drag-canvas',\n\n  // Object form (custom configuration)\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // Specify a unique identifier for subsequent updates\n    sensitivity: 1.5, // Zoom sensitivity\n  },\n\n  // Enable drag only on nodes\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // Enable drag only on nodes\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new behavior\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// Replace specific behavior\ngraph.setBehaviors((currentBehaviors) => {\n  // Filter out existing zoom behaviors\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // Add new zoom behavior configuration\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\nUpdate the configuration of a specific behavior, identified by the `key`.\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                             | Type                                          | Default | Required |\n| --------- | --------------------------------------- | --------------------------------------------- | ------- | -------- |\n| behavior  | Configuration of the behavior to update | [UpdateBehaviorOption](#updatebehavioroption) | -       | ✓        |\n\n**Note**\n\nTo update a behavior, the original behavior configuration must specify the `key` field to accurately locate and update the behavior.\n\n**Example 1**: Update behavior configuration\n\n```typescript\n// Specify key when initially setting behaviors\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// Update behavior configuration\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // Specify the behavior to update\n  sensitivity: 2.0, // New zoom sensitivity\n  enableOptimize: true, // Add new configuration\n});\n```\n\n**Example 2**: Disable/Enable behavior\n\n```typescript\n// Set behaviors with keys\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// Disable drag functionality\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// Re-enable later\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## Type Definitions\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // Interaction type\n  type: string;\n\n  // Interaction key, a unique identifier for identifying and further operating this interaction\n  key?: string;\n\n  // There may be other configuration items for different types of interactions\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // Unique identifier of the behavior to update\n  key: string;\n\n  // Other configuration items to update\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/behavior.zh.md":"---\ntitle: 交互\norder: 8\n---\n\n## 交互概述\n\n交互（Behavior）是 G6 的核心构建模块，它精确定义了用户与图之间的互动行为。每个 Behavior 插件都是一个高度封装的功能单元，内部集成了特定场景下的事件监听、状态管理和响应处理逻辑。\n\nG6 的内置 Behavior 涵盖了大多数常见交互需求，同时提供了灵活的扩展机制，支持开发者根据业务场景构建定制化交互体验。\n有关完整的交互行为类型、配置选项及开发示例，请参阅 [交互总览](/manual/behavior/overview) 章节。\n\n## API 参考\n\n### Graph.getBehaviors()\n\n获取当前图表中所有已配置的交互行为。\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**返回值**\n\n- **类型**: [BehaviorOptions](#behavioroptions)\n- **描述**: 当前图表中已配置的所有交互行为\n\n**示例**\n\n```typescript\n// 获取当前所有交互行为\nconst behaviors = graph.getBehaviors();\nconsole.log('当前图表的交互行为:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\n设置图表的交互行为，将替换所有现有的交互行为。\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**参数**\n\n| 参数      | 描述                                                 | 类型                                                                              | 默认值 | 必选 |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | ------ | ---- |\n| behaviors | 新的交互行为配置，或一个基于当前配置返回新配置的函数 | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -      | ✓    |\n\n**说明**\n\n设置的交互会全量替换原有的交互，如果需要新增交互可以使用函数式更新：\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**示例 1**: 设置基本交互\n\n```typescript\n// 设置基本交互\ngraph.setBehaviors([\n  'drag-canvas', // 拖拽画布\n  'zoom-canvas', // 缩放画布\n  'drag-element', // 拖拽元素\n]);\n```\n\n**示例 2**: 设置带配置的交互\n\n```typescript\ngraph.setBehaviors([\n  // 字符串形式（使用默认配置）\n  'drag-canvas',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // 指定唯一标识，用于后续更新\n    sensitivity: 1.5, // 缩放灵敏度\n  },\n\n  // 只有节点上启用拖拽\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // 仅在节点上启用拖拽\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的交互行为\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// 替换特定交互行为\ngraph.setBehaviors((currentBehaviors) => {\n  // 过滤掉现有的缩放交互\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // 添加新的缩放交互配置\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\n更新指定的交互行为配置，需要通过 `key` 标识要更新的交互。\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**参数**\n\n| 参数     | 描述               | 类型                                          | 默认值 | 必选 |\n| -------- | ------------------ | --------------------------------------------- | ------ | ---- |\n| behavior | 更新的交互行为配置 | [UpdateBehaviorOption](#updatebehavioroption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个交互，必须在原始交互配置中指定 `key` 字段，以便能够准确找到并更新该交互。\n\n**示例 1**: 更新交互配置\n\n```typescript\n// 初始设置交互时指定 key\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// 更新交互配置\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // 指定要更新的交互\n  sensitivity: 2.0, // 新的缩放灵敏度\n  enableOptimize: true, // 添加新配置\n});\n```\n\n**示例 2**: 禁用/启用交互\n\n```typescript\n// 设置带 key 的行为\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// 禁用拖拽功能\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// 稍后重新启用\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## 类型定义\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // 交互类型\n  type: string;\n\n  // 交互 key，即唯一标识，用于标识交互，从而进一步操作此交互\n  key?: string;\n\n  // 针对不同类型的交互，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // 要更新的交互的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/canvas.en.md":"---\ntitle: Canvas Operations\norder: 1\n---\n\n## Overview of Canvas Operations\n\nG6 provides a series of canvas operation APIs to control and obtain basic information about the canvas. With these APIs, you can:\n\n- Get the canvas instance\n- Get and set the canvas size\n- Operate the canvas renderer and layers\n\n## API Reference\n\n### Graph.getCanvas()\n\nGet the canvas instance, which can be used for low-level canvas operations.\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**Return Value Description**\n\nThe Canvas instance includes the following main functions:\n\n- `getLayer(name?: string)`: Get the specified layer\n- `getLayers()`: Get all layers\n- `getCamera()`: Get the camera instance\n- `getRoot()`: Get the root node\n- `setCursor(cursor: string)`: Set the mouse cursor style\n\n**Example**\n\n```typescript\n// Get the canvas instance\nconst canvas = graph.getCanvas();\n\n// Get the main layer\nconst mainLayer = canvas.getLayer('main');\n\n// Set the mouse cursor style\ncanvas.setCursor('pointer');\n\n// Get the root node of the canvas\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\nGet the size of the current canvas container. Returns an array containing the width and height.\n\n```typescript\ngetSize(): [number, number];\n```\n\n**Example**\n\n```typescript\n// Get the canvas size\nconst [width, height] = graph.getSize();\nconsole.log('Canvas width:', width);\nconsole.log('Canvas height:', height);\n\n// Use the size information for calculations\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\nSet the size of the canvas container. This method will update both the canvas and container size.\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description            | Type   | Default | Required |\n| --------- | ---------------------- | ------ | ------- | -------- |\n| width     | Canvas width (pixels)  | number | -       | ✓        |\n| height    | Canvas height (pixels) | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set a fixed size\ngraph.setSize(800, 600);\n```\n","packages/site/docs/api/canvas.zh.md":"---\ntitle: 画布操作\norder: 1\n---\n\n## 画布操作概述\n\nG6 提供了一系列画布操作 API，用于控制和获取画布的基本信息。通过这些 API，你可以：\n\n- 获取画布实例\n- 获取和设置画布尺寸\n- 操作画布渲染器和图层\n\n## API 参考\n\n### Graph.getCanvas()\n\n获取画布实例，返回的实例可用于进行底层的画布操作。\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**返回值类型说明**\n\nCanvas 实例包含以下主要功能：\n\n- `getLayer(name?: string)`: 获取指定图层\n- `getLayers()`: 获取所有图层\n- `getCamera()`: 获取相机实例\n- `getRoot()`: 获取根节点\n- `setCursor(cursor: string)`: 设置鼠标样式\n\n**示例**\n\n```typescript\n// 获取画布实例\nconst canvas = graph.getCanvas();\n\n// 获取主图层\nconst mainLayer = canvas.getLayer('main');\n\n// 设置鼠标样式\ncanvas.setCursor('pointer');\n\n// 获取画布根节点\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\n获取当前画布容器的尺寸。返回一个包含宽度和高度的数组。\n\n```typescript\ngetSize(): [number, number];\n```\n\n**示例**\n\n```typescript\n// 获取画布尺寸\nconst [width, height] = graph.getSize();\nconsole.log('画布宽度:', width);\nconsole.log('画布高度:', height);\n\n// 使用尺寸信息进行计算\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\n设置画布容器的尺寸。这个方法会同时更新画布和容器的大小。\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述             | 类型   | 默认值 | 必选 |\n| ------ | ---------------- | ------ | ------ | ---- |\n| width  | 画布宽度（像素） | number | -      | ✓    |\n| height | 画布高度（像素） | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置固定尺寸\ngraph.setSize(800, 600);\n```\n","packages/site/docs/api/coordinate.en.md":"---\ntitle: Coordinate Transformation\norder: 12\n---\n\n## Overview of Coordinate Systems\n\nUnderstanding different coordinate systems and their transformations is crucial in graph visualization. G6 involves multiple coordinate systems, each used for different scenarios:\n\n- **Client Coordinate System**: Origin is at the top-left corner of the browser viewport, measured in pixels. Typically used for handling browser events.\n- **Screen Coordinate System**: Origin is at the top-left corner of the screen, affected by page scrolling.\n- **Page Coordinate System**: Origin is at the top-left corner of the document, considering document scrolling.\n- **Canvas Coordinate System**: Also known as the world coordinate system, used for drawing and layout, with the origin at the top-left corner of the canvas element.\n- **Viewport Coordinate System**: The visible area of the canvas, with the origin at the top-left corner of the viewport. The viewport can be panned and zoomed to view different areas of the Canvas.\n\nIn this [example](https://g.antv.antgroup.com/en/examples/canvas/canvas-basic#coordinates), moving the mouse shows the position in various coordinate systems:\n\n![Coordinate System Diagram](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\nWhen the canvas is not panned or zoomed, the Viewport and Canvas coordinate systems coincide. With user interactions like dragging or zooming, the two systems may shift.\n\nG6 provides a series of APIs for converting between different coordinate systems, detailed below.\n\n## API Reference\n\n### Graph.getCanvasByClient(point)\n\nConvert browser coordinates (client coordinates) to canvas coordinates.\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description              | Type                                         | Default | Required |\n| --------- | ------------------------ | -------------------------------------------- | ------- | -------- |\n| point     | Browser coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getCanvasByViewport(point)\n\nConvert viewport coordinates to canvas coordinates.\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                         | Default | Required |\n| --------- | ------------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Viewport coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getClientByCanvas(point)\n\nConvert canvas coordinates to browser client coordinates.\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the browser client coordinate system\n\n### Graph.getViewportByCanvas(point)\n\nConvert canvas coordinates to viewport coordinates.\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the viewport coordinate system\n","packages/site/docs/api/coordinate.zh.md":"---\ntitle: 坐标转换\norder: 12\n---\n\n## 坐标系概述\n\n在图可视化中，理解不同的坐标系及其转换关系至关重要。G6 中涉及多种坐标系，它们各自用于不同的场景：\n\n- **Client 坐标系**：浏览器视口左上角为原点，单位为像素。通常用于处理浏览器事件。\n- **Screen 坐标系**：屏幕左上角为原点，会受页面滚动影响。\n- **Page 坐标系**：文档左上角为原点，考虑文档滚动。\n- **Canvas 坐标系**：也称为世界坐标系，图形绘制和布局时使用的坐标系，画布元素左上角为原点。\n- **Viewport 坐标系**：视口坐标系，当前可见的画布区域，视口左上角为原点。视口通过平移、缩放等操作，可以观察不同的 Canvas 区域。\n\n在这个[示例](https://g.antv.antgroup.com/zh/examples/canvas/canvas-basic#coordinates)中，移动鼠标可以看到鼠标所在位置在各个坐标系下的值：\n\n![坐标系关系图](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\n当画布没有发生平移和缩放时，Viewport 坐标系与 Canvas 坐标系重合。随着用户的交互（如拖拽画布、缩放），两个坐标系会出现偏移。\n\nG6 提供了一系列 API 用于在不同坐标系之间进行转换，下面将详细介绍这些 API。\n\n## API 参考\n\n### Graph.getCanvasByClient(point)\n\n将浏览器坐标（客户端坐标）转换为画布坐标。\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述         | 类型                                         | 默认值 | 必选 |\n| ----- | ------------ | -------------------------------------------- | ------ | ---- |\n| point | 浏览器坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getCanvasByViewport(point)\n\n将视口坐标转换为画布坐标。\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 视口坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getClientByCanvas(point)\n\n将画布坐标转换为浏览器客户端坐标。\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 浏览器客户端坐标系下的坐标点\n\n### Graph.getViewportByCanvas(point)\n\n将画布坐标转换为视口坐标。\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 视口坐标系下的坐标点\n","packages/site/docs/api/data.en.md":"---\ntitle: Data\norder: 0\n---\n\n## Overview of Data Operations\n\nG6 provides a comprehensive [data](/en/manual/data) operation API, covering the complete lifecycle of graph data from query, modification to update.\n\n## API Reference\n\n### Graph.getData()\n\nGet the complete data of the graph.\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**Return Value**:\n\n- **Type**: [GraphData](#graphdata)\n\n- **Description**: Returns the complete graph data containing all nodes, edges, and combo data\n\n**Example**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('Node data:', graphData.nodes);\nconsole.log('Edge data:', graphData.edges);\nconsole.log('Combo data:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\nGet node data, supporting three calling methods.\n\n```typescript\n// Get all node data\ngetNodeData(): NodeData[];\n\n// Get single node data\ngetNodeData(id: ID): NodeData;\n\n// Get multiple node data\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Node ID       | string   | -       |          |\n| ids       | Node ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **Description**: Returns the specified node data or node data array\n\n**Example**:\n\n```typescript\n// Get all nodes\nconst nodes = graph.getNodeData();\n\n// Get single node\nconst node = graph.getNodeData('node1');\nconsole.log('Node position:', node.style.x, node.style.y);\n\n// Get multiple nodes\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\nGet edge data, supporting three calling methods.\n\n```typescript\n// Get all edge data\ngetEdgeData(): EdgeData[];\n\n// Get single edge data\ngetEdgeData(id: ID): EdgeData;\n\n// Get multiple edge data\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Edge ID       | string   | -       |          |\n| ids       | Edge ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **Description**: Returns the specified edge data or edge data array\n\n**Example**:\n\n```typescript\n// Get all edges\nconst edges = graph.getEdgeData();\n\n// Get single edge\nconst edge = graph.getEdgeData('edge1');\nconsole.log('Edge source and target:', edge.source, edge.target);\n\n// Get multiple edges\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\nGet combo data, supporting three calling methods.\n\n```typescript\n// Get all combo data\ngetComboData(): ComboData[];\n\n// Get single combo data\ngetComboData(id: ID): ComboData;\n\n// Get multiple combo data\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter | Description    | Type     | Default | Required |\n| --------- | -------------- | -------- | ------- | -------- |\n| id        | Combo ID       | string   | -       |          |\n| ids       | Combo ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **Description**: Returns the specified combo data or combo data array\n\n**Example**:\n\n```typescript\n// Get all combos\nconst combos = graph.getComboData();\n\n// Get single combo\nconst combo = graph.getComboData('combo1');\nconsole.log('Nodes in combo:', combo.children);\n\n// Get multiple combos\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\nGet single element data, supporting two calling methods.\n\n⚠️ **Note**: This API directly gets the data of the element without considering the element type.\n\n```typescript\n// Get single element data\ngetElementData(id: ID): ElementDatum;\n\n// Get multiple element data\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type     | Default | Required |\n| --------- | ---------------- | -------- | ------- | -------- |\n| id        | Element ID       | string   | -       |          |\n| ids       | Element ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: ElementDatum \\| ElementDatum[]\n- **Description**: Directly gets the data of the element without considering the element type\n\n**Example**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('Element data:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('Multiple element data:', elements);\n```\n\n### Graph.getElementDataByState()\n\nGet element data in a specified state, supporting three calling methods.\n\n```typescript\n// Get node data in a specified state\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// Get edge data in a specified state\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// Get combo data in a specified state\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter   | Description  | Type                              | Default | Required |\n| ----------- | ------------ | --------------------------------- | ------- | -------- |\n| elementType | Element type | `'node'` \\| `'edge'` \\| `'combo'` | -       | ✓        |\n| state       | State        | string                            | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **Description**: Returns node data, edge data, or combo data in the specified state\n\n**Example**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('Selected nodes:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('Selected edges:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('Selected combos:', selectedCombos);\n```\n\n**Built-in States**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\nGet the data of neighbor nodes of a node or combo.\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[]\n- **Description**: Returns neighbor node data\n\n**Example**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('Neighbor nodes:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\nGet the data of edges related to a node or combo.\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type                          | Default | Required |\n| --------- | ---------------- | ----------------------------- | ------- | -------- |\n| id        | Node or combo ID | string                        | -       | ✓        |\n| direction | Edge direction   | `'in'` \\| `'out'` \\| `'both'` | -       |          |\n\n**Return Value**:\n\n- **Type**: EdgeData[]\n- **Description**: Returns the data of edges related to the specified node or combo\n\n**Example**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('Related edges:', relatedEdges);\n```\n\n### Graph.getParentData()\n\nGet the data of the parent element of a node or combo.\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       |          |\n\n**Return Value**:\n\n- **Type**: NodeData \\| ComboData \\| undefined\n- **Description**: Returns the parent element data, or undefined if it does not exist\n\n**Example**:\n\n```typescript\n// Get the parent node in a tree graph\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// Get the parent combo in a combo\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\nGet the data of child elements of a node or combo.\n\n```typescript\ngetChildrenData(id: ID): (NodeData \\| ComboData)[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: (NodeData \\| ComboData)[]\n- **Description**: Returns an array of child element data\n\n**Note**:\n\n- **Querying combo's child elements**: If the id corresponds to a combo element, you can directly use this API to get all its child elements.\n- **Querying node's child elements**: If the id corresponds to a node, only when the graph data is a tree structure (i.e., the node data maintains a `children` field, and `children` is an array of child node IDs for that node), can you use this API to get the child elements of that node. Otherwise, an empty array is returned.\n\n**Example**:\n\n```typescript\n// Get the child elements of a combo\nconst children = graph.getChildrenData('combo1');\nconsole.log('Number of child nodes:', children.length);\n\n// Process each child element\nchildren.forEach((child) => {\n  console.log('Child element ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\nGet the data of all ancestor elements of a node or combo.\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of ancestor element data, ordered from parent to root\n\n**Example**:\n\n```typescript\n// Get all ancestor nodes in a tree graph\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  'Ancestor node path:',\n  treeAncestors.map((node) => node.id),\n);\n\n// Get all parent combos in a combo\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\nGet the data of all descendant elements of a node or combo.\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of descendant element data\n\n**Example**:\n\n```typescript\n// Get all descendants of a node\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('Number of descendants:', descendants.length);\n\n// Process all descendant elements\ndescendants.forEach((descendant) => {\n  console.log('Descendant element ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\nSet the complete data of the graph.\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                        | Default | Required |\n| --------- | ----------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | New graph data or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Directly set data\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// Use functional incremental update: get current graph data and return new graph data\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\nAdd new element data.\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                              | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Graph data to add or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\nAdd new node data.\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Node data to add or a function returning node data | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single node\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: 'Node 1' },\n  },\n]);\n\n// Add multiple nodes\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// Functional addition\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\nAdd new edge data.\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                          | Default | Required |\n| --------- | -------------------------------------------------- | ------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to add or a function returning edge data | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single edge\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: 'Relation',\n    },\n  },\n]);\n\n// Add multiple edges\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// Functional addition\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\nAdd new combo data.\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                          | Type                                                            | Default | Required |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to add or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\nAdd child node data to a tree graph node.\n\n⚠️ **Note**: Use addNodeData / addComboData methods to add child nodes to a combo.\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**Parameters**:\n\n| Parameter    | Description     | Type                    | Default | Required |\n| ------------ | --------------- | ----------------------- | ------- | -------- |\n| parentId     | Parent node ID  | string                  | -       | ✓        |\n| childrenData | Child node data | [NodeData](#nodedata)[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\nRemove element data.\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                               | Type                                               | Default | Required |\n| --------- | --------------------------------------------------------- | -------------------------------------------------- | ------- | -------- |\n| ids       | Element IDs to remove or a function returning element IDs | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\nRemove node data.\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Node IDs to remove or a function returning node IDs | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\nRemove edge data.\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Edge IDs to remove or a function returning edge IDs | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\nRemove combo data.\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                            | Default | Required |\n| --------- | ----------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Combo IDs to remove or a function returning combo IDs | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\nUpdate element data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                 | Type                                                                             | Default | Required |\n| --------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Element data to update or a function returning element data | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\nUpdate node data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                           | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------- | ------- | -------- |\n| data      | Node data to update or a function returning node data | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\nUpdate edge data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                                                                                         | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to update or a function returning edge data | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\nUpdate combo data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                             | Type                                                            | Default | Required |\n| --------- | ------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to update or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\nDetermine if an node exists\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n| Parameter | Description | Type | Default | Required |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id | Node ID to be judged | [ID](#id) | - | ✓ |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\nDetermine if an edge exists\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description          | Type      | Default | Required |\n| --------- | -------------------- | --------- | ------- | -------- |\n| id        | Edge ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\nDetermine if combo exists\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description           | Type      | Default | Required |\n| --------- | --------------------- | --------- | ------- | -------- |\n| id        | Combo ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## Type Definitions\n\n### ID\n\nElement ID type.\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\nMultiple element ID type.\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 graph data type.\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\nNode data type.\n\n```typescript\ninterface NodeData {\n  id: string; // Node ID\n  type?: string; // Node type\n  data?: Record<string, any>; // Node data\n  style?: Record<string, any>; // Node style\n  states?: string[]; // Initial node states\n  combo?: string; // Belonging combo\n  children?: string[]; // Array of child node IDs\n}\n```\n\nFor detailed type definitions, please refer to [Node Data](/en/manual/data#nodedata).\n\n### EdgeData\n\nEdge data type.\n\n```typescript\ninterface EdgeData {\n  source: string; // Source ID\n  target: string; // Target ID\n  id?: string; // Edge ID\n  type?: string; // Edge type\n  data?: Record<string, any>; // Edge data\n  style?: Record<string, any>; // Edge style\n  states?: string[]; // Initial edge states\n}\n```\n\nFor detailed type definitions, please refer to [Edge Data](/en/manual/data#edgedata).\n\n### ComboData\n\nCombo data type.\n\n```typescript\ninterface ComboData {\n  id: string; // Combo ID\n  type?: string; // Combo type\n  data?: Record<string, any>; // Combo data\n  style?: Record<string, any>; // Combo style\n  states?: string[]; // Initial combo states\n  combo?: string; // Parent combo ID\n}\n```\n\nFor detailed type definitions, please refer to [Combo Data](/en/manual/data#combodata).\n","packages/site/docs/api/data.zh.md":"---\ntitle: 数据\norder: 0\n---\n\n## 数据操作概述\n\nG6 提供了一套全面的 [数据](/manual/data) 操作 API，覆盖了图数据从查询、修改到更新的完整生命周期。\n\n## API 参考\n\n### Graph.getData()\n\n获取图的完整数据。\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**返回值**:\n\n- **类型**: [GraphData](#graphdata)\n\n- **描述**: 返回包含所有节点、边和组合数据的完整图数据\n\n**示例**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('节点数据:', graphData.nodes);\nconsole.log('边数据:', graphData.edges);\nconsole.log('组合数据:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\n获取节点数据，支持三种调用方式。\n\n```typescript\n// 获取所有节点数据\ngetNodeData(): NodeData[];\n\n// 获取单个节点数据\ngetNodeData(id: ID): NodeData;\n\n// 批量获取多个节点数据\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 节点 ID      | string   | -      |      |\n| ids  | 节点 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **描述**: 返回指定的节点数据或节点数据数组\n\n**示例**:\n\n```typescript\n// 获取所有节点\nconst nodes = graph.getNodeData();\n\n// 获取单个节点\nconst node = graph.getNodeData('node1');\nconsole.log('节点位置:', node.style.x, node.style.y);\n\n// 获取多个节点\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\n获取边数据，支持三种调用方式。\n\n```typescript\n// 获取所有边数据\ngetEdgeData(): EdgeData[];\n\n// 获取单条边数据\ngetEdgeData(id: ID): EdgeData;\n\n// 批量获取多条边数据\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**参数**:\n\n| 参数 | 描述       | 类型     | 默认值 | 必选 |\n| ---- | ---------- | -------- | ------ | ---- |\n| id   | 边 ID      | string   | -      |      |\n| ids  | 边 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **描述**: 返回指定的边数据或边数据数组\n\n**示例**:\n\n```typescript\n// 获取所有边\nconst edges = graph.getEdgeData();\n\n// 获取单条边\nconst edge = graph.getEdgeData('edge1');\nconsole.log('边的起点和终点:', edge.source, edge.target);\n\n// 获取多条边\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\n获取组合数据,支持三种调用方式。\n\n```typescript\n// 获取所有组合数据\ngetComboData(): ComboData[];\n\n// 获取单个组合数据\ngetComboData(id: ID): ComboData;\n\n// 批量获取多个组合数据\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 组合 ID      | string   | -      |      |\n| ids  | 组合 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **描述**: 返回指定的组合数据或组合数据数组\n\n**示例**:\n\n```typescript\n// 获取所有组合\nconst combos = graph.getComboData();\n\n// 获取单个组合\nconst combo = graph.getComboData('combo1');\nconsole.log('组合包含的节点:', combo.children);\n\n// 获取多个组合\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\n获取单个元素数据，支持两种调用方式。\n\n⚠️ **注意**: 此 API 直接获取元素的数据而不必考虑元素类型。\n\n```typescript\n// 获取单个元素数据\ngetElementData(id: ID): ElementDatum;\n\n// 批量获取多个元素数据\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 元素 ID      | string   | -      |      |\n| ids  | 元素 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: ElementDatum \\| ElementDatum[]\n- **描述**: 直接获取元素的数据而不必考虑元素类型\n\n**示例**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('元素数据:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('多个元素数据:', elements);\n```\n\n### Graph.getElementDataByState()\n\n获取指定状态下的元素数据，支持三种调用方式。\n\n```typescript\n// 获取指定状态下的节点数据\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// 获取指定状态下的边数据\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// 获取指定状态下的组合数据\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**参数**:\n\n| 参数        | 描述     | 类型                              | 默认值 | 必选 |\n| ----------- | -------- | --------------------------------- | ------ | ---- |\n| elementType | 元素类型 | `'node'` \\| `'edge'` \\| `'combo'` | -      | ✓    |\n| state       | 状态     | string                            | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **描述**: 返回指定状态下的节点数据、边数据或组合数据\n\n**示例**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('选中的节点:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('选中的边:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('选中的组合:', selectedCombos);\n```\n\n**内置状态**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\n获取节点或组合的一跳邻居节点数据。\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[]\n- **描述**: 返回邻居节点数据\n\n**示例**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('邻居节点:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\n获取节点或组合关联边的数据。\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**参数**:\n\n| 参数      | 描述            | 类型                          | 默认值 | 必选 |\n| --------- | --------------- | ----------------------------- | ------ | ---- |\n| id        | 节点或组合的 ID | string                        | -      | ✓    |\n| direction | 边的方向        | `'in'` \\| `'out'` \\| `'both'` | -      |      |\n\n**返回值**:\n\n- **类型**: EdgeData[]\n- **描述**: 返回与指定节点或组合关联的边数据\n\n**示例**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('关联边:', relatedEdges);\n```\n\n### Graph.getParentData()\n\n获取节点或组合的父元素数据。\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      |      |\n\n**返回值**:\n\n- **类型**: NodeData \\| ComboData \\| undefined\n- **描述**: 返回父元素数据,如果不存在则返回 undefined\n\n**示例**:\n\n```typescript\n// 获取树图中节点的父节点\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// 获取组合中节点的父组合\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\n获取节点或组合的子元素数据。\n\n```typescript\ngetChildrenData(id: ID):(NodeData \\| ComboData)[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: (NodeData \\| ComboData)[]\n- **描述**: 返回子元素数据数组\n\n**注意**:\n\n- **查询 combo 的子元素**：如果 id 对应的是 combo 元素，可以直接通过此 API 获取其所有子元素。\n- **查询节点的子元素**：如果 id 对应的是节点，只有当图数据为树结构（即节点数据中维护有 `children` 字段，且 `children` 为该节点的子节点 ID 数组）时，才能通过此 API 获取到该节点的子元素。否则返回空数组。\n\n**示例**:\n\n```typescript\n// 获取组合的子元素\nconst children = graph.getChildrenData('combo1');\nconsole.log('子节点数量:', children.length);\n\n// 处理每个子元素\nchildren.forEach((child) => {\n  console.log('子元素ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\n获取节点或组合的所有祖先元素数据。\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回祖先元素数据数组，从父节点到根节点的顺序排列\n\n**示例**:\n\n```typescript\n// 获取树图中节点的所有祖先节点\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  '祖先节点路径:',\n  treeAncestors.map((node) => node.id),\n);\n\n// 获取组合中节点的所有父组合\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\n获取节点或组合的所有后代元素数据。\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回后代元素数据数组\n\n**示例**:\n\n```typescript\n// 获取节点的所有后代\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('后代数量:', descendants.length);\n\n// 处理所有后代元素\ndescendants.forEach((descendant) => {\n  console.log('后代元素ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\n设置图的完整数据。\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                           | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 新的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 直接设置数据\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// 使用函数式增量更新：获取当前图数据，并返回新的图数据\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\n新增元素数据。\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 需要添加的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\n新增节点数据。\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 要添加的节点数据或返回节点数据的函数 | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: '节点 1' },\n  },\n]);\n\n// 批量添加节点\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// 函数式添加\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\n新增边数据。\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                          | 默认值 | 必选 |\n| ---- | -------------------------------- | ------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的边数据或返回边数据的函数 | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单条边\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: '关系',\n    },\n  },\n]);\n\n// 批量添加边\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// 函数式添加\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\n新增组合数据。\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\n为树图节点添加子节点数据。\n\n⚠️ **注意**: 为组合添加子节点使用 addNodeData / addComboData 方法。\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**参数**:\n\n| 参数         | 描述       | 类型                    | 默认值 | 必选 |\n| ------------ | ---------- | ----------------------- | ------ | ---- |\n| parentId     | 父节点 ID  | string                  | -      | ✓    |\n| childrenData | 子节点数据 | [NodeData](#nodedata)[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\n删除元素数据。\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                               | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的元素 ID 或返回元素 ID 的函数 | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\n删除节点数据。\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的节点 ID 或返回节点 ID 的函数 | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\n删除边数据。\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                            | 默认值 | 必选 |\n| ---- | -------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的边 ID 或返回边 ID 的函数 | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\n删除组合数据。\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的组合 ID 或返回组合 ID 的函数 | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\n更新元素数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                                             | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的元素数据或返回元素数据的函数 | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\n更新节点数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                           | 默认值 | 必选 |\n| ---- | ------------------------------------ | ---------------------------------------------- | ------ | ---- |\n| data | 要更新的节点数据或返回节点数据的函数 | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\n更新边数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                                                                                         | 默认值 | 必选 |\n| ---- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的边数据或返回边数据的函数 | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\n更新组合数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\n判断节点是否存在\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                 | 类型      | 默认值 | 必选 |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的节点id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\n判断边是否存在\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述               | 类型      | 默认值 | 必选 |\n| ---- | ------------------ | --------- | ------ | ---- |\n| id   | 需要进行判断的边id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\n判断combo是否存在\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                      | 类型      | 默认值 | 必选 |\n| ---- | ------------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的combo组合id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## 类型定义\n\n### ID\n\n元素 ID 类型。\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\n多个元素 ID 类型。\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 图数据类型。\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\n节点数据类型。\n\n```typescript\ninterface NodeData {\n  id: string; // 节点 ID\n  type?: string; // 节点类型\n  data?: Record<string, any>; // 节点数据\n  style?: Record<string, any>; // 节点样式\n  states?: string[]; // 节点初始状态\n  combo?: string; // 所属组合\n  children?: string[]; // 子节点 ID 数组\n}\n```\n\n详细类型定义请参考 [节点数据](/manual/data#节点数据nodedata)。\n\n### EdgeData\n\n边数据类型。\n\n```typescript\ninterface EdgeData {\n  source: string; // 起点 ID\n  target: string; // 终点 ID\n  id?: string; // 边 ID\n  type?: string; // 边类型\n  data?: Record<string, any>; // 边数据\n  style?: Record<string, any>; // 边样式\n  states?: string[]; // 边初始状态\n}\n```\n\n详细类型定义请参考 [边数据](/manual/data#边数据edgedata)。\n\n### ComboData\n\n组合数据类型。\n\n```typescript\ninterface ComboData {\n  id: string; // 组合 ID\n  type?: string; // 组合类型\n  data?: Record<string, any>; // 组合数据\n  style?: Record<string, any>; // 组合样式\n  states?: string[]; // 组合初始状态\n  combo?: string; // 父组合 ID\n}\n```\n\n详细类型定义请参考 [组合数据](/manual/data#组合数据combodata)。\n","packages/site/docs/api/element.en.md":"---\ntitle: Element Operations\norder: 1\n---\n\n## Overview of Element Operations\n\nThe [Element](/en/manual/element/overview) operation API in G6 allows you to control the behavior and attributes of elements such as nodes, edges, and Combos in the graph. These APIs can be used for:\n\n1. **Element State Management**: Set, update, or remove the state of elements\n2. **Element Display Control**: Control the z-index and visibility of elements\n3. **Element Collapse/Expand**: Operate the collapse/expand state of collapsible elements\n4. **Element Position Operations**: Move and align element positions\n5. **Element Focus**: Focus the viewport on specific elements\n\nThrough these operations, you can achieve rich interactive effects and visual presentations.\n\n## API Reference\n\n### Graph.getElementPosition(id)\n\nGet the position of an element.\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Returns the coordinates of the element\n\n**Example**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\nGet the rendering bounding box of the element itself and its child nodes in the world coordinate system.\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [AABB](#aabb)\n- **Description**: Returns the rendering bounding box of the element\n\n### Graph.getElementRenderStyle(id)\n\nGet the rendering style of an element.\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Record<string, any>\n- **Description**: Returns the rendering style of the element\n\n### Graph.getElementState(id)\n\nGet the state of an element.\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [State](#state)[]\n- **Description**: Returns the state of the element\n\n### Graph.getElementType(id)\n\nGet the type of an element.\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: string\n- **Description**: Returns the type of the element\n\n### Graph.getElementVisibility(id)\n\nGet the visibility of an element.\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden';\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: 'visible' | 'hidden'\n- **Description**: Returns the visibility of the element\n\n### Graph.getElementZIndex(id)\n\nGet the z-index of an element.\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: number\n- **Description**: Returns the z-index of the element\n\n### Graph.setElementState(id, state, options)\n\nSet the state of an element, supporting two calling methods:\n\n```typescript\n// Set the state of a single element\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// Set the state of multiple elements\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element State Setting**\n\n| Parameter | Description       | Type            | Default | Required |\n| --------- | ----------------- | --------------- | ------- | -------- | --- |\n| id        | Element ID to set | string          | -       | ✓        |\n| state     | State to set      | [State](#state) | State[] | -        | ✓   |\n| animation | Enable animation  | boolean         | -       |          |\n\n**Batch Element State Setting**\n\n| Parameter | Description                    | Type                       | Default  | Required |\n| --------- | ------------------------------ | -------------------------- | -------- | -------- | --- |\n| state     | Mapping of element ID to state | Record<ID, [State](#state) | State[]> | -        | ✓   |\n| animation | Enable animation               | boolean                    | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the state setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the state of a single element\nawait graph.setElementState('node1', 'selected');\n\n// Set the state of multiple elements\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\nSet the visibility of an element, supporting two calling methods:\n\n```typescript\n// Set the visibility of a single element\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// Set the visibility of multiple elements\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Visibility Setting**\n\n| Parameter  | Description       | Type      | Default  | Required |\n| ---------- | ----------------- | --------- | -------- | -------- | --- |\n| id         | Element ID to set | string    | -        | ✓        |\n| visibility | Visibility to set | 'visible' | 'hidden' | -        | ✓   |\n| animation  | Enable animation  | boolean   | -        |          |\n\n**Batch Element Visibility Setting**\n\n| Parameter  | Description                         | Type                 | Default   | Required |\n| ---------- | ----------------------------------- | -------------------- | --------- | -------- | --- |\n| visibility | Mapping of element ID to visibility | Record<ID, 'visible' | 'hidden'> | -        | ✓   |\n| animation  | Enable animation                    | boolean              | -         |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the visibility setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the visibility of a single element\nawait graph.setElementVisibility('node1', 'hidden');\n\n// Set the visibility of multiple elements\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\nSet the z-index of an element, supporting two calling methods:\n\n```typescript\n// Set the z-index of a single element\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// Set the z-index of multiple elements\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Z-Index Setting**\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n| zIndex    | Z-Index     | number | -       | ✓        |\n\n**Batch Element Z-Index Setting**\n\n| Parameter | Description                      | Type               | Default | Required |\n| --------- | -------------------------------- | ------------------ | ------- | -------- |\n| zIndex    | Mapping of element ID to z-index | Record<ID, number> | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the z-index setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the z-index of a single element\nawait graph.setElementZIndex('node1', 10);\n\n// Set the z-index of multiple elements\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\nSet the node style mapping, i.e., the value of `options.node`.\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| node      | Node configuration | [NodeOptions](/en/manual/element/node/overview) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Set the fill color of all nodes to red\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\nSet the edge style mapping, i.e., the value of `options.edge`.\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| edge      | Edge configuration | [EdgeOptions](/en/manual/element/edge/overview) | -       | ✓        |\n\n### Graph.setCombo(combo)\n\nSet the combo style mapping, i.e., the value of `options.combo`.\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description         | Type                                              | Default | Required |\n| --------- | ------------------- | ------------------------------------------------- | ------- | -------- |\n| combo     | Combo configuration | [ComboOptions](/en/manual/element/combo/overview) | -       | ✓        |\n\n### Graph.collapseElement(id, options)\n\nCollapse the specified element, usually used to collapse Combos or nodes with child elements.\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                     | Type    | Default                                                 | Required |\n| --------- | --------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to collapse                                          | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for collapsing nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the collapse operation is complete\n\n**Example**:\n\n```typescript\n// Simple collapse with default configuration\nawait graph.collapseElement('combo1');\n\n// Collapse with animation\ngraph.collapseElement('combo1', true);\n\n// Collapse while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\nExpand the specified element, usually used to expand previously collapsed Combos or nodes.\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                    | Type    | Default                                                 | Required |\n| --------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to expand                                           | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for expanding nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the expand operation is complete\n\n**Example**:\n\n```typescript\n// Simple expand with default configuration\nawait graph.expandElement('combo1');\n\n// Expand with animation\nawait graph.expandElement('combo1', true);\n\n// Expand while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\nBring the specified element to the front, making it appear above other overlapping elements.\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default  | Required |\n| --------- | ----------- | ------ | -------- | -------- | --- |\n| id        | Element ID  | string | string[] | -        | ✓   |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\n// Bring a node to the front\ngraph.frontElement('node1');\n\n// Bring multiple selected nodes to the front\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\nShow the specified element.\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the show operation is complete\n\n**Example**:\n\n```typescript\n// Show a single element\nawait graph.showElement('node1');\n\n// Show an element with animation\nawait graph.showElement('node1', true);\n\n// Show multiple elements\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\nHide the specified element.\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the hide operation is complete\n\n**Example**:\n\n```typescript\n// Hide an element without animation\nawait graph.hideElement('node1');\n\n// Hide an element with animation\nawait graph.hideElement('node1', true);\n\n// Hide multiple elements\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\nTranslate an element by a specified distance, supporting two calling methods:\n\n```typescript\n// Translate an element by a specified distance (relative translation)\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// Translate multiple elements by a specified distance (relative translation)\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Translation**\n\n| Parameter | Description                            | Type             | Default | Required |\n| --------- | -------------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                             | string           | -       | ✓        |\n| offset    | Relative translation distance [dx, dy] | [number, number] | -       | ✓        |\n| animation | Enable animation                       | boolean          | -       |          |\n\n**Batch Element Translation**\n\n| Parameter | Description                                   | Type                         | Default | Required |\n| --------- | --------------------------------------------- | ---------------------------- | ------- | -------- |\n| offsets   | Mapping of element ID to translation distance | Record<ID, [number, number]> | -       | ✓        |\n| animation | Enable animation                              | boolean                      | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the translation operation is complete\n\n**Example**:\n\n```typescript\n// Translate right by 100 pixels and down by 50 pixels\nawait graph.translateElementBy('node1', [100, 50]);\n\n// Translate with animation\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// Apply the same translation to multiple nodes\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\nMove an element to a specified position, supporting two calling methods:\n\n```typescript\n// Move an element to a specified position (absolute position)\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// Move multiple elements to specified positions (absolute position)\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Movement**\n\n| Parameter | Description                     | Type             | Default | Required |\n| --------- | ------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                      | string           | -       | ✓        |\n| position  | Target absolute position [x, y] | [number, number] | -       | ✓        |\n| animation | Enable animation                | boolean          | -       |          |\n\n**Batch Element Movement**\n\n| Parameter | Description                              | Type                             | Default | Required |\n| --------- | ---------------------------------------- | -------------------------------- | ------- | -------- |\n| positions | Mapping of element ID to target position | Record<string, [number, number]> | -       | ✓        |\n| animation | Enable animation                         | boolean                          | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the movement operation is complete\n\n**Example**:\n\n```typescript\n// Move a node to position (200, 300) on the canvas\nawait graph.translateElementTo('node1', [200, 300]);\n\n// Move with animation\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// Arrange a group of nodes neatly\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\nFocus on the specified element, centering it in the viewport.\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                         | Type                                                            | Default  | Required |\n| --------- | ----------------------------------- | --------------------------------------------------------------- | -------- | -------- | --- |\n| id        | One or more element IDs to focus on | string                                                          | string[] | -        | ✓   |\n| animation | Viewport animation configuration    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the focus operation is complete\n\n**Example**:\n\n```typescript\n// Focus on a single node\nawait graph.focusElement('node1');\n\n// Use custom animation configuration\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// Focus on multiple nodes\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## Type Definitions\n\n### CollapseExpandNodeOptions\n\nConfiguration options for collapsing or expanding elements.\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * Enable animation\n   */\n  animation?: boolean;\n  /**\n   * Ensure the position of expanded/collapsed nodes remains unchanged\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) is a fundamental concept in computer graphics.\n\n```typescript\ninterface AABB {\n  x: number; // x-coordinate of the top-left corner of the rectangle\n  y: number; // y-coordinate of the top-left corner of the rectangle\n  width: number; // Width of the rectangle\n  height: number; // Height of the rectangle\n}\n```\n\n### State\n\nElement state type.\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","packages/site/docs/api/element.zh.md":"---\ntitle: 元素操作\norder: 1\n---\n\n## 元素操作概述\n\nG6 中的 [元素](/manual/element/overview) 操作 API 允许您控制图中节点、边和组合(Combo)等元素的行为和属性。这些 API 可以用于：\n\n1. **元素状态管理**：设置、更新或移除元素的状态\n2. **元素显示控制**：控制元素的层级、可见性\n3. **元素展开/收起**：操作可折叠元素的展开/收起状态\n4. **元素位置操作**：移动、对齐元素位置\n5. **元素聚焦**：将视口聚焦到特定元素\n\n通过这些操作，您可以实现丰富的交互效果和视觉呈现。\n\n## API 参考\n\n### Graph.getElementPosition(id)\n\n获取元素位置。\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 返回元素的坐标位置\n\n**示例**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\n获取元素自身以及子节点在世界坐标系下的渲染包围盒。\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [AABB](#aabb)\n- **描述**: 返回元素的渲染包围盒\n\n### Graph.getElementRenderStyle(id)\n\n获取元素的渲染样式。\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Record\\<string, any\\>\n- **描述**: 返回元素的渲染样式\n\n### Graph.getElementState(id)\n\n获取元素的状态。\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [State](#state)[]\n- **描述**: 返回元素的状态\n\n### Graph.getElementType(id)\n\n获取元素类型。\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: string\n- **描述**: 返回元素的类型\n\n### Graph.getElementVisibility(id)\n\n获取元素可见性。\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden' ;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: 'visible' | 'hidden'\n- **描述**: 返回元素的可见性\n\n### Graph.getElementZIndex(id)\n\n获取元素层级。\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: number\n- **描述**: 返回元素的层级\n\n### Graph.setElementState(id, state, options)\n\n设置元素状态，支持两种调用方式：\n\n```typescript\n// 设置单个元素状态\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// 批量设置元素状态\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素状态设置**\n\n| 参数      | 描述                | 类型                       | 默认值 | 必选 |\n| --------- | ------------------- | -------------------------- | ------ | ---- |\n| id        | 要设置状态的元素 ID | string                     | -      | ✓    |\n| state     | 要设置的状态        | [State](#state) \\| State[] | -      | ✓    |\n| animation | 是否启用动画        | boolean                    | -      |      |\n\n**批量元素状态设置**\n\n| 参数      | 描述               | 类型                                   | 默认值 | 必选 |\n| --------- | ------------------ | -------------------------------------- | ------ | ---- |\n| state     | 元素ID到状态的映射 | Record<ID, [State](#state) \\| State[]> | -      | ✓    |\n| animation | 是否启用动画       | boolean                                | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，状态设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素状态\nawait graph.setElementState('node1', 'selected');\n\n// 设置多个元素状态\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\n设置元素的可见性，支持两种调用方式：\n\n```typescript\n// 设置单个元素可见性\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// 批量设置元素可见性\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素可见性设置**\n\n| 参数       | 描述                  | 类型                      | 默认值 | 必选 |\n| ---------- | --------------------- | ------------------------- | ------ | ---- |\n| id         | 要设置可见性的元素 ID | string                    | -      | ✓    |\n| visibility | 要设置的可见性        | `'visible'` \\| `'hidden'` | -      | ✓    |\n| animation  | 是否启用动画          | boolean                   | -      |      |\n\n**批量元素可见性设置**\n\n| 参数       | 描述                 | 类型                                  | 默认值 | 必选 |\n| ---------- | -------------------- | ------------------------------------- | ------ | ---- |\n| visibility | 元素ID到可见性的映射 | Record<ID, `'visible'` \\| `'hidden'`> | -      | ✓    |\n| animation  | 是否启用动画         | boolean                               | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，可见性设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素可见性\nawait graph.setElementVisibility('node1', 'hidden');\n\n// 设置多个元素可见性\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\n设置元素的层级，有两种调用方式：\n\n```typescript\n// 设置单个元素层级\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// 批量设置元素层级\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**参数**:\n\n**单个元素层级设置**\n\n| 参数   | 描述    | 类型   | 默认值 | 必选 |\n| ------ | ------- | ------ | ------ | ---- |\n| id     | 元素 ID | string | -      | ✓    |\n| zIndex | 层级    | number | -      | ✓    |\n\n**批量元素层级设置**\n\n| 参数   | 描述               | 类型               | 默认值 | 必选 |\n| ------ | ------------------ | ------------------ | ------ | ---- |\n| zIndex | 元素ID到层级的映射 | Record<ID, number> | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，层级设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素层级\nawait graph.setElementZIndex('node1', 10);\n\n// 设置多个元素层级\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\n设置节点样式映射。即 `options.node` 的值。\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述     | 类型                                         | 默认值 | 必选 |\n| ---- | -------- | -------------------------------------------- | ------ | ---- |\n| node | 节点配置 | [NodeOptions](/manual/element/node/overview) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 设置所有的节点填充色为红色\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\n设置边样式映射。即 `options.edge` 的值。\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述   | 类型                                         | 默认值 | 必选 |\n| ---- | ------ | -------------------------------------------- | ------ | ---- |\n| edge | 边配置 | [EdgeOptions](/manual/element/edge/overview) | -      | ✓    |\n\n### Graph.setCombo(combo)\n\n设置组合样式映射。即 `options.combo` 的值。\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**参数**:\n\n| 参数  | 描述     | 类型                                           | 默认值 | 必选 |\n| ----- | -------- | ---------------------------------------------- | ------ | ---- |\n| combo | 组合配置 | [ComboOptions](/manual/element/combo/overview) | -      | ✓    |\n\n### Graph.collapseElement(id, options)\n\n收起指定元素，通常用于折叠组合(Combo)或具有子元素的节点。\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要收起的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或收起节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，收起操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单收起，使用默认配置\nawait graph.collapseElement('combo1');\n\n// 收起并启用动画\nawait graph.collapseElement('combo1', true);\n\n// 收起并保证展开/收起的节点位置不变\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\n展开指定元素，通常用于展开先前收起的组合(Combo)或节点。\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要展开的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或展开节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，展开操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单展开，使用默认配置\nawait graph.expandElement('combo1');\n\n// 展开并启用动画\nawait graph.expandElement('combo1', true);\n\n// 展开并保证展开/收起的节点位置不变\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\n将指定元素置于最顶层，使其显示在其他重叠元素之上。\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型               | 默认值 | 必选 |\n| ---- | ------- | ------------------ | ------ | ---- |\n| id   | 元素 ID | string \\| string[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\n// 将节点置于最顶层\ngraph.frontElement('node1');\n\n// 对于选中的多个节点，都置于最顶层\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\n显示指定元素。\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，显示操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 显示单个元素\nawait graph.showElement('node1');\n\n// 带动画显示元素\nawait graph.showElement('node1', true);\n\n// 显示多个元素\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\n隐藏指定元素。\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，隐藏操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 无动画隐藏元素\nawait graph.hideElement('node1');\n\n// 带动画隐藏元素\nawait graph.hideElement('node1', true);\n\n// 隐藏多个元素\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\n相对平移元素指定距离，支持两种调用方式：\n\n```typescript\n// 将元素平移指定距离（相对平移）\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素平移指定距离（相对平移）\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素平移**\n\n| 参数      | 描述                    | 类型             | 默认值 | 必选 |\n| --------- | ----------------------- | ---------------- | ------ | ---- |\n| id        | 要平移的元素 ID         | string           | -      | ✓    |\n| offset    | 平移的相对距离 [dx, dy] | [number, number] | -      | ✓    |\n| animation | 是否启用动画            | boolean          | -      |      |\n\n**批量元素平移**\n\n| 参数      | 描述                   | 类型                         | 默认值 | 必选 |\n| --------- | ---------------------- | ---------------------------- | ------ | ---- |\n| offsets   | 元素ID到平移距离的映射 | Record<ID, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                      | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，平移操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 向右平移100像素，向下平移50像素\nawait graph.translateElementBy('node1', [100, 50]);\n\n// 带动画平移\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// 对多个节点应用相同的平移\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\n将元素移动到指定位置，支持两种调用方式：\n\n```typescript\n// 将元素移动到指定位置（绝对位置）\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素移动到指定位置（绝对位置）\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素移动**\n\n| 参数      | 描述                | 类型             | 默认值 | 必选 |\n| --------- | ------------------- | ---------------- | ------ | ---- |\n| id        | 要移动的元素 ID     | string           | -      | ✓    |\n| position  | 目标绝对位置 [x, y] | [number, number] | -      | ✓    |\n| animation | 是否启用动画        | boolean          | -      |      |\n\n**批量元素移动**\n\n| 参数      | 描述                   | 类型                             | 默认值 | 必选 |\n| --------- | ---------------------- | -------------------------------- | ------ | ---- |\n| positions | 元素ID到目标位置的映射 | Record<string, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                          | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，移动操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 将节点移动到画布的 (200, 300) 位置\nawait graph.translateElementTo('node1', [200, 300]);\n\n// 带动画移动\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// 将一组节点整齐排列\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\n聚焦到指定元素，使元素居中于视口。\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述                      | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| id        | 要聚焦的一个或多个元素 ID | string \\| string[]                                              | -      | ✓    |\n| animation | 视口动画配置              | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，聚焦操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 聚焦到单个节点\nawait graph.focusElement('node1');\n\n// 使用自定义动画配置\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// 聚焦到多个节点\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## 类型定义\n\n### CollapseExpandNodeOptions\n\n收起或展开元素的配置选项。\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * 是否使用动画\n   */\n  animation?: boolean;\n  /**\n   * 保证展开/收起的节点位置不变\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) 是\"轴对齐包围盒\"的缩写，是计算机图形学中的一个基础概念。\n\n```typescript\ninterface AABB {\n  x: number; // 矩形左上角的 x 坐标\n  y: number; // 矩形左上角的 y 坐标\n  width: number; // 矩形宽度\n  height: number; // 矩形高度\n}\n```\n\n### State\n\n元素状态类型。\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","packages/site/docs/api/event.en.md":"---\ntitle: Event Listening\norder: 11\n---\n\n## Overview of the Event System\n\nG6 provides a powerful event mechanism that allows you to respond to various interactive behaviors occurring in the chart, such as node clicks, edge hovers, canvas drags, etc. Through the event system, you can implement complex interactive logic to enhance user experience.\n\n### Event Categories\n\nEvents in G6 can be broadly categorized into the following types:\n\n1. **Element Events**: Events related to nodes, edges, and Combos, such as `node:click`, `edge:mouseenter`\n2. **Canvas Events**: Events related to the entire canvas, such as `canvas:drag`, `canvas:wheel`\n3. **Lifecycle Events**: Events related to the chart lifecycle, such as `beforerender`, `afterrender`\n\n### Event Naming Convention\n\nG6 events follow the `[object]:[event]` format, for example:\n\n- `node:click` - Node click event\n- `edge:mouseenter` - Mouse enters edge event\n- `canvas:drag` - Canvas drag event\n\n## Best Practice: Using Constant Enums\n\nG6 provides a complete set of event constant enums, and it is **strongly recommended** to use these constants instead of directly using string event names:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// Use constant enums to listen to events\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**Advantages**:\n\n- Type safety, avoiding string spelling errors\n- Provides intelligent code hints and auto-completion\n\n## API Reference\n\n### Graph.on(eventName, callback, once)\n\nListen to a specified event and execute a callback function when the event is triggered.\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n| once      | Whether to listen only once                            | boolean            | -       |          |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Listen to node click event\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // Get the ID of the clicked node\n  console.log(`Node ${target.id} was clicked`);\n\n  // Get node data\n  const nodeData = graph.getNodeData(target.id);\n  console.log('Node data:', nodeData);\n\n  // Modify node state\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen to edge mouse enter event\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// Listen to canvas drag event\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('Canvas is being dragged');\n});\n```\n\n### Graph.once(eventName, callback)\n\nListen to an event once, and automatically remove the listener after the event is triggered once.\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// Listen to the chart's first load completion event, executed only once\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('Chart rendered for the first time');\n  // Execute one-time initialization operations\n  highlightImportantNodes();\n});\n\n// Wait for the user to click a node for the first time and then perform operations\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('User clicked a node for the first time:', evt.target.id);\n  showTutorialTip('You can drag nodes to change their position');\n});\n```\n\n### Graph.off()\n\nRemove all event listeners.\n\n```typescript\noff(): this;\n```\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\n// Remove all event listeners\ngraph.off();\nconsole.log('All event listeners have been removed');\n```\n\n### Graph.off(eventName)\n\nRemove all listeners of a specified event type.\n\n```typescript\noff(eventName: string): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type   | Default | Required |\n| --------- | --------------------------- | ------ | ------- | -------- |\n| eventName | Name of the event to remove | string | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Remove all node click event listeners\ngraph.off(NodeEvent.CLICK);\nconsole.log('All node click event listeners have been removed');\n\n// Remove related temporary event listeners after a certain operation mode ends\nfunction exitEditMode() {\n  // Remove all listeners in edit mode\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('Exited edit mode');\n}\n```\n\n### Graph.off(eventName, callback)\n\nRemove a specific callback function for a specific event.\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type                     | Default | Required |\n| --------- | --------------------------- | ------------------------ | ------- | -------- |\n| eventName | Name of the event to remove | string                   | -       | ✓        |\n| callback  | Callback function to remove | (...args: any[]) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Define callback function\nconst handleNodeClick = (evt) => {\n  console.log('Node clicked:', evt.target.id);\n};\n\n// Add listener\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// Later, remove this specific listener at a certain point\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('Specific node click event listener has been removed');\n```\n\n## Event Constant Enums\n\nG6 provides various event constant enums to facilitate developers in using standardized event names. Below is a detailed description of all event constants:\n\n### Node Events (NodeEvent)\n\n| Constant Name | Event Name          | Description                                                                   |\n| ------------- | ------------------- | ----------------------------------------------------------------------------- |\n| CLICK         | `node:click`        | Triggered when a node is clicked                                              |\n| DBLCLICK      | `node:dblclick`     | Triggered when a node is double-clicked                                       |\n| POINTER_OVER  | `node:pointerover`  | Triggered when the pointer enters a node                                      |\n| POINTER_LEAVE | `node:pointerleave` | Triggered when the pointer leaves a node                                      |\n| POINTER_ENTER | `node:pointerenter` | Triggered when the pointer enters a node or its child elements (non-bubbling) |\n| POINTER_MOVE  | `node:pointermove`  | Triggered when the pointer moves over a node                                  |\n| POINTER_OUT   | `node:pointerout`   | Triggered when the pointer leaves a node                                      |\n| POINTER_DOWN  | `node:pointerdown`  | Triggered when the pointer is pressed down on a node                          |\n| POINTER_UP    | `node:pointerup`    | Triggered when the pointer is released on a node                              |\n| CONTEXT_MENU  | `node:contextmenu`  | Triggered when the context menu is opened on a node                           |\n| DRAG_START    | `node:dragstart`    | Triggered when dragging a node starts                                         |\n| DRAG          | `node:drag`         | Triggered during node dragging                                                |\n| DRAG_END      | `node:dragend`      | Triggered when node dragging ends                                             |\n| DRAG_ENTER    | `node:dragenter`    | Triggered when a draggable item enters a node                                 |\n| DRAG_OVER     | `node:dragover`     | Triggered when a draggable item is over a node                                |\n| DRAG_LEAVE    | `node:dragleave`    | Triggered when a draggable item leaves a node                                 |\n| DROP          | `node:drop`         | Triggered when a draggable item is dropped on a node                          |\n\n### Edge Events (EdgeEvent)\n\n| Constant Name | Event Name          | Description                                                                    |\n| ------------- | ------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `edge:click`        | Triggered when an edge is clicked                                              |\n| DBLCLICK      | `edge:dblclick`     | Triggered when an edge is double-clicked                                       |\n| POINTER_OVER  | `edge:pointerover`  | Triggered when the pointer enters an edge                                      |\n| POINTER_LEAVE | `edge:pointerleave` | Triggered when the pointer leaves an edge                                      |\n| POINTER_ENTER | `edge:pointerenter` | Triggered when the pointer enters an edge or its child elements (non-bubbling) |\n| POINTER_MOVE  | `edge:pointermove`  | Triggered when the pointer moves over an edge                                  |\n| POINTER_OUT   | `edge:pointerout`   | Triggered when the pointer leaves an edge                                      |\n| POINTER_DOWN  | `edge:pointerdown`  | Triggered when the pointer is pressed down on an edge                          |\n| POINTER_UP    | `edge:pointerup`    | Triggered when the pointer is released on an edge                              |\n| CONTEXT_MENU  | `edge:contextmenu`  | Triggered when the context menu is opened on an edge                           |\n| DRAG_ENTER    | `edge:dragenter`    | Triggered when a draggable item enters an edge                                 |\n| DRAG_OVER     | `edge:dragover`     | Triggered when a draggable item is over an edge                                |\n| DRAG_LEAVE    | `edge:dragleave`    | Triggered when a draggable item leaves an edge                                 |\n| DROP          | `edge:drop`         | Triggered when a draggable item is dropped on an edge                          |\n\n### Combo Events (ComboEvent)\n\n| Constant Name | Event Name           | Description                                                                    |\n| ------------- | -------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `combo:click`        | Triggered when a Combo is clicked                                              |\n| DBLCLICK      | `combo:dblclick`     | Triggered when a Combo is double-clicked                                       |\n| POINTER_OVER  | `combo:pointerover`  | Triggered when the pointer enters a Combo                                      |\n| POINTER_LEAVE | `combo:pointerleave` | Triggered when the pointer leaves a Combo                                      |\n| POINTER_ENTER | `combo:pointerenter` | Triggered when the pointer enters a Combo or its child elements (non-bubbling) |\n| POINTER_MOVE  | `combo:pointermove`  | Triggered when the pointer moves over a Combo                                  |\n| POINTER_OUT   | `combo:pointerout`   | Triggered when the pointer leaves a Combo                                      |\n| POINTER_DOWN  | `combo:pointerdown`  | Triggered when the pointer is pressed down on a Combo                          |\n| POINTER_UP    | `combo:pointerup`    | Triggered when the pointer is released on a Combo                              |\n| CONTEXT_MENU  | `combo:contextmenu`  | Triggered when the context menu is opened on a Combo                           |\n| DRAG_START    | `combo:dragstart`    | Triggered when dragging a Combo starts                                         |\n| DRAG          | `combo:drag`         | Triggered during Combo dragging                                                |\n| DRAG_END      | `combo:dragend`      | Triggered when Combo dragging ends                                             |\n| DRAG_ENTER    | `combo:dragenter`    | Triggered when a draggable item enters a Combo                                 |\n| DRAG_OVER     | `combo:dragover`     | Triggered when a draggable item is over a Combo                                |\n| DRAG_LEAVE    | `combo:dragleave`    | Triggered when a draggable item leaves a Combo                                 |\n| DROP          | `combo:drop`         | Triggered when a draggable item is dropped on a Combo                          |\n\n### Canvas Events (CanvasEvent)\n\n| Constant Name | Event Name            | Description                                                                       |\n| ------------- | --------------------- | --------------------------------------------------------------------------------- |\n| CLICK         | `canvas:click`        | Triggered when clicking on the canvas blank area                                  |\n| DBLCLICK      | `canvas:dblclick`     | Triggered when double-clicking on the canvas blank area                           |\n| POINTER_OVER  | `canvas:pointerover`  | Triggered when the pointer enters the canvas                                      |\n| POINTER_LEAVE | `canvas:pointerleave` | Triggered when the pointer leaves the canvas                                      |\n| POINTER_ENTER | `canvas:pointerenter` | Triggered when the pointer enters the canvas or its child elements (non-bubbling) |\n| POINTER_MOVE  | `canvas:pointermove`  | Triggered when the pointer moves over the canvas                                  |\n| POINTER_OUT   | `canvas:pointerout`   | Triggered when the pointer leaves the canvas                                      |\n| POINTER_DOWN  | `canvas:pointerdown`  | Triggered when the pointer is pressed down on the canvas                          |\n| POINTER_UP    | `canvas:pointerup`    | Triggered when the pointer is released on the canvas                              |\n| CONTEXT_MENU  | `canvas:contextmenu`  | Triggered when the context menu is opened on the canvas                           |\n| DRAG_START    | `canvas:dragstart`    | Triggered when dragging the canvas starts                                         |\n| DRAG          | `canvas:drag`         | Triggered during canvas dragging                                                  |\n| DRAG_END      | `canvas:dragend`      | Triggered when canvas dragging ends                                               |\n| DRAG_ENTER    | `canvas:dragenter`    | Triggered when a draggable item enters the canvas                                 |\n| DRAG_OVER     | `canvas:dragover`     | Triggered when a draggable item is over the canvas                                |\n| DRAG_LEAVE    | `canvas:dragleave`    | Triggered when a draggable item leaves the canvas                                 |\n| DROP          | `canvas:drop`         | Triggered when a draggable item is dropped on the canvas                          |\n| WHEEL         | `canvas:wheel`        | Triggered when scrolling the mouse wheel on the canvas                            |\n\n### Graph Lifecycle Events (GraphEvent)\n\n| Constant Name            | Event Name               | Description                                    |\n| ------------------------ | ------------------------ | ---------------------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | Triggered before canvas initialization         |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | Triggered after canvas initialization          |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | Triggered before viewport size change          |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | Triggered after viewport size change           |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | Triggered before element creation              |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | Triggered after element creation               |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | Triggered before element update                |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | Triggered after element update                 |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | Triggered before element destruction           |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | Triggered after element destruction            |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | Triggered before element translation           |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | Triggered after element translation            |\n| BEFORE_DRAW              | `beforedraw`             | Triggered before drawing starts                |\n| AFTER_DRAW               | `afterdraw`              | Triggered after drawing ends                   |\n| BEFORE_RENDER            | `beforerender`           | Triggered before rendering starts              |\n| AFTER_RENDER             | `afterrender`            | Triggered after rendering completes            |\n| BEFORE_ANIMATE           | `beforeanimate`          | Triggered before animation starts              |\n| AFTER_ANIMATE            | `afteranimate`           | Triggered after animation ends                 |\n| BEFORE_LAYOUT            | `beforelayout`           | Triggered before layout starts                 |\n| AFTER_LAYOUT             | `afterlayout`            | Triggered after layout ends                    |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | Triggered before each stage in pipeline layout |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | Triggered after each stage in pipeline layout  |\n| BEFORE_TRANSFORM         | `beforetransform`        | Triggered before viewport transformation       |\n| AFTER_TRANSFORM          | `aftertransform`         | Triggered after viewport transformation        |\n| BATCH_START              | `batchstart`             | Triggered when batch operation starts          |\n| BATCH_END                | `batchend`               | Triggered when batch operation ends            |\n| BEFORE_DESTROY           | `beforedestroy`          | Triggered before chart destruction             |\n| AFTER_DESTROY            | `afterdestroy`           | Triggered after chart destruction              |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | Triggered before renderer change               |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | Triggered after renderer change                |\n\n### Container Events (ContainerEvent)\n\n| Constant Name | Event Name | Description                                   |\n| ------------- | ---------- | --------------------------------------------- |\n| KEY_DOWN      | `keydown`  | Triggered when a keyboard key is pressed down |\n| KEY_UP        | `keyup`    | Triggered when a keyboard key is released     |\n\n### Common Events (CommonEvent)\n\nThese are events without prefixes and can be used to listen to global events:\n\n| Constant Name | Event Name     | Description                                                                        |\n| ------------- | -------------- | ---------------------------------------------------------------------------------- |\n| CLICK         | `click`        | Triggered when any element is clicked                                              |\n| DBLCLICK      | `dblclick`     | Triggered when any element is double-clicked                                       |\n| POINTER_OVER  | `pointerover`  | Triggered when the pointer enters any element                                      |\n| POINTER_LEAVE | `pointerleave` | Triggered when the pointer leaves any element                                      |\n| POINTER_ENTER | `pointerenter` | Triggered when the pointer enters any element or its child elements (non-bubbling) |\n| POINTER_MOVE  | `pointermove`  | Triggered when the pointer moves over any element                                  |\n| POINTER_OUT   | `pointerout`   | Triggered when the pointer leaves any element                                      |\n| POINTER_DOWN  | `pointerdown`  | Triggered when the pointer is pressed down on any element                          |\n| POINTER_UP    | `pointerup`    | Triggered when the pointer is released on any element                              |\n| CONTEXT_MENU  | `contextmenu`  | Triggered when the context menu is opened on any element                           |\n| DRAG_START    | `dragstart`    | Triggered when dragging any element starts                                         |\n| DRAG          | `drag`         | Triggered during any element dragging                                              |\n| DRAG_END      | `dragend`      | Triggered when any element dragging ends                                           |\n| DRAG_ENTER    | `dragenter`    | Triggered when a draggable item enters any element                                 |\n| DRAG_OVER     | `dragover`     | Triggered when a draggable item is over any element                                |\n| DRAG_LEAVE    | `dragleave`    | Triggered when a draggable item leaves any element                                 |\n| DROP          | `drop`         | Triggered when a draggable item is dropped on any element                          |\n| KEY_DOWN      | `keydown`      | Triggered when a keyboard key is pressed down                                      |\n| KEY_UP        | `keyup`        | Triggered when a keyboard key is released                                          |\n| WHEEL         | `wheel`        | Triggered when scrolling the mouse wheel                                           |\n| PINCH         | `pinch`        | Triggered when pinching or spreading fingers on a multi-touch screen               |\n\n## Tips for Use\n\n### Chain Calls\n\nG6's event API supports chain calls, allowing you to register multiple events consecutively:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Use constant enums + chain calls\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### Event Delegation\n\nYou can use the event bubbling mechanism to listen to all child element events on the parent element:\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// Handle all element click events uniformly\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('Clicked on node:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('Clicked on edge:', target.id);\n  } else {\n    console.log('Clicked on canvas blank area');\n  }\n});\n```\n\n### Event Object Properties\n\nMost event callback functions receive an event object containing the following common properties:\n\n- `target` - The element that triggered the event\n- `targetType` - The type of the element that triggered the event (node/edge/combo/canvas)\n- `originalTarget` - The original graphic that triggered the event\n- `currentTarget` - The current object that triggered the event\n- `originalEvent` - The original browser event object\n\nWith these properties, you can precisely control interactive behavior.\n","packages/site/docs/api/event.zh.md":"---\ntitle: 事件监听\norder: 11\n---\n\n## 事件系统概述\n\nG6 提供了强大的事件机制，允许你响应图表中发生的各种交互行为。例如节点点击、边悬停、画布拖拽等。通过事件系统，你可以实现复杂的交互逻辑，提升用户体验。\n\n### 事件分类\n\nG6 中的事件大致可分为以下几类：\n\n1. **元素事件**：与节点、边、Combo 相关的事件，如 `node:click`, `edge:mouseenter`\n2. **画布事件**：与整个画布相关的事件，如 `canvas:drag`, `canvas:wheel`\n3. **生命周期事件**：与图表生命周期相关的事件，如 `beforerender`, `afterrender`\n\n### 事件命名规则\n\nG6 的事件命名遵循 `[对象]:[事件]` 的格式，例如：\n\n- `node:click` - 节点点击事件\n- `edge:mouseenter` - 鼠标进入边的事件\n- `canvas:drag` - 画布拖拽事件\n\n## 最佳实践：使用常量枚举\n\nG6 提供了完整的事件常量枚举，**强烈建议**使用这些常量而非直接使用字符串事件名：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// 使用常量枚举监听事件\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**优势**：\n\n- 类型安全，避免字符串拼写错误\n- 提供智能代码提示和自动完成\n\n## API 参考\n\n### Graph.on(eventName, callback, once)\n\n监听指定的事件，当事件触发时执行回调函数。\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n| once      | 是否只监听一次           | boolean            | -      |      |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 监听节点点击事件\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // 获取被点击节点的 ID\n  console.log(`节点 ${target.id} 被点击了`);\n\n  // 获取节点数据\n  const nodeData = graph.getNodeData(target.id);\n  console.log('节点数据:', nodeData);\n\n  // 修改节点状态\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边的鼠标进入事件\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// 监听画布拖拽事件\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('画布正在被拖拽');\n});\n```\n\n### Graph.once(eventName, callback)\n\n一次性监听事件，事件触发一次后自动移除监听器。\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// 监听图表首次加载完成事件，仅执行一次\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('图表首次渲染完成');\n  // 执行一次性的初始化操作\n  highlightImportantNodes();\n});\n\n// 等待用户第一次点击某个节点后执行操作\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('用户首次点击了节点:', evt.target.id);\n  showTutorialTip('您可以拖拽节点改变位置');\n});\n```\n\n### Graph.off()\n\n移除全部事件监听器。\n\n```typescript\noff(): this;\n```\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\n// 移除所有事件监听器\ngraph.off();\nconsole.log('已移除所有事件监听器');\n```\n\n### Graph.off(eventName)\n\n移除指定事件类型的所有监听器。\n\n```typescript\noff(eventName: string): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型   | 默认值 | 必选 |\n| --------- | ---------------- | ------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 移除所有节点点击事件的监听器\ngraph.off(NodeEvent.CLICK);\nconsole.log('已移除所有节点点击事件监听器');\n\n// 在某个操作模式结束后，移除相关的临时事件监听\nfunction exitEditMode() {\n  // 移除编辑模式下的所有监听器\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('已退出编辑模式');\n}\n```\n\n### Graph.off(eventName, callback)\n\n移除特定事件的特定回调函数。\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型                     | 默认值 | 必选 |\n| --------- | ---------------- | ------------------------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string                   | -      | ✓    |\n| callback  | 要移除的回调函数 | (...args: any[]) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 定义回调函数\nconst handleNodeClick = (evt) => {\n  console.log('节点被点击:', evt.target.id);\n};\n\n// 添加监听器\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// 之后在某个时机移除这个特定的监听器\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('已移除特定的节点点击事件监听器');\n```\n\n## 事件常量枚举\n\nG6 提供了多种事件常量枚举，便于开发者使用规范的事件名称。以下是所有事件常量的详细说明：\n\n### 节点事件 (NodeEvent)\n\n| 常量名        | 事件名              | 描述                                 |\n| ------------- | ------------------- | ------------------------------------ |\n| CLICK         | `node:click`        | 点击节点时触发                       |\n| DBLCLICK      | `node:dblclick`     | 双击节点时触发                       |\n| POINTER_OVER  | `node:pointerover`  | 指针移入节点时触发                   |\n| POINTER_LEAVE | `node:pointerleave` | 指针离开节点时触发                   |\n| POINTER_ENTER | `node:pointerenter` | 指针进入节点或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `node:pointermove`  | 指针在节点上移动时触发               |\n| POINTER_OUT   | `node:pointerout`   | 指针离开节点时触发                   |\n| POINTER_DOWN  | `node:pointerdown`  | 指针在节点上按下时触发               |\n| POINTER_UP    | `node:pointerup`    | 指针在节点上抬起时触发               |\n| CONTEXT_MENU  | `node:contextmenu`  | 节点上打开上下文菜单时触发           |\n| DRAG_START    | `node:dragstart`    | 开始拖拽节点时触发                   |\n| DRAG          | `node:drag`         | 拖拽节点过程中触发                   |\n| DRAG_END      | `node:dragend`      | 拖拽节点结束时触发                   |\n| DRAG_ENTER    | `node:dragenter`    | 拖拽物进入节点时触发                 |\n| DRAG_OVER     | `node:dragover`     | 拖拽物在节点上方时触发               |\n| DRAG_LEAVE    | `node:dragleave`    | 拖拽物离开节点时触发                 |\n| DROP          | `node:drop`         | 在节点上放置拖拽物时触发             |\n\n### 边事件 (EdgeEvent)\n\n| 常量名        | 事件名              | 描述                               |\n| ------------- | ------------------- | ---------------------------------- |\n| CLICK         | `edge:click`        | 点击边时触发                       |\n| DBLCLICK      | `edge:dblclick`     | 双击边时触发                       |\n| POINTER_OVER  | `edge:pointerover`  | 指针移入边时触发                   |\n| POINTER_LEAVE | `edge:pointerleave` | 指针离开边时触发                   |\n| POINTER_ENTER | `edge:pointerenter` | 指针进入边或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `edge:pointermove`  | 指针在边上移动时触发               |\n| POINTER_OUT   | `edge:pointerout`   | 指针离开边时触发                   |\n| POINTER_DOWN  | `edge:pointerdown`  | 指针在边上按下时触发               |\n| POINTER_UP    | `edge:pointerup`    | 指针在边上抬起时触发               |\n| CONTEXT_MENU  | `edge:contextmenu`  | 边上打开上下文菜单时触发           |\n| DRAG_ENTER    | `edge:dragenter`    | 拖拽物进入边时触发                 |\n| DRAG_OVER     | `edge:dragover`     | 拖拽物在边上方时触发               |\n| DRAG_LEAVE    | `edge:dragleave`    | 拖拽物离开边时触发                 |\n| DROP          | `edge:drop`         | 在边上放置拖拽物时触发             |\n\n### Combo事件 (ComboEvent)\n\n| 常量名        | 事件名               | 描述                                  |\n| ------------- | -------------------- | ------------------------------------- |\n| CLICK         | `combo:click`        | 点击Combo时触发                       |\n| DBLCLICK      | `combo:dblclick`     | 双击Combo时触发                       |\n| POINTER_OVER  | `combo:pointerover`  | 指针移入Combo时触发                   |\n| POINTER_LEAVE | `combo:pointerleave` | 指针离开Combo时触发                   |\n| POINTER_ENTER | `combo:pointerenter` | 指针进入Combo或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `combo:pointermove`  | 指针在Combo上移动时触发               |\n| POINTER_OUT   | `combo:pointerout`   | 指针离开Combo时触发                   |\n| POINTER_DOWN  | `combo:pointerdown`  | 指针在Combo上按下时触发               |\n| POINTER_UP    | `combo:pointerup`    | 指针在Combo上抬起时触发               |\n| CONTEXT_MENU  | `combo:contextmenu`  | Combo上打开上下文菜单时触发           |\n| DRAG_START    | `combo:dragstart`    | 开始拖拽Combo时触发                   |\n| DRAG          | `combo:drag`         | 拖拽Combo过程中触发                   |\n| DRAG_END      | `combo:dragend`      | 拖拽Combo结束时触发                   |\n| DRAG_ENTER    | `combo:dragenter`    | 拖拽物进入Combo时触发                 |\n| DRAG_OVER     | `combo:dragover`     | 拖拽物在Combo上方时触发               |\n| DRAG_LEAVE    | `combo:dragleave`    | 拖拽物离开Combo时触发                 |\n| DROP          | `combo:drop`         | 在Combo上放置拖拽物时触发             |\n\n### 画布事件 (CanvasEvent)\n\n| 常量名        | 事件名                | 描述                                 |\n| ------------- | --------------------- | ------------------------------------ |\n| CLICK         | `canvas:click`        | 点击画布空白处时触发                 |\n| DBLCLICK      | `canvas:dblclick`     | 双击画布空白处时触发                 |\n| POINTER_OVER  | `canvas:pointerover`  | 指针移入画布时触发                   |\n| POINTER_LEAVE | `canvas:pointerleave` | 指针离开画布时触发                   |\n| POINTER_ENTER | `canvas:pointerenter` | 指针进入画布或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `canvas:pointermove`  | 指针在画布上移动时触发               |\n| POINTER_OUT   | `canvas:pointerout`   | 指针离开画布时触发                   |\n| POINTER_DOWN  | `canvas:pointerdown`  | 指针在画布上按下时触发               |\n| POINTER_UP    | `canvas:pointerup`    | 指针在画布上抬起时触发               |\n| CONTEXT_MENU  | `canvas:contextmenu`  | 画布上打开上下文菜单时触发           |\n| DRAG_START    | `canvas:dragstart`    | 开始拖拽画布时触发                   |\n| DRAG          | `canvas:drag`         | 拖拽画布过程中触发                   |\n| DRAG_END      | `canvas:dragend`      | 拖拽画布结束时触发                   |\n| DRAG_ENTER    | `canvas:dragenter`    | 拖拽物进入画布时触发                 |\n| DRAG_OVER     | `canvas:dragover`     | 拖拽物在画布上方时触发               |\n| DRAG_LEAVE    | `canvas:dragleave`    | 拖拽物离开画布时触发                 |\n| DROP          | `canvas:drop`         | 在画布上放置拖拽物时触发             |\n| WHEEL         | `canvas:wheel`        | 在画布上滚动鼠标滚轮时触发           |\n\n### 图表生命周期事件 (GraphEvent)\n\n| 常量名                   | 事件名                   | 描述                               |\n| ------------------------ | ------------------------ | ---------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | 画布初始化之前触发                 |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | 画布初始化之后触发                 |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | 视口尺寸变更之前触发               |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | 视口尺寸变更之后触发               |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | 元素创建之前触发                   |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | 元素创建之后触发                   |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | 元素更新之前触发                   |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | 元素更新之后触发                   |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | 元素销毁之前触发                   |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | 元素销毁之后触发                   |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | 元素平移之前触发                   |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | 元素平移之后触发                   |\n| BEFORE_DRAW              | `beforedraw`             | 绘制开始之前触发                   |\n| AFTER_DRAW               | `afterdraw`              | 绘制结束之后触发                   |\n| BEFORE_RENDER            | `beforerender`           | 渲染开始之前触发                   |\n| AFTER_RENDER             | `afterrender`            | 渲染完成之后触发                   |\n| BEFORE_ANIMATE           | `beforeanimate`          | 动画开始之前触发                   |\n| AFTER_ANIMATE            | `afteranimate`           | 动画结束之后触发                   |\n| BEFORE_LAYOUT            | `beforelayout`           | 布局开始之前触发                   |\n| AFTER_LAYOUT             | `afterlayout`            | 布局结束之后触发                   |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | 流水线布局过程中每个阶段开始前触发 |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | 流水线布局过程中每个阶段结束后触发 |\n| BEFORE_TRANSFORM         | `beforetransform`        | 可视区域变化之前触发               |\n| AFTER_TRANSFORM          | `aftertransform`         | 可视区域变化之后触发               |\n| BATCH_START              | `batchstart`             | 批处理操作开始时触发               |\n| BATCH_END                | `batchend`               | 批处理操作结束时触发               |\n| BEFORE_DESTROY           | `beforedestroy`          | 图表销毁前触发                     |\n| AFTER_DESTROY            | `afterdestroy`           | 图表销毁后触发                     |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | 渲染器变更之前触发                 |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | 渲染器变更之后触发                 |\n\n### 容器事件 (ContainerEvent)\n\n| 常量名   | 事件名    | 描述               |\n| -------- | --------- | ------------------ |\n| KEY_DOWN | `keydown` | 键盘按键按下时触发 |\n| KEY_UP   | `keyup`   | 键盘按键抬起时触发 |\n\n### 通用事件 (CommonEvent)\n\n这些是不带前缀的事件，可用于监听全局事件：\n\n| 常量名        | 事件名         | 描述                                     |\n| ------------- | -------------- | ---------------------------------------- |\n| CLICK         | `click`        | 点击任何元素时触发                       |\n| DBLCLICK      | `dblclick`     | 双击任何元素时触发                       |\n| POINTER_OVER  | `pointerover`  | 指针移入任何元素时触发                   |\n| POINTER_LEAVE | `pointerleave` | 指针离开任何元素时触发                   |\n| POINTER_ENTER | `pointerenter` | 指针进入任何元素或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `pointermove`  | 指针在任何元素上移动时触发               |\n| POINTER_OUT   | `pointerout`   | 指针离开任何元素时触发                   |\n| POINTER_DOWN  | `pointerdown`  | 指针在任何元素上按下时触发               |\n| POINTER_UP    | `pointerup`    | 指针在任何元素上抬起时触发               |\n| CONTEXT_MENU  | `contextmenu`  | 任何元素上打开上下文菜单时触发           |\n| DRAG_START    | `dragstart`    | 开始拖拽任何元素时触发                   |\n| DRAG          | `drag`         | 拖拽任何元素过程中触发                   |\n| DRAG_END      | `dragend`      | 拖拽任何元素结束时触发                   |\n| DRAG_ENTER    | `dragenter`    | 拖拽物进入任何元素时触发                 |\n| DRAG_OVER     | `dragover`     | 拖拽物在任何元素上方时触发               |\n| DRAG_LEAVE    | `dragleave`    | 拖拽物离开任何元素时触发                 |\n| DROP          | `drop`         | 在任何元素上放置拖拽物时触发             |\n| KEY_DOWN      | `keydown`      | 键盘按键按下时触发                       |\n| KEY_UP        | `keyup`        | 键盘按键抬起时触发                       |\n| WHEEL         | `wheel`        | 滚动鼠标滚轮时触发                       |\n| PINCH         | `pinch`        | 多点触控屏幕上双指捏合或张开时触发       |\n\n## 使用技巧\n\n### 链式调用\n\nG6 的事件 API 支持链式调用，可以连续注册多个事件：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 使用常量枚举+链式调用\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### 事件代理\n\n你可以利用事件冒泡机制，在父元素上监听所有子元素的事件：\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// 统一处理所有元素的点击事件\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('点击了节点:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('点击了边:', target.id);\n  } else {\n    console.log('点击了画布空白处');\n  }\n});\n```\n\n### 事件对象属性\n\n大多数事件的回调函数会接收一个事件对象，包含以下常用属性：\n\n- `target` - 触发事件的元素\n- `targetType` - 触发事件的元素类型（node/edge/combo/canvas）\n- `originalTarget` - 原始的触发事件的图形\n- `currentTarget` - 当前触发事件的对象\n- `originalEvent` - 原始的浏览器事件对象\n\n通过这些属性，你可以精确地控制交互行为。\n","packages/site/docs/api/export-image.en.md":"---\ntitle: Export Image\norder: 12\n---\n\n## Overview of Image Export\n\nG6 provides the functionality to export the graph as an image, allowing you to export the current canvas content as a DataURL format. This is convenient for saving, sharing, or further processing. The exported image will retain all visible elements on the canvas, including nodes, edges, combos, and other custom graphics.\n\n## API Reference\n\n### Graph.toDataURL(options)\n\nExport the current canvas as an image in DataURL format.\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**Parameters**\n\n| Parameter | Description                | Type                      | Default | Required |\n| --------- | -------------------------- | ------------------------- | ------- | -------- |\n| options   | Export image configuration | Partial\\<DataURLOptions\\> | -       |          |\n\n**Return Value**\n\nReturns a Promise that resolves to a DataURL string representing the image.\n\n**DataURLOptions Type Definition**\n\n| Parameter      | Type                                        | Required | Description                                                                                              |\n| -------------- | ------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |\n| mode           | 'viewport' \\| 'overall'                     | No       | Export mode <br/> - viewport: Export viewport content <br/> - overall: Export entire canvas              |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | No       | Image type <br/> - image/png: PNG format <br/> - image/jpeg: JPEG format <br/> - image/webp: WebP format |\n| encoderOptions | number                                      | No       | Image quality, only effective for image/jpeg and image/webp, range 0 ~ 1                                 |\n\n## Download Image\n\nG6 5.0 only provides an API to export the canvas as a Base64 image ([toDataURL](#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=Note}\nThe exported image content may not include the complete canvas content. The export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., which will not appear in the exported image.\n:::\n","packages/site/docs/api/export-image.zh.md":"---\ntitle: 导出图片\norder: 12\n---\n\n## 图片导出概述\n\nG6 提供了将图导出为图片的功能，可以将当前画布内容导出为 DataURL 格式，方便保存、分享或进一步处理。导出的图片会保留画布上的所有可见元素，包括节点、边、组合以及其他自定义图形。\n\n## API 参考\n\n### Graph.toDataURL(options)\n\n将当前画布导出为 DataURL 格式的图片。\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**参数**\n\n| 参数    | 描述         | 类型                      | 默认值 | 必选 |\n| ------- | ------------ | ------------------------- | ------ | ---- |\n| options | 导出图片配置 | Partial\\<DataURLOptions\\> | -      |      |\n\n**返回值**\n\n返回一个 Promise，解析为表示图片的 DataURL 字符串。\n\n**DataURLOptions 类型定义**\n\n| 参数           | 类型                                        | 必选 | 描述                                                                                             |\n| -------------- | ------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------ |\n| mode           | 'viewport' \\| 'overall'                     | 否   | 导出模式 <br/> - viewport: 导出视口内容 <br/> - overall: 导出整个画布                            |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | 否   | 图片类型 <br/> - image/png: PNG 格式 <br/> - image/jpeg: JPEG 格式 <br/> - image/webp: WebP 格式 |\n| encoderOptions | number                                      | 否   | 图片质量，仅对 image/jpeg 和 image/webp 有效，取值范围 0 ~ 1                                     |\n\n## 下载图片\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","packages/site/docs/api/graph.en.md":"---\ntitle: Graph Instance\norder: 2\n---\n\n## API Reference\n\n### Graph.destroy()\n\nDestroy the current graph instance and release all resources related to it.\n\n⚠️ **Note**: After destruction, no operations can be performed. If you need to use it again, you must create a new graph instance.\n\n```typescript\ndestroy(): void;\n```\n\n**Usage Scenarios**:\n\n- When the user closes the chart or switches to another view, this method can be called to release resources.\n- When needing to recreate a graph instance, ensure the old instance is destroyed first to avoid memory leaks.\n","packages/site/docs/api/graph.zh.md":"---\ntitle: 图实例\norder: 2\n---\n\n## API 参考\n\n### Graph.destroy()\n\n销毁当前图实例，释放与图实例相关的所有资源。\n\n⚠️ **注意**: 销毁后无法进行任何操作，如果需要重新使用，需要重新创建一个新的图实例。\n\n```typescript\ndestroy(): void;\n```\n\n**使用场景**:\n\n- 当用户关闭图表或切换到其他视图时，可以调用此方法来释放资源。\n- 在需要重新创建图实例时，确保先销毁旧的实例，以避免内存泄漏。\n","packages/site/docs/api/layout.en.md":"---\ntitle: Layout\norder: 6\n---\n\n## Overview of Layout\n\n[Layout](/en/manual/layout/overview) is a crucial part of graph visualization, determining the positioning of nodes on the canvas. G6 offers a variety of layout algorithms to meet different data structures and visualization needs. Through the layout API, you can:\n\n- Set and update the graph's layout configuration\n- Execute or stop layout calculations\n- Combine multiple layout strategies\n- Customize layout algorithms\n\nA suitable layout can clearly display the relationship patterns between nodes, enhancing the graph's readability and aesthetics.\n\n## API Reference\n\n### Graph.setLayout(layout)\n\nSet the graph's layout algorithm and configuration.\n\n⚠️ **Note**: Calling this function won't automatically re-layout, so there's need to call `graph.layout()` separately.\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                        | Type                                                                        | Default | Required |\n| --------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layout    | Layout configuration object, or a function returning a new configuration based on the previous one | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       | ✓        |\n\n**Example 1**: Set a force-directed layout\n\n```typescript\n// Set a simple force-directed layout\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // Prevent node overlap\n  nodeStrength: -50, // Repulsion between nodes, negative value for repulsion\n  edgeStrength: 0.5, // Edge strength, affects edge length\n});\n```\n\n**Example 2**: Update layout using a function\n\n```typescript\n// Update based on the current layout configuration\ngraph.setLayout((prevLayout) => {\n  // If the previous layout was force-directed, adjust its parameters\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // Increase repulsion\n      alphaDecay: 0.01, // Lower decay rate for more iteration time\n    };\n  }\n\n  // Otherwise, switch to radial layout\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**Example 3**: Set a combined layout\n\n```typescript\n// Set a combined layout - different nodes use different layout algorithms\ngraph.setLayout([\n  {\n    type: 'grid',\n    // Filter function: only nodes with type 'main' participate in the layout\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\nGet the current layout configuration.\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**Return Value**\n\n- **Type**: [LayoutOptions](#layoutoptions)\n- **Description**: The current layout configuration object\n\n**Example**\n\n```typescript\n// Get the current layout configuration\nconst currentLayout = graph.getLayout();\nconsole.log('Current layout type:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\nExecute layout calculations. When graph data changes, call this method to trigger the layout algorithm to recalculate node positions.\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter     | Description                 | Type                                                                        | Default | Required |\n| ------------- | --------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layoutOptions | Layout configuration object | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       |          |\n\nIf `layoutOptions` is provided, it takes precedence over the graph's current layout configuration.\n\n**Note**\n\nLayout calculation is an asynchronous process, especially for complex layout algorithms like force-directed layout. This method returns a Promise, which can be used to perform subsequent operations after the layout is complete.\n\n**Example 1**: Basic usage\n\n```typescript\n// Execute layout\nawait graph.layout();\nconsole.log('Layout calculation complete');\n```\n\n**Example 2**: Re-layout after adding data\n\n```typescript\n// Add new nodes and edges\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// Draw new nodes and edges\nawait graph.draw();\n\n// Recalculate layout\nawait graph.layout();\n```\n\n**Example 3**: Listen to layout events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before layout starts\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('Layout calculation starting...');\n});\n\n// After layout completes\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('Layout calculation complete');\n});\n\n// Execute layout\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\nStop an ongoing layout calculation. Mainly used to stop iterative layout algorithms like force-directed layout.\n\n```typescript\nstopLayout(): void;\n```\n\n**Note**\n\nApplicable to layouts with iterative animations, currently `force` belongs to this category. If the layout calculation takes too long, you can manually stop the iteration.\n\n**Example 1**: Basic usage\n\n```typescript\n// Stop layout after 5 seconds\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('Layout manually stopped');\n}, 5000);\n```\n\n**Example 2**: Stop layout with user interaction\n\n```typescript\n// Stop layout when the user clicks the canvas\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('User clicked canvas, layout stopped');\n});\n```\n\n## Type Definitions\n\n### LayoutOptions\n\nLayout configuration type, can be a single layout configuration or an array of layout configurations.\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\nSingle layout configuration, can be a built-in layout configuration or a custom base layout configuration.\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\nBasic configuration items common to all layout types.\n\n```typescript\ninterface BaseLayoutOptions {\n  // Layout type\n  type: string;\n\n  // Node filter function for participating in the layout\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // Whether to calculate the layout before initializing elements\n  preLayout?: boolean;\n\n  // Whether invisible nodes participate in the layout (effective when preLayout is true)\n  isLayoutInvisibleNodes?: boolean;\n\n  // Enable layout animation, for iterative layouts, animation transitions occur between iterations\n  animation?: boolean;\n\n  // Whether to run the layout in a WebWorker\n  enableWorker?: boolean;\n\n  // Number of iterations for iterative layouts\n  iterations?: number;\n\n  // Other specific layout configuration items\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nConfiguration for G6's built-in layout types, see [API - Built-in Layouts](/en/manual/layout/antv-dagre-layout) for details.\n","packages/site/docs/api/layout.zh.md":"---\ntitle: 布局\norder: 6\n---\n\n## 布局概述\n\n[布局](/manual/layout/overview) 是图可视化中至关重要的一环，它决定了节点在画布上的位置排布。G6 提供了多种布局算法，以满足不同数据结构和可视化需求。通过布局 API，你可以：\n\n- 设置和更新图的布局配置\n- 执行或停止布局计算\n- 组合多种布局策略\n- 自定义布局算法\n\n合适的布局可以清晰地展示节点间的关系模式，提高图的可读性和美观度。\n\n## API 参考\n\n### Graph.setLayout(layout)\n\n设置图的布局算法及配置。\n\n⚠️ **注意**: 调用此函数不会自动重新布局，需要单独调用 `graph.layout()`。\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**参数**\n\n| 参数   | 描述                                               | 类型                                                                        | 默认值 | 必选 |\n| ------ | -------------------------------------------------- | --------------------------------------------------------------------------- | ------ | ---- |\n| layout | 布局配置对象，或者一个基于之前配置返回新配置的函数 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      | ✓    |\n\n**示例 1**: 设置力导向布局\n\n```typescript\n// 设置简单的力导向布局\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // 防止节点重叠\n  nodeStrength: -50, // 节点间斥力，负值为斥力\n  edgeStrength: 0.5, // 边的强度，会影响边的长度\n});\n```\n\n**示例 2**: 使用函数式更新布局\n\n```typescript\n// 基于当前布局配置进行更新\ngraph.setLayout((prevLayout) => {\n  // 如果之前是力导向布局，调整其参数\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // 增加斥力\n      alphaDecay: 0.01, // 降低衰减率，让布局有更多迭代时间\n    };\n  }\n\n  // 否则切换到放射状布局\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**示例 3**: 设置组合布局\n\n```typescript\n// 设置组合布局 - 不同的节点使用不同的布局算法\ngraph.setLayout([\n  {\n    type: 'grid',\n    // 过滤函数：只有type为'main'的节点参与布局\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\n获取当前的布局配置。\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**返回值**\n\n- **类型**: [LayoutOptions](#layoutoptions)\n- **描述**: 当前的布局配置对象\n\n**示例**\n\n```typescript\n// 获取当前布局配置\nconst currentLayout = graph.getLayout();\nconsole.log('当前布局类型:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\n执行布局计算。当图数据发生变化后，调用此方法可触发布局算法重新计算节点位置。\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**参数**\n\n| 参数          | 描述         | 类型                                                                        | 默认值 | 必选 |\n| ------------- | ------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| layoutOptions | 布局配置对象 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      |      |\n\n如果传入 `layoutOptions`，则优先考虑传入的布局配置，否则使用图的当前布局配置进行布局。\n\n**说明**\n\n布局计算是一个异步过程，特别是对于复杂的布局算法（如力导向布局）。此方法返回一个 Promise，可以用于在布局完成后执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 执行布局\nawait graph.layout();\nconsole.log('布局计算完成');\n```\n\n**示例 2**: 添加数据后重新布局\n\n```typescript\n// 添加新节点和边\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// 绘制新节点和边\nawait graph.draw();\n\n// 重新计算布局\nawait graph.layout();\n```\n\n**示例 3**: 监听布局事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 布局开始前\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('布局计算开始...');\n});\n\n// 布局完成后\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('布局计算完成');\n});\n\n// 执行布局\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\n停止正在进行中的布局计算。主要用于停止迭代类型的布局算法，如力导向布局。\n\n```typescript\nstopLayout(): void;\n```\n\n**说明**\n\n适用于带有迭代动画的布局，目前有 `force` 属于此类布局。当布局计算时间过长时，可以手动停止迭代。\n\n**示例 1**: 基本使用\n\n```typescript\n// 5秒后停止布局\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('布局已手动停止');\n}, 5000);\n```\n\n**示例 2**: 结合用户交互停止布局\n\n```typescript\n// 当用户点击画布时停止布局\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('用户点击画布，布局已停止');\n});\n```\n\n## 类型定义\n\n### LayoutOptions\n\n布局配置类型，可以是单一布局配置或布局配置数组。\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\n单一布局配置，可以是内置布局配置或自定义基础布局配置。\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\n所有布局类型共有的基础配置项。\n\n```typescript\ninterface BaseLayoutOptions {\n  // 布局类型\n  type: string;\n\n  // 参与该布局的节点过滤函数\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // 是否在初始化元素前计算布局\n  preLayout?: boolean;\n\n  // 不可见节点是否参与布局（当 preLayout 为 true 时生效）\n  isLayoutInvisibleNodes?: boolean;\n\n  // 启用布局动画，对于迭代布局，会在两次迭代之间进行动画过渡\n  animation?: boolean;\n\n  // 是否在 WebWorker 中运行布局\n  enableWorker?: boolean;\n\n  // 迭代布局的迭代次数\n  iterations?: number;\n\n  // 其他特定布局的配置项\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nG6 内置的布局类型配置，具体请查看 [API - 内置布局](/manual/layout/antv-dagre-layout)。\n","packages/site/docs/api/option.en.md":"---\ntitle: Graph Options\norder: 7\n---\n\n## Overview of Graph Options\n\nThe [options](/en/manual/graph/option) of a G6 graph instance control various aspects of the graph, including canvas settings, viewport properties, data, layout, styles, interaction behaviors, plugins, and more. By configuring these options appropriately, you can flexibly customize the appearance and behavior of the graph.\n\nOptions can be specified when creating a graph instance or dynamically modified at runtime through the API. Some basic configurations (such as devicePixelRatio, container) require destroying and recreating the graph instance to take effect after modification.\n\n## API Reference\n\n### Graph.getOptions()\n\nRetrieve all configuration options of the current graph.\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**Return Value**\n\n- **Type**: [GraphOptions](/en/manual/graph/option)\n- **Description**: Complete configuration options of the current graph\n\n**Example**\n\n```typescript\n// Retrieve the current graph's options\nconst options = graph.getOptions();\nconsole.log('Current graph options:', options);\n\n// Retrieve specific options\nconsole.log('Current canvas width:', options.width);\nconsole.log('Current layout options:', options.layout);\n```\n\n### Graph.setOptions(options)\n\nUpdate the graph's configuration options.\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                    | Default | Required |\n| --------- | ------------------------- | --------------------------------------- | ------- | -------- |\n| options   | New configuration options | [GraphOptions](/en/manual/graph/option) | -       | ✓        |\n\n**Note**\n\n⚠️ **Attention**: To update basic properties like devicePixelRatio, container, etc., you need to destroy the current graph instance and recreate it. Most other configurations can be dynamically updated.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Update graph configuration\ngraph.setOptions({\n  width: 1000, // Update width\n  height: 800, // Update height\n  autoFit: 'view', // Enable auto-fit\n  animation: true, // Enable animation\n});\n```\n\n**Example 2**: Update Theme\n\n```typescript\n// Update graph theme configuration\ngraph.setOptions({\n  theme: {\n    type: 'dark', // Switch to dark theme\n    // Custom theme configuration\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**Example 3**: Update Layout Configuration\n\n```typescript\n// Update layout configuration\ngraph.setOptions({\n  layout: {\n    type: 'force', // Switch to force-directed layout\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**Example 4**: Update Default Node and Edge Configuration\n\n```typescript\n// Update default style configuration for nodes and edges\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n\n## Type Definitions\n\n### GraphOptions\n\n```typescript\ntype GraphOptions = {\n  // Whether to enable zooming\n  enableZoom?: boolean;\n\n  // Whether to enable dragging\n  enableDrag?: boolean;\n\n  // Default style for nodes\n  defaultNodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Additional configuration options for the graph\n  [configKey: string]: any;\n};\n```\n","packages/site/docs/api/option.zh.md":"---\ntitle: 图配置项\norder: 7\n---\n\n## 图配置项概述\n\nG6 图实例的 [配置项](/manual/graph/option) 控制着图的各个方面，包括画布设置、视口属性、数据、布局、样式、交互行为、插件等。通过合理配置这些选项，可以灵活定制图的外观和行为。\n\n配置项可以在图实例创建时指定，也可以通过 API 在运行时动态修改。某些基础配置（如 devicePixelRatio、container）修改后需要销毁并重新创建图实例才能生效。\n\n## API 参考\n\n### Graph.getOptions()\n\n获取当前图表的所有配置项。\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**返回值**\n\n- **类型**: [GraphOptions](/manual/graph/option)\n- **描述**: 当前图表的完整配置项\n\n**示例**\n\n```typescript\n// 获取当前图表的配置项\nconst options = graph.getOptions();\nconsole.log('当前图表配置:', options);\n\n// 获取特定配置\nconsole.log('当前画布宽度:', options.width);\nconsole.log('当前布局配置:', options.layout);\n```\n\n### Graph.setOptions(options)\n\n更新图表的配置项。\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**参数**\n\n| 参数    | 描述       | 类型                                 | 默认值 | 必选 |\n| ------- | ---------- | ------------------------------------ | ------ | ---- |\n| options | 新的配置项 | [GraphOptions](/manual/graph/option) | -      | ✓    |\n\n**说明**\n\n⚠️ **注意**: 要更新 devicePixelRatio、container 等基础属性，需要销毁当前图实例后重新创建。其他大部分配置可以动态更新。\n\n**示例 1**: 基本用法\n\n```typescript\n// 更新图表配置\ngraph.setOptions({\n  width: 1000, // 更新宽度\n  height: 800, // 更新高度\n  autoFit: 'view', // 开启自适应\n  animation: true, // 启用动画\n});\n```\n\n**示例 2**: 更新主题\n\n```typescript\n// 更新图表主题配置\ngraph.setOptions({\n  theme: {\n    type: 'dark', // 切换到暗色主题\n    // 自定义主题配置\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**示例 3**: 更新布局配置\n\n```typescript\n// 更新布局配置\ngraph.setOptions({\n  layout: {\n    type: 'force', // 切换到力导向布局\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**示例 4**: 更新节点和边的默认配置\n\n```typescript\n// 更新节点和边的默认样式配置\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n","packages/site/docs/api/plugin.en.md":"---\ntitle: Plugin\norder: 8\n---\n\n## Overview of Plugins\n\n[Plugins](/en/manual/plugin/overview) are an important mechanism in G6 for extending functionality and enhancing the interactive experience of graphs. Plugins typically provide independent functional modules, such as thumbnails, toolbars, context menus, etc. They integrate well with the main graph while maintaining modular and maintainable code.\n\nThe plugin system is designed to follow the \"plug and play\" principle, allowing dynamic addition or removal as needed.\n\n## API Reference\n\n### Graph.getPluginInstance(key)\n\nRetrieve the plugin instance specified by the key, used to access and operate the methods provided by the plugin.\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**Parameters**\n\n| Parameter | Description                     | Type   | Default | Required |\n| --------- | ------------------------------- | ------ | ------- | -------- |\n| key       | Unique identifier of the plugin | string | -       | ✓        |\n\n**Return Value**\n\n- **Type**: Plugin instance\n- **Description**: The plugin instance corresponding to the specified key\n\n**Note**\n\nMany plugins provide specific API methods, which can be directly called by obtaining the plugin instance. For example, the fullscreen plugin provides `request()` and `exit()` methods to control fullscreen status.\n\n**Example**: Operate the fullscreen plugin\n\n```typescript\n// Get the fullscreen plugin instance\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// Request to enter fullscreen\nfullscreen.request();\n\n// Exit fullscreen later\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\nRetrieve all configured plugins in the current graph.\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**Return Value**\n\n- **Type**: [PluginOptions](#pluginoptions)\n- **Description**: All configured plugins in the current graph\n\n**Example**\n\n```typescript\n// Get all plugin configurations\nconst plugins = graph.getPlugins();\n\n// View currently active plugins\nconsole.log('Current graph plugin configurations:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\nSet the graph's plugins, replacing all existing plugin configurations.\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                     | Type                                                                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| plugins   | New plugin configurations, or a function returning new configurations based on the current ones | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -       | ✓        |\n\n**Note**\n\nThe set plugins will completely replace the original plugin configurations. To add new plugins based on existing ones, you can use functional updates:\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**Example 1**: Set basic plugins\n\n```typescript\n// Set multiple basic plugins\ngraph.setPlugins([\n  // String form (using default configuration)\n  'minimap',\n\n  // Object form (custom configuration)\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**Example 2**: Use functional updates\n\n```typescript\n// Add new plugins to existing configurations\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// Replace specific plugins\ngraph.setPlugins((currentPlugins) => {\n  // Filter out existing grid plugins\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // Add new grid plugin configuration\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\nUpdate the configuration of a specified plugin, identified by the `key` of the plugin to be updated.\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                               | Type                                      | Default | Required |\n| --------- | ----------------------------------------- | ----------------------------------------- | ------- | -------- |\n| plugin    | Configuration of the plugin to be updated | [UpdatePluginOption](#updatepluginoption) | -       | ✓        |\n\n**Note**\n\nTo update a plugin, the `key` field must be specified in the original plugin configuration to accurately locate and update the plugin.\n\n**Example 1**: Update plugin configuration\n\n```typescript\n// Specify key when initially setting plugins\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// Update grid plugin configuration\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## Type Definitions\n\n### PluginOptions\n\nPlugin configuration type, representing an array of plugin configurations.\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\nCustom plugin configuration interface, used to configure plugin parameters.\n\n```typescript\ntype CustomPluginOption = {\n  // Plugin type\n  type: string;\n\n  // Plugin key, i.e., unique identifier\n  // Used to identify the plugin for further operations\n  key?: string;\n\n  // Other configuration items for different types of plugins\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\nConfiguration interface for updating plugins, used to dynamically modify plugin parameters.\n\n```typescript\ntype UpdatePluginOption = {\n  // Unique identifier of the plugin to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/plugin.zh.md":"---\ntitle: 插件\norder: 8\n---\n\n## 插件概述\n\n[插件](/manual/plugin/overview)（Plugin）是 G6 中扩展功能的重要机制，用于增强图表的功能和交互体验。插件通常提供一些独立的功能模块，如缩略图、工具栏、上下文菜单等，它们可以与图表主体良好集成，同时又保持代码的模块化和可维护性。\n\n插件系统设计遵循\"即插即用\"的原则，可以根据需要动态添加或移除。\n\n## API 参考\n\n### Graph.getPluginInstance(key)\n\n获取指定 key 的插件实例，用于访问和操作插件提供的方法。\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**参数**\n\n| 参数 | 描述             | 类型   | 默认值 | 必选 |\n| ---- | ---------------- | ------ | ------ | ---- |\n| key  | 插件的唯一标识符 | string | -      | ✓    |\n\n**返回值**\n\n- **类型**: 插件实例\n- **描述**: 指定 key 对应的插件实例\n\n**说明**\n\n许多插件提供了特定的API方法，通过获取插件实例可以直接调用这些方法。例如，全屏插件提供了 `request()` 和 `exit()` 方法来控制全屏状态。\n\n**示例**: 操作全屏插件\n\n```typescript\n// 获取全屏插件实例\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// 请求进入全屏\nfullscreen.request();\n\n// 稍后退出全屏\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\n获取当前图表中所有已配置的插件。\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**返回值**\n\n- **类型**: [PluginOptions](#pluginoptions)\n- **描述**: 当前图表中已配置的所有插件\n\n**示例**\n\n```typescript\n// 获取所有插件配置\nconst plugins = graph.getPlugins();\n\n// 查看当前激活的插件\nconsole.log('当前图表的插件配置:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\n设置图表的插件，将替换所有现有的插件配置。\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**参数**\n\n| 参数    | 描述                                             | 类型                                                                        | 默认值 | 必选 |\n| ------- | ------------------------------------------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| plugins | 新的插件配置，或一个基于当前配置返回新配置的函数 | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -      | ✓    |\n\n**说明**\n\n设置的插件会全量替换原有的插件配置。如果需要在现有插件基础上添加新插件，可以使用函数式更新方式：\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**示例 1**: 设置基本插件\n\n```typescript\n// 设置多个基本插件\ngraph.setPlugins([\n  // 字符串形式（使用默认配置）\n  'minimap',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**示例 2**: 使用函数式更新\n\n```typescript\n// 添加新插件到现有配置\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// 替换特定插件\ngraph.setPlugins((currentPlugins) => {\n  // 过滤掉现有的网格插件\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // 添加新的网格插件配置\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\n更新指定的插件配置，需要通过 `key` 标识要更新的插件。\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**参数**\n\n| 参数   | 描述           | 类型                                      | 默认值 | 必选 |\n| ------ | -------------- | ----------------------------------------- | ------ | ---- |\n| plugin | 更新的插件配置 | [UpdatePluginOption](#updatepluginoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个插件，必须在原始插件配置中指定 `key` 字段，以便能够准确找到并更新该插件。\n\n**示例 1**: 更新插件配置\n\n```typescript\n// 初始设置插件时指定 key\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// 更新网格插件配置\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## 类型定义\n\n### PluginOptions\n\n插件配置类型，表示一组插件配置的数组。\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\n自定义插件配置接口，用于配置插件参数。\n\n```typescript\ntype CustomPluginOption = {\n  // 插件类型\n  type: string;\n\n  // 插件 key，即唯一标识\n  // 用于标识插件，从而进一步操作此插件\n  key?: string;\n\n  // 针对不同类型的插件，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\n更新插件的配置接口，用于动态修改插件参数。\n\n```typescript\ntype UpdatePluginOption = {\n  // 要更新的插件的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/render.en.md":"---\ntitle: Drawing and Rendering\norder: 3\n---\n\n## Overview of Drawing and Rendering\n\nG6 provides a series of drawing and rendering-related APIs to control the display process of graphical elements. In G6, drawing and rendering are two different concepts:\n\n- **Drawing (draw)**: Responsible only for drawing graphical elements onto the canvas, without involving layout calculations.\n- **Rendering (render)**: A complete rendering process, including data processing, layout calculations, and final drawing.\n\nUnderstanding the differences between these APIs is crucial for optimizing performance and achieving specific effects.\n\n## API Reference\n\n### Graph.draw()\n\nDraw elements without performing layout calculations.\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**Note**\n\nThe `draw` method only executes the drawing process of elements and does not recalculate the layout.\n\n⚠️ **Attention**: `draw` is an asynchronous method, requiring the use of `await` or Promise chaining to ensure subsequent operations are executed after drawing is complete.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.draw();\n```\n\n**Example 2**: Redraw after modifying node styles\n\n```javascript\n// Redraw after modifying node styles\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// Only draw the updated styles without re-layout\nawait graph.draw();\n```\n\n**Example 3**: Batch update multiple elements and draw once\n\n```javascript\n// Update multiple nodes\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// Update edges\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// Draw after batch operations\nawait graph.draw();\n```\n\n**Example 4**: Use event listener to detect drawing completion\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('Drawing complete');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\nExecute the complete rendering process, including data processing, layout calculations, and drawing.\n\n```typescript\nrender(): Promise<void>;\n```\n\n**Note**\n\nThe `render` method executes the complete rendering process:\n\n1. Process data updates\n2. Draw elements onto the canvas\n3. Execute layout algorithms\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.render();\n```\n\n**Example 2**: Render after adding new data\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**Example 3**: Listen to rendering events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before rendering starts\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('Rendering starts...');\n  // Show loading indicator\n  showLoadingIndicator();\n});\n\n// After rendering completes\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('Rendering complete');\n  // Hide loading indicator\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\nClear all elements on the canvas, including nodes, edges, and other graphical elements.\n\n```typescript\nclear(): Promise<void>;\n```\n\n**Note**\n\nThis method deletes all elements in the graph but retains the canvas configuration and styles. It is an asynchronous method that returns a Promise.\n\n**Example**\n\n```typescript\n// Basic usage\nawait graph.clear();\n```\n\n## Usage Tips\n\n### Choosing between draw and render\n\n- Use `draw()` when:\n  - Only the styles or states of elements are modified, without needing to recalculate positions.\n  - Performance-sensitive, aiming to avoid unnecessary layout calculations.\n- Use `render()` when:\n  - Initializing the graph.\n  - Changing layout configurations.\n  - Adding or removing a large number of nodes/edges.\n  - Need to recalculate positions of all elements.\n","packages/site/docs/api/render.zh.md":"---\ntitle: 绘制与渲染\norder: 3\n---\n\n## 绘制与渲染概述\n\nG6 提供了一系列绘制和渲染相关的 API，用于控制图形元素的显示过程。在 G6 中，绘制和渲染是两个不同的概念：\n\n- **绘制(draw)**: 仅负责将图形元素绘制到画布上，不涉及布局计算\n- **渲染(render)**: 完整的渲染流程，包括数据处理、布局计算和最终绘制\n\n理解这些 API 的区别对于优化性能和实现特定效果至关重要。\n\n## API 参考\n\n### Graph.draw()\n\n绘制元素，但不执行布局计算。\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**说明**\n\n`draw` 方法仅执行元素的绘制过程，不会重新计算布局。\n\n⚠️ **注意**: `draw` 为异步方法，需要使用 `await` 或 Promise 链式调用来确保绘制完成后再执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 基本用法\nawait graph.draw();\n```\n\n**示例 2**: 修改节点样式后重新绘制\n\n```javascript\n// 修改节点样式后重新绘制\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 仅绘制更新后的样式，不重新布局\nawait graph.draw();\n```\n\n**示例 3**: 批量更新多个元素后一次性绘制\n\n```javascript\n// 更新多个节点\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// 更新边\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// 批量操作完成后绘制\nawait graph.draw();\n```\n\n**示例 4**: 使用事件监听绘制完成\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('绘制完成');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\n执行完整的渲染流程，包括数据处理、布局计算和绘制。\n\n```typescript\nrender(): Promise<void>;\n```\n\n**说明**\n\n`render` 方法会执行完整的渲染流程：\n\n1. 处理数据更新\n2. 绘制元素到画布上\n3. 执行布局算法\n\n**示例 1**: 基本用法\n\n```typescript\n// 基本用法\nawait graph.render();\n```\n\n**示例 2**: 添加新数据后渲染\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**示例 3**: 监听渲染事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 渲染开始前\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('渲染开始...');\n  // 显示加载指示器\n  showLoadingIndicator();\n});\n\n// 渲染完成后\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('渲染完成');\n  // 隐藏加载指示器\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\n清空画布上的所有元素，包括节点、边和其他图形元素。\n\n```typescript\nclear(): Promise<void>;\n```\n\n**说明**\n\n此方法会删除图中的所有元素，但保留画布配置和样式。这是一个异步方法，返回一个 Promise。\n\n**示例**\n\n```typescript\n// 基本用法\nawait graph.clear();\n```\n\n## 使用技巧\n\n### draw 与 render 的选择\n\n- 使用 `draw()` 当:\n  - 仅修改了元素样式或状态，不需要重新计算位置\n  - 性能敏感，希望避免不必要的布局计算\n- 使用 `render()` 当:\n  - 初始化图表\n  - 更改了布局配置\n  - 添加或删除了大量节点/边\n  - 需要重新计算所有元素位置\n","packages/site/docs/api/theme.en.md":"---\ntitle: Theme\norder: 9\n---\n\n## Overview of Theme\n\nG6 allows users to customize the appearance of graphs through themes. Themes can be used to define colors, shapes, and styles for nodes, edges, and other graph elements.\n\n## API Reference\n\n### Graph.getTheme()\n\nGet the theme\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>Related Parameters</summary>\n\n**Return Value**:\n\n- **Type:** false \\| 'light' \\| 'dark' \\| string\n\n- **Description:** Current theme\n\n</details>\n\n### Graph.setTheme(theme)\n\nSet the theme\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**Example**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>Related Parameters</summary>\n\n<table><thead><tr><th>\n\nParameter\n\n</th><th>\n\nType\n\n</th><th>\n\nDescription\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) => false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\nTheme name\n\n</td></tr>\n</tbody></table>\n\n**Return Value**:\n\n- **Type:** void\n\n</details>\n\n## Type Definitions\n\n### ThemeOptions\n\n```typescript\ntype ThemeOptions = {\n  // Colors used in the theme\n  colors: string[];\n\n  // Node style settings\n  nodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Edge style settings\n  edgeStyle?: {\n    stroke: string;\n  };\n\n  // Additional configuration options for the theme\n  [configKey: string]: any;\n};\n```\n","packages/site/docs/api/theme.zh.md":"---\ntitle: 主题\norder: 9\n---\n\n## API 参考\n\n### Graph.getTheme()\n\n获取主题\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>相关参数</summary>\n\n**返回值**：\n\n- **类型：** false \\| 'light' \\| 'dark' \\| string\n\n- **描述：** 当前主题\n\n</details>\n\n### Graph.setTheme(theme)\n\n设置主题\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**示例**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>相关参数</summary>\n\n<table><thead><tr><th>\n\n参数\n\n</th><th>\n\n类型\n\n</th><th>\n\n描述\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) =&gt; false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\n主题名\n\n</td></tr>\n</tbody></table>\n\n**返回值**：\n\n- **类型：** void\n\n</details>\n","packages/site/docs/api/transform.en.md":"---\ntitle: Data Transformation\norder: 10\n---\n\n## Overview of Data Transformation\n\n[Data Transformation](/en/manual/transform/overview) is a powerful feature in G6 that allows for processing and transforming data during the graph rendering process. With data transformers, you can achieve various data processing needs, such as:\n\n- Data Filtering: Filter nodes and edges to be displayed based on conditions\n- Data Calculation: Generate new attributes based on original data, such as calculating node size based on the number of connections, without polluting the original data\n- Data Aggregation: Aggregate a large number of nodes into fewer nodes to improve the performance of large-scale graphs\n\nData transformation occurs at specific stages of the rendering process, allowing flexible changes to the final presentation without modifying the original data source.\n\n## API Reference\n\n### Graph.getTransforms()\n\nRetrieve all configured data transformers in the current graph.\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**Return Value**\n\n- **Type**: [TransformOptions](#transformoptions)\n- **Description**: All configured data transformers in the current graph\n\n**Example**\n\n```typescript\n// Retrieve all data transformers\nconst transforms = graph.getTransforms();\nconsole.log('Data transformers in the current graph:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\nSet the data transformers for the graph, replacing all existing transformers.\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**Parameters**\n\n| Parameter  | Description                                                                                               | Type                                                                                  | Default | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------- | -------- |\n| transforms | New data transformer configurations, or a function returning new configurations based on the current ones | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -       | ✓        |\n\n**Note**\n\nData transformers can process data at different stages of the graph rendering process. The set data transformations will completely replace the original ones. To add new data transformations based on existing ones, you can use functional updates.\n\n**Example 1**: Set basic data transformations\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**Example 2**: Set data transformations with configurations\n\n```typescript\ngraph.setTransforms([\n  // String form (using default configuration)\n  'process-parallel-edges',\n\n  // Object form (custom configuration)\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // Distance between parallel edges\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new data transformations to existing configurations\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\nUpdate the configuration of a specified data transformer, identified by the `key` of the transformer to be updated.\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                         | Type                                            | Default | Required |\n| --------- | --------------------------------------------------- | ----------------------------------------------- | ------- | -------- |\n| transform | Configuration of the data transformer to be updated | [UpdateTransformOption](#updatetransformoption) | -       | ✓        |\n\n**Note**\n\nTo update a data transformer, the `key` field must be specified in the original data transformer configuration to accurately locate and update the transformer.\n\n**Example**: Update data transformer configuration\n\n```typescript\n// Specify key when initially setting data transformers\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// Update distance between parallel edges\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## Type Definitions\n\n### TransformOptions\n\nData transformer configuration type, representing an array of data transformer configurations.\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\nCustom data transformer configuration interface, used to configure data processing parameters.\n\n```typescript\ntype CustomTransformOption = {\n  // Data processing type\n  type: string;\n\n  // Unique identifier for the data transformer\n  key?: string;\n\n  // Other configuration items for different types of data processing\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\nConfiguration interface for updating data transformers, used to dynamically modify data processing parameters.\n\n```typescript\ntype UpdateTransformOption = {\n  // Unique identifier of the data transformer to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/transform.zh.md":"---\ntitle: 数据处理\norder: 10\n---\n\n## 数据处理概述\n\n[数据处理](/manual/transform/overview)（Transform）是 G6 中一项强大的功能，允许在图渲染过程中对数据进行处理和转换。通过数据处理器，您可以实现各种数据处理需求，比如：\n\n- 数据过滤：根据条件筛选需要显示的节点和边\n- 数据计算：基于原始数据生成新的属性，如根据节点连接数计算节点大小，但不污染原始数据\n- 数据聚合：将大量节点聚合为少量节点，提高大规模图表的性能\n\n数据处理发生在渲染流程的特定阶段，可以灵活地改变最终呈现的结果，而无需修改原始数据源。\n\n## API 参考\n\n### Graph.getTransforms()\n\n获取当前图表中所有已配置的数据处理器。\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**返回值**\n\n- **类型**: [TransformOptions](#transformoptions)\n- **描述**: 当前图表中已配置的所有数据处理器\n\n**示例**\n\n```typescript\n// 获取当前所有数据处理器\nconst transforms = graph.getTransforms();\nconsole.log('当前图表的数据处理器:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\n设置图表的数据处理器，将替换所有现有的数据处理器。\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**参数**\n\n| 参数       | 描述                                                   | 类型                                                                                  | 默认值 | 必选 |\n| ---------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------ | ---- |\n| transforms | 新的数据处理器配置，或一个基于当前配置返回新配置的函数 | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -      | ✓    |\n\n**说明**\n\n数据处理器能够在图渲染过程的不同阶段对数据进行处理。设置的数据处理会全量替换原有的数据处理，如果需要在现有数据处理基础上添加新的数据处理，可以使用函数式更新方式。\n\n**示例 1**: 设置基本数据处理\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**示例 2**: 设置带配置的数据处理\n\n```typescript\ngraph.setTransforms([\n  // 字符串形式（使用默认配置）\n  'process-parallel-edges',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // 平行边之间的距离\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的数据处理到现有配置\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\n更新指定的数据处理器配置，需要通过 `key` 标识要更新的数据处理。\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**参数**\n\n| 参数      | 描述               | 类型                                            | 默认值 | 必选 |\n| --------- | ------------------ | ----------------------------------------------- | ------ | ---- |\n| transform | 更新的数据处理配置 | [UpdateTransformOption](#updatetransformoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个数据处理器，必须在原始数据处理配置中指定 `key` 字段，以便能够准确找到并更新该数据处理。\n\n**示例**: 更新数据处理配置\n\n```typescript\n// 初始设置数据处理时指定 key\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// 更新平行边距离\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## 类型定义\n\n### TransformOptions\n\n数据处理器配置类型，表示一组数据处理配置的数组。\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\n自定义数据处理配置接口，用于配置数据处理参数。\n\n```typescript\ntype CustomTransformOption = {\n  // 数据处理类型\n  type: string;\n\n  // 数据处理唯一标识\n  key?: string;\n\n  // 针对不同类型的数据处理，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\n更新数据处理的配置接口，用于动态修改数据处理参数。\n\n```typescript\ntype UpdateTransformOption = {\n  // 要更新的数据处理的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/viewport.en.md":"---\ntitle: Viewport Operations\norder: 4\n---\n\n## Overview of Viewport Operations\n\nG6 provides a series of viewport operation APIs to control the zooming, panning, and rotating of the canvas. These operations help users better view and interact with graphical content. Through viewport operations, you can achieve the following functions:\n\n- Zoom the canvas to view details or the global view\n- Pan the canvas to view different areas\n- Rotate the canvas to get different perspectives\n- Automatically fit content to the viewport\n\n### Categories of Viewport Operations\n\nViewport operations in G6 are mainly divided into the following categories:\n\n1. **Zoom Operations**: such as `zoomTo`, `zoomBy`\n2. **Pan Operations**: such as `translateTo`, `translateBy`\n3. **Rotate Operations**: such as `rotateTo`, `rotateBy`\n4. **Fit Operations**: such as `fitView`, `fitCenter`\n5. **Viewport Information Retrieval**: such as `getZoom`, `getPosition`\n\n## API Reference\n\n### Graph.zoomTo(zoom, animation, origin)\n\nZoom the canvas to a specified scale (absolute zoom).\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                                    | Type                                                            | Default | Required |\n| --------- | -------------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| zoom      | Target zoom scale (1 = original size, >1 zoom in, <1 zoom out) | number                                                          | -       | ✓        |\n| animation | Animation configuration                                        | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates)                       | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in to 2x\ngraph.zoomTo(2);\n\n// Zoom out to 0.5x with animation\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// Zoom in with the viewport center as the origin\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\nZoom based on the current zoom scale (relative zoom).\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                              | Type                                                            | Default | Required |\n| --------- | ---------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ratio     | Zoom ratio (>1 zoom in, <1 zoom out)     | number                                                          | -       | ✓        |\n| animation | Animation configuration                  | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in by 1.2x based on the current scale\ngraph.zoomBy(1.2);\n\n// Zoom out to 0.8x based on the current scale with animation\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\nPan the graph to a specified position (absolute pan).\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                 | Type                                                            | Default | Required |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| position  | Target position coordinates | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan to a specified position\ngraph.translateTo([100, 100]);\n\n// Pan with animation\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\nPan the graph by a specified distance relative to the current position (relative pan).\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| offset    | Pan offset              | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan right by 100 pixels and down by 50 pixels\ngraph.translateBy([100, 50]);\n\n// Relative pan with animation\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\nRotate the canvas to a specified angle (absolute rotation).\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Target rotation angle (radians)              | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate to 45 degrees\ngraph.rotateTo(Math.PI / 4);\n\n// Rotate to 90 degrees with animation\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\nRotate based on the current angle (relative rotation).\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Rotation angle increment (radians)           | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate clockwise by 30 degrees relative to the current angle\ngraph.rotateBy(Math.PI / 6);\n\n// Relative rotation with animation\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\nScale the graph to fit the appropriate size and pan to the center of the viewport.\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| options   | Fit options             | FitViewOptions                                                  | -       |          |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**FitViewOptions Type Description**\n\n| Property  | Type                   | Default    | Description                                       |\n| --------- | ---------------------- | ---------- | ------------------------------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | Fit timing: only when overflow or always          |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | Fit direction: x-axis, y-axis, or both directions |\n\n**Example**\n\n```typescript\n// Basic usage\ngraph.fitView();\n\n// Configure fit options\ngraph.fitView(\n  {\n    when: 'always', // Always fit\n    direction: 'both', // Fit in both directions\n  },\n  {\n    duration: 1000, // With animation\n  },\n);\n\n// Fit in the x direction only when content overflows\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\nPan the graph to the center of the viewport.\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Center the graph\ngraph.fitCenter();\n\n// Center with animation\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\nGet the current zoom scale.\n\n```typescript\ngetZoom(): number;\n```\n\n**Example**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('Current zoom scale:', currentZoom);\n```\n\n### Graph.getPosition()\n\nGet the position of the graph (position of the canvas origin in the viewport coordinate system).\n\n```typescript\ngetPosition(): Point;\n```\n\n**Example**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('Current position:', position);\n```\n\n### Graph.getRotation()\n\nGet the current rotation angle.\n\n```typescript\ngetRotation(): number;\n```\n\n**Example**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('Current rotation angle (radians):', rotation);\nconsole.log('Current rotation angle (degrees):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\nGet the viewport coordinates of the viewport center.\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('Viewport center coordinates:', center);\n```\n\n### Graph.getViewportCenter()\n\nGet the canvas coordinates of the viewport center.\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('Canvas coordinates of the viewport center:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\nSet the zoom range of the current graph.\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**Parameters**\n\n| Parameter | Description | Type                          | Default | Required |\n| --------- | ----------- | ----------------------------- | ------- | -------- |\n| zoomRange | Zoom range  | [number, number] \\| undefined | -       | ✓        |\n\n**Example**\n\n```typescript\n// Limit the zoom range between 0.5x and 2x\ngraph.setZoomRange([0.5, 2]);\n\n// Remove zoom restrictions\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\nGet the zoom range of the current graph.\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**Example**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('Current zoom range:', range);\n```\n\n### Graph.resize()\n\nResize the canvas to the size of the graph container.\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\nResize the canvas to the specified width and height.\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description   | Type   | Default | Required |\n| --------- | ------------- | ------ | ------- | -------- |\n| width     | Target width  | number | -       | ✓        |\n| height    | Target height | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set the canvas size to 800x600\ngraph.resize(800, 600);\n```\n\n## Type Definitions\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Whether to enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### Point\n\nCoordinate point type.\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\nView fit options.\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // Fit timing\n  direction?: 'x' | 'y' | 'both'; // Fit direction\n}\n```\n","packages/site/docs/api/viewport.zh.md":"---\ntitle: 视口操作\norder: 4\n---\n\n## 视口操作概述\n\nG6 提供了一系列视口操作 API，用于控制画布的缩放、平移和旋转。这些操作可以帮助用户更好地查看和交互图形内容。通过视口操作，你可以实现以下功能：\n\n- 缩放画布以查看细节或全局视图\n- 平移画布以查看不同区域\n- 旋转画布以获得不同视角\n- 自动适配内容到视口\n\n### 视口操作分类\n\nG6 的视口操作主要分为以下几类：\n\n1. **缩放操作**：如 `zoomTo`、`zoomBy`\n2. **平移操作**：如 `translateTo`、`translateBy`\n3. **旋转操作**：如 `rotateTo`、`rotateBy`\n4. **自适应操作**：如 `fitView`、`fitCenter`\n5. **视口信息获取**：如 `getZoom`、`getPosition`\n\n## API 参考\n\n### Graph.zoomTo(zoom, animation, origin)\n\n缩放画布至指定比例（绝对缩放）。\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                                          | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| zoom      | 目标缩放比例 (1 = 原始大小, >1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)                          | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 放大到2倍\ngraph.zoomTo(2);\n\n// 带动画效果的缩小到0.5倍\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// 以视口中心点为原点放大\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\n基于当前缩放比例进行缩放（相对缩放）。\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                        | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ratio     | 缩放比例 (>1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)        | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 在当前比例基础上放大1.2倍\ngraph.zoomBy(1.2);\n\n// 在当前比例基础上缩小到0.8倍，带动画\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\n将图平移至指定位置（绝对平移）。\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述         | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------ | --------------------------------------------------------------- | ------ | ---- |\n| position  | 目标位置坐标 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 平移到指定位置\ngraph.translateTo([100, 100]);\n\n// 带动画效果的平移\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\n将图相对当前位置平移指定距离（相对平移）。\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述       | 类型                                                            | 默认值 | 必选 |\n| --------- | ---------- | --------------------------------------------------------------- | ------ | ---- |\n| offset    | 平移偏移量 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置   | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 向右平移100像素，向下平移50像素\ngraph.translateBy([100, 50]);\n\n// 带动画效果的相对平移\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\n旋转画布至指定角度（绝对旋转）。\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 目标旋转角度(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 旋转到45度\ngraph.rotateTo(Math.PI / 4);\n\n// 带动画效果的旋转到90度\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\n基于当前角度进行旋转（相对旋转）。\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 旋转角度增量(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 相对当前角度顺时针旋转30度\ngraph.rotateBy(Math.PI / 6);\n\n// 带动画效果的相对旋转\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\n将图缩放至合适大小并平移至视口中心。\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| options   | 适配选项 | FitViewOptions                                                  | -      |      |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**FitViewOptions 类型说明**\n\n| 属性      | 类型                   | 默认值     | 描述                         |\n| --------- | ---------------------- | ---------- | ---------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | 适配时机：仅溢出时或始终适配 |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | 适配方向：x轴、y轴或两个方向 |\n\n**示例**\n\n```typescript\n// 基本使用\ngraph.fitView();\n\n// 配置适配选项\ngraph.fitView(\n  {\n    when: 'always', // 始终进行适配\n    direction: 'both', // 在两个方向上适配\n  },\n  {\n    duration: 1000, // 带动画效果\n  },\n);\n\n// 仅在内容溢出时适配x方向\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\n将图平移至视口中心。\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 居中显示\ngraph.fitCenter();\n\n// 带动画效果的居中\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\n获取当前缩放比例。\n\n```typescript\ngetZoom(): number;\n```\n\n**示例**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('当前缩放比例:', currentZoom);\n```\n\n### Graph.getPosition()\n\n获取图的位置（画布原点在视口坐标系下的位置）。\n\n```typescript\ngetPosition(): Point;\n```\n\n**示例**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('当前位置:', position);\n```\n\n### Graph.getRotation()\n\n获取当前旋转角度。\n\n```typescript\ngetRotation(): number;\n```\n\n**示例**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('当前旋转角度(弧度):', rotation);\nconsole.log('当前旋转角度(度):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\n获取视口中心的视口坐标。\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('视口中心坐标:', center);\n```\n\n### Graph.getViewportCenter()\n\n获取视口中心的画布坐标。\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('视口中心的画布坐标:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\n设置当前图的缩放区间。\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                          | 默认值 | 必选 |\n| --------- | -------- | ----------------------------- | ------ | ---- |\n| zoomRange | 缩放区间 | [number, number] \\| undefined | -      | ✓    |\n\n**示例**\n\n```typescript\n// 限制缩放范围在0.5到2倍之间\ngraph.setZoomRange([0.5, 2]);\n\n// 移除缩放限制\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\n获取当前图的缩放区间。\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**示例**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('当前缩放区间:', range);\n```\n\n### Graph.resize()\n\n调整画布大小为图容器大小。\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\n调整画布大小为指定宽高。\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述     | 类型   | 默认值 | 必选 |\n| ------ | -------- | ------ | ------ | ---- |\n| width  | 目标宽度 | number | -      | ✓    |\n| height | 目标高度 | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置画布大小为800x600\ngraph.resize(800, 600);\n```\n\n## 类型定义\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### Point\n\n坐标点类型。\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\n视图适配选项。\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // 适配时机\n  direction?: 'x' | 'y' | 'both'; // 适配方向\n}\n```\n","packages/site/docs/backup/CameraSetting.en.md":"---\ntitle: CameraSetting\n---\n\n## Options\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _string_\n\nPlugin type\n\n### aspect\n\n> _number \\| 'auto'_\n\nCamera viewport aspect ratio, only valid in perspective camera.\n\n- number : Specific aspect ratio\n\n- `'auto'` : Automatically set to the aspect ratio of the canvas\n\n### azimuth\n\n> _number_\n\nAzimuth\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\nCamera type\n\n- `'orbiting'`: Fixed viewpoint, change camera position\n\n- `'exploring'`: Similar to orbiting, but allows the camera to rotate between the North Pole and the South Pole\n\n- `'tracking'`: Fixed camera position, change viewpoint\n\n### distance\n\n> _number_ **Default:** `500`\n\nThe distance from the camera to the target\n\n### elevation\n\n> _number_\n\nElevation\n\n### far\n\n> _number_\n\nThe position of the far plane\n\n### fov\n\n> _number_\n\nCamera field of view, only valid in perspective camera\n\n### maxDistance\n\n> _number_\n\nMaximum distance\n\n### minDistance\n\n> _number_\n\nMinimum distance\n\n### near\n\n> _number_\n\nThe position of the near plane\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\nProjection mode, perspective projection is only valid in 3D scenes\n\n- `'perspective'` : perspective projection\n\n- `'orthographic'` : Orthogonal projection\n\n### roll\n\n> _number_\n\nRoll\n\n## API\n","packages/site/docs/backup/CameraSetting.zh.md":"---\ntitle: CameraSetting 相机设置\n---\n\n## 配置项\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _`camera-setting` \\| string_\n\n⚠️ **注意**：\n\n- 相机设置插件必须在 3D 场景下使用\n- 此插件在使用前需要自行注册：\n\n```javascript\nimport { register, CameraSetting, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting); // type: 'camera-setting'\n```\n\n### aspect\n\n> _number \\| `'auto'`_\n\n相机视口宽高比，仅在透视相机下有效\n\n- number : 具体的宽高比\n\n- `'auto'` : 自动设置为画布的宽高比\n\n### azimuth\n\n> _number_\n\n方位角\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\n相机类型\n\n- `'orbiting'`: 固定视点，改变相机位置\n- `'exploring'`: 类似 orbiting，但允许相机在北极和南极之间旋转\n- `'tracking'`: 固定相机位置，改变视点\n\n### distance\n\n> _number_ **Default:** `500`\n\n相机距离目标的距离\n\n### elevation\n\n> _number_\n\n仰角\n\n### far\n\n> _number_\n\n远平面位置\n\n### fov\n\n> _number_\n\n相机视角，仅在透视相机下有效\n\n### maxDistance\n\n> _number_\n\n最大视距\n\n### minDistance\n\n> _number_\n\n最小视距\n\n### near\n\n> _number_\n\n近平面位置\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\n投影模式，透视投影仅在 3D 场景下有效\n\n- `'perspective'` : 透视投影\n- `'orthographic'` : 正交投影\n\n### roll\n\n> _number_\n\n滚转角\n\n## API\n","packages/site/docs/manual/animation/animation.en.md":"---\ntitle: Animation Overview\norder: 1\n---\n\n## Overview\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nAnimation refers to the state changes of elements over a period of time, such as the position, size, and color of nodes. In G6, animations are often used to enhance user experience and improve the coherence and smoothness of the graph update process.\n\nG6 provides a set of animation paradigms to describe element animations and has built-in some common animation effects. Users can achieve different animation effects by configuring animation parameters.\n\nThe implementation of an animation paradigm is as follows:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\nThe aforementioned animation paradigm indicates that when the `x` and `y` attributes of an element change, an animation will be executed.\n\n## Configure Animation\n\nIn G6, animation configuration is divided into global configuration and local configuration. Global configuration is mainly used to set whether animations are enabled globally, the duration of animations, and other parameters. Local configuration is primarily used to set the animation effects for elements.\n\n### Disabled Global Animation\n\nTo disable global animations, you can pass the `animation` option when instantiating the `Graph`:\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### Configure Global Animation\n\nIf you want to enable animations and also configure the default duration for the animations, you can pass the `animation` option:\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### Configure Element Animation\n\nFor individual elements, you can configure animations at different stages. For example, if you want an element to have a fade-in and fade-out effect when it enters and exits, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\nIf you want to update the position of an element with a translation transition, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\nIf you wish to disable animations for an element, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## Animation Paradigm\n\nThe animation configuration mentioned in the previous section actually used the built-in animation paradigm. This section introduces how to customize the animation paradigm.\n\n:::info{title=Tip}\nBefore writing an animation paradigm, it is necessary to understand the compositional structure of an element. For details, please refer to the [Element](/en/manual/element/overview) section.\n:::\n\nThe [Element](/en/manual/element/overview) section mentioned that elements in G6 are composed of one or more atomic graphics. Therefore, the animation of an element is essentially a combination of these atomic shape animations.\n\nThus, the animation paradigm is an array that describes the animation effects of each atomic shape within the element. For the element itself, it is also a special composite shape and thus has basic shape attributes such as `x`, `y`, etc.\n\nTherefore, you can directly write an animation paradigm for the element itself:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## Custom Animation\n\nIf the built-in animations do not meet your requirements, you can create custom animations. For details, please refer to [Custom Animation](/en/manual/animation/custom-animation).\n\n## Animation Priority\n\nAnimation priority refers to the precedence between global animation configuration and element-specific animation configuration. It can be summarized as follows:\n\n| Global Animation Config | Local Animation Config | Whether to Execute Animation                                                                     |\n| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------ |\n| ✅ true                 | ✅ true                | ✅ Execute animation with default configuration                                                  |\n| ✅ true                 | ❌ false               | ❌ Won't execute animation                                                                       |\n| ✅ true                 | ✅ Custom Animation    | ✅ Execute animation with local animation configuration                                          |\n| ❌ false                | ✅ true                | ❌ Won't execute animation                                                                       |\n| ❌ false                | ❌ false               | ❌ Won't execute animation                                                                       |\n| ❌ false                | ✅ Custom Animation    | ❌ Won't execute animation                                                                       |\n| ✅ Custom Animation     | ✅ true                | ✅ Execute animation with global animation configuration                                         |\n| ✅ Custom Animation     | ✅ Custom Animation    | ✅ Execute animation, local animation configuration overrides the global animation configuration |\n| ✅ Custom Animation     | ❌ false               | ❌ Won't execute animation                                                                       |\n\n## Persistent Animation\n\nIf you want elements to have persistent animations, such as the undulating effect of nodes or the ant line effect of edges, this can be achieved by customizing the elements. Below is an implementation of an edge with an Ant Line animation provided:\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\nThe `onCreate` is a lifecycle hook used to execute animations when an element is created.\n\nConfigure the edge style in the options as follows:\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\nThe `lineDash` is an array for `lineDashOffset`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\nThe `lineDashOffset` is the offset for `lineDash`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\nNode Style Configuration:\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","packages/site/docs/manual/animation/animation.zh.md":"---\ntitle: 动画总览\norder: 1\n---\n\n## 概述\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n动画是指元素在一段时间内的状态变化，例如节点的位置、大小、颜色等。在 G6 中，动画通常用于增强用户体验，提升图更新过程的连贯性和流畅度。\n\nG6 提供了一套动画范式来描述元素动画，并内置了一些常用的动画效果，用户可以通过配置动画参数来实现不同的动画效果。\n\n一个动画范式的实现如下：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n上述动画范式表示当元素的 `x` 和 `y` 属性发生变化时，会执行动画。\n\n## 配置动画\n\nG6 中动画配置分为全局配置和局部配置，全局配置主要用于配置全局是否开启动画、动画时长等参数，局部配置主要用于配置元素的动画效果。\n\n### 关闭全局动画\n\n若要关闭全局动画，可以在实例化 `Graph` 时传入 `animation` 配置项：\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### 配置全局动画\n\n如果要启用动画且同时配置动画的默认播放时长，可以传入 `animation` 配置项：\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### 配置元素动画\n\n对于单个元素，可以配置其在不同阶段的动画。例如希望元素在进场和退场时具有淡入淡出效果，可以以如下方式配置：\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\n如果希望更新元素位置时是以平移过渡的方式，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\n如果希望关闭元素的动画，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## 动画范式\n\n上一节中提到的动画配置实际上使用了内置的动画范式，本节介绍如何自定义动画范式。\n\n:::info{title=提示}\n在编写动画范式之前需要了解元素的组成结构，具体请参考[元素](/manual/element/overview)一节\n:::\n\n[元素](/manual/element/overview)一节中提到：G6 中的元素是由一个或多个原子图形组合而成。因此元素的动画本质上是这些原子图形动画的组合。\n\n因此动画范式是一个数组，用于描述元素中各原子图形的动画效果。对于元素本身来说，其也是一个特殊的复合图形，因此具有基本的图形属性，如 `x`、`y` 等。\n\n因此可以直接为元素本身编写动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## 自定义动画\n\n如果内置动画无法满足需求，可以自定义动画，具体请参考[自定义动画](/manual/animation/custom-animation)。\n\n## 动画优先级\n\n动画优先级是指全局动画配置和元素动画配置之前的优先级，可以归纳如下：\n\n| 全局动画配置 | 局部动画配置 | 是否执行动画                                      |\n| ------------ | ------------ | ------------------------------------------------- |\n| ✅ true      | ✅ true      | ✅ 执行动画，以默认动画配置执行                   |\n| ✅ true      | ❌ false     | ❌ 不执行该类元素动画                             |\n| ✅ true      | ✅ 配置动画  | ✅ 执行动画，以局部动画配置执行                   |\n| ❌ false     | ✅ true      | ❌ 不执行任何动画                                 |\n| ❌ false     | ❌ false     | ❌ 不执行任何动画                                 |\n| ❌ false     | ✅ 配置动画  | ❌ 不执行任何动画                                 |\n| ✅ 配置动画  | ✅ true      | ✅ 执行动画，以全局动画配置执行                   |\n| ✅ 配置动画  | ✅ 配置动画  | ✅ 执行动画，将局部动画配置覆盖全局动画配置后执行 |\n| ✅ 配置动画  | ❌ false     | ❌ 不执行该类元素动画                             |\n\n## 持续动画\n\n如果希望元素具有持续动画，例如节点的波动效果、边的蚂蚁线效果等，可以通过自定义元素方式实现，下面提供一个具有蚂蚁线(Ant Line)动画的边的实现：\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\n其中 `onCreate` 是一个生命周期钩子，用于在元素创建时执行动画。\n\n在 options 中配置边样式：\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\n其中 `lineDash` 是 `lineDashOffset` 的数组，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\n其中 `lineDashOffset` 是 `lineDash` 的偏移量，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\n节点样式配置：\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","packages/site/docs/manual/animation/custom-animation.en.md":"---\ntitle: Custom Animation\norder: 2\n---\n\n## Overview\n\n## Implement Animation\n\nFor circular node (Circle) elements, the main shape is a circle. Now, let's create an animation for it so that when the size of the node changes, it transitions with a scaling animation:\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nNow let's create a graph instance and update the element size to trigger the update animation:\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### Principle Analysis\n\nWhen animating an element, the element converts its animation frame parameters into animation frame parameters for its individual sub-graphics and executes the corresponding animations.\n\nIn the example above, by updating the node size, an animation was performed on the node, and its animation frame parameters were:\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\nAfter obtaining the attribute, the node element converts it into animation frame parameters for the main shape (circle):\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\nTherefore, what is ultimately happening here is that a transition animation is being performed on the circle, changing its radius from 10 to 20.\n\n#### Composite Animation\n\nBy directly combining the position change animation with the size change animation into a single animation paradigm, you can obtain a composite animation paradigm:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nAnd update both the position and size of the node simultaneously:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\nAdd color transition:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\nExecute node update:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","packages/site/docs/manual/animation/custom-animation.zh.md":"---\ntitle: 自定义动画\norder: 2\n---\n\n## 概述\n\n## 实现动画\n\n对于圆形节点（Circle）元素，其主图形是一个圆形，现在为其编写一个动画，当节点的尺寸发生变化时，能够以缩放的方式进行过渡动画：\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n下面我们创建一个图实例并更新元素尺寸来触发更新动画：\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### 原理分析\n\n当对一个元素执行动画时，该元素会将其动画帧参数转化为其各个子图形上的动画帧参数，并执行对应的动画。\n\n在上面的例子中，通过更新节点尺寸(size)，对该节点执行了动画，其动画帧参数为：\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\n节点元素拿到该属性后，将其转化为主图形（圆形）的动画帧参数：\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\n因此这里最终是对圆形执行了半径从 10 到 20 的过渡动画。\n\n#### 复合动画\n\n直接将位置变化动画和尺寸变化动画合并到一个动画范式即可得到复合动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n并同时更新该节点的位置和尺寸：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\n加入颜色过渡：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\n执行节点更新：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","packages/site/docs/manual/behavior/AutoAdaptLabel.en.md":"---\ntitle: AutoAdaptLabel\norder: 1\n---\n\n## Overview\n\nAuto-adapt label display is a dynamic label management strategy designed to intelligently adjust which labels should be displayed or hidden based on factors such as spatial allocation of the current visible range and node importance. By analyzing the visible area in real-time, it ensures that users receive the most relevant and clear information display in different interaction scenarios, while avoiding visual overload and information redundancy.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Node size changes\n- Graph scaling\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // Throttle time\n      padding: 10, // Extra spacing when detecting overlap\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                      | Type                                                                                                                              | Default            | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- |\n| type      | Interaction type name                                                                                                                                                                                                                                                                            | string                                                                                                                            | `auto-adapt-label` | √        |\n| enable    | Whether to enable this interaction                                                                                                                                                                                                                                                               | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                                                   | true               |          |\n| throttle  | Label update throttle time (ms)                                                                                                                                                                                                                                                                  | number                                                                                                                            | 100                |          |\n| padding   | Extra spacing when detecting label overlap                                                                                                                                                                                                                                                       | number \\| number[]                                                                                                                | 0                  |          |\n| sort      | Custom sorting function, sorting elements from high to low importance, with higher importance elements having higher label display priority. Generally, combo > node > edge                                                                                                                      | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                |                    |          |\n| sortNode  | Sort nodes from high to low importance, with higher importance nodes having higher label display priority. Several built-in [centrality algorithms](#nodecentralityoptions) are available, or a custom sorting function can be used. Note that if `sort` is set, `sortNode` will not take effect | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/en/manual/data#nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |          |\n| sortEdge  | Sort edges from high to low importance, with higher importance edges having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortEdge` will not take effect                                                                  | (edgeA: [EdgeData](/en/manual/data#edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                    |                    |          |\n| sortCombo | Sort groups from high to low importance, with higher importance groups having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortCombo` will not take effect                                                               | (comboA: [ComboData](/en/manual/data#combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |          |\n\n### NodeCentralityOptions\n\nMethods for measuring node centrality\n\n- `'degree'`: Degree centrality, measured by the degree of the node (number of connected edges). Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measured by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measured by the reciprocal of the sum of the shortest path lengths from the node to all other nodes. Nodes with high closeness centrality can usually reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measured by the degree of connection of the node to other central nodes. Nodes with high eigenvector centrality are usually connected to other important nodes\n- `'pagerank'`: PageRank centrality, measured by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to webpage ranking algorithms\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md":"---\ntitle: 标签自适应显示 AutoAdaptLabel\norder: 1\n---\n\n## 概述\n\n标签自适应显示是一种动态标签管理策略，旨在根据当前可视范围的空间分配、节点重要性等因素，智能调整哪些标签应显示或隐藏。通过对可视区域的实时分析，确保用户在不同的交互场景下获得最相关最清晰的信息展示，同时避免视觉过载和信息冗余。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 节点尺寸变化\n- 图形缩放\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // 节流时间\n      padding: 10, // 检测重叠时的额外间距\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                        | 类型                                                                                                                                   | 默认值             | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ---- |\n| type      | 交互类型名称                                                                                                                                                                                | string                                                                                                                                 | `auto-adapt-label` | √    |\n| enable    | 是否启用该交互                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                                      | true               |      |\n| throttle  | 标签更新节流时间（ms）                                                                                                                                                                      | number                                                                                                                                 | 100                |      |\n| padding   | 标签检测重叠时的额外间距                                                                                                                                                                    | number \\| number[]                                                                                                                     | 0                  |      |\n| sort      | 自定义排序函数，根据元素的重要性从高到低排序，重要性越高的元素其标签显示优先级越高。一般情况下 combo > node > edge                                                                          | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                     |                    |      |\n| sortNode  | 根据节点的重要性从高到低排序，重要性越高的节点其标签显示优先级越高。内置几种[中心性算法](#nodecentralityoptions)，也可以自定义排序函数。需要注意，如果设置了 `sort`，则 `sortNode` 不会生效 | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/manual/data#节点数据nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |      |\n| sortEdge  | 根据边的重要性从高到低排序，重要性越高的边其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortEdge` 不会生效                                               | (edgeA: [EdgeData](/manual/data#边数据edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                      |                    |      |\n| sortCombo | 根据群组的重要性从高到低排序，重要性越高的群组其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortCombo` 不会生效                                          | (comboA: [ComboData](/manual/data#组合数据combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |      |\n\n### NodeCentralityOptions\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/BrushSelect.en.md":"---\ntitle: BrushSelect\norder: 2\n---\n\n## Overview\n\nBrush select allows users to click and drag a box to enclose elements, selecting the elements within the box.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Quickly selecting a batch of elements\n- Quickly deselecting a batch of elements\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Type                                                                             | Default                   | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | -------- |\n| type           | Interaction type name. This plugin is built-in, and you can use it with `type: 'brush-select'`.                                                                                                                                                                                                                                                                                                                                                                                                                              | `brush-select` \\| string                                                         | `brush-select`            | ✓        |\n| animation      | Whether to enable animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | boolean                                                                          | false                     |          |\n| enable         | Whether to enable brush select functionality                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)  | true                      |          |\n| enableElements | Types of elements that can be selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |          |\n| immediately    | Whether to select immediately, only effective when [selection mode](#mode) is `default`, [example](#immediately)                                                                                                                                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |          |\n| mode           | Selection mode, [example](#mode)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |          |\n| onSelect       | Callback for selected element state                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |          |\n| state          | Switch to this state when selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |          |\n| style          | Specify the style of the selection box, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                  | See below                 |          |\n| trigger        | Press this shortcut key in combination with a mouse click to perform selection **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means selection can be performed with a mouse click without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: [], // No need to press other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nFour selection modes are built-in:\n\n- `union`: Retain the current state of selected elements and add the specified state.\n- `intersect`: If the selected elements already have the specified state, retain it; otherwise, clear the state.\n- `diff`: Invert the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Attribute         | Description               | Type                                     | Default   |\n| ----------------- | ------------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style               | string                                   |           |\n| fill              | Fill color                | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity              | number \\| string                         | 0.1       |\n| isBillboard       | Enable billboard mode     | boolean                                  |           |\n| isSizeAttenuation | Enable size attenuation   | boolean                                  |           |\n| lineCap           | Line end style            | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash configuration        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash offset               | number                                   |           |\n| lineJoin          | Line join style           | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width                | number \\| string                         | 1         |\n| opacity           | Overall opacity           | number \\| string                         |           |\n| radius            | Rectangle corner radius   | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur degree        | number                                   |           |\n| shadowColor       | Shadow color              | string                                   |           |\n| shadowOffsetX     | Shadow X direction offset | number                                   |           |\n| shadowOffsetY     | Shadow Y direction offset | number                                   |           |\n| stroke            | Stroke color              | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity            | number \\| string                         |           |\n| visibility        | Visibility                | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level           | number                                   | 2         |\n\n**Example**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/BrushSelect.zh.md":"---\ntitle: 框选 BrushSelect\norder: 2\n---\n\n## 概述\n\n鼠标点击拖一个框笼罩元素，框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素\n- 快速取消选中一批元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                                                                                                                                                                                                                                                                                                                                            | 类型                                                                             | 默认值                    | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | ---- |\n| type           | 交互类型名称。此插件已内置，你可以通过 `type: 'brush-select'` 来使用它。                                                                                                                                                                                                                                                                                                        | `brush-select` \\| string                                                         | `brush-select`            | ✓    |\n| animation      | 是否启用动画                                                                                                                                                                                                                                                                                                                                                                    | boolean                                                                          | false                     |      |\n| enable         | 是否启用框选功能                                                                                                                                                                                                                                                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                | true                      |      |\n| enableElements | 可框选的元素类型                                                                                                                                                                                                                                                                                                                                                                | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |      |\n| immediately    | 是否及时框选, 仅在 [框选模式 mode](#mode) 为 `default` 时生效，[示例](#immediately)                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |      |\n| mode           | 框选的选择模式，[示例](#mode)                                                                                                                                                                                                                                                                                                                                                   | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |      |\n| onSelect       | 框选元素状态回调                                                                                                                                                                                                                                                                                                                                                                | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |      |\n| state          | 被选中时切换到该状态                                                                                                                                                                                                                                                                                                                                                            | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |      |\n| style          | 指定框选时的框样式，[配置项](#style)                                                                                                                                                                                                                                                                                                                                            |                                                                                  | 见下文                    |      |\n| trigger        | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n内置支持四种框选的选择模式：\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ClickSelect.en.md":"---\ntitle: ClickSelect\norder: 3\n---\n\n## Overview\n\nWhen an element is clicked, it will be highlighted.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Focusing on elements\n- Viewing element details\n- Viewing element relationships\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['click-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // Selection spread range\n      state: 'active', // Selected state\n      neighborState: 'neighborActive', // Neighbor node attached state\n      unselectedState: 'inactive', // Unselected node state\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option          | Description                                                                                                                                                                                                                                                        | Type                                                                            | Default        | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | -------------- | -------- |\n| type            | Behavior type name. This behavior is built-in, and you can use it with `type: 'click-select'`.                                                                                                                                                                     | `click-select` \\| string                                                        | `click-select` | ✓        |\n| animation       | Whether to enable animation effects when switching element states                                                                                                                                                                                                  | boolean                                                                         | true           |          |\n| degree          | Controls the highlight spread range, [example](#degree)                                                                                                                                                                                                            | number \\| (event:[Event](/en/api/event#event-object-properties)) => number      | 0              |          |\n| enable          | Whether to enable the click element function, supports dynamic control through functions, [example](#enable)                                                                                                                                                       | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean) | true           |          |\n| multiple        | Whether to allow multiple selections                                                                                                                                                                                                                               | boolean                                                                         | false          |          |\n| state           | The state applied when an element is selected                                                                                                                                                                                                                      | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| neighborState   | The state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements, [example](#neighborstate)                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| unselectedState | The state applied to all other elements except the selected element and its affected neighbor elements when an element is selected, [example](#unselectedState)                                                                                                    | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        |                |          |\n| onClick         | Callback when an element is clicked                                                                                                                                                                                                                                | (event: [Event](/en/api/event#event-object-properties)) => void                 |                |          |\n| trigger         | Press this shortcut key in combination with a mouse click to perform multi-selection, key reference: _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                        | `['shift']`    |          |\n\n### degree\n\nControls the highlight spread range\n\n- For nodes, `0` means only the current node is selected, `1` means the current node and its directly adjacent nodes and edges are selected, and so on.\n- For edges, `0` means only the current edge is selected, `1` means the current edge and its directly adjacent nodes are selected, and so on.\n\n> In the following example, when `degree: 0` only the <span style='color:#E4504D'>red</span> point is highlighted;\n> When `degree: 1` the <span style='color:#E4504D'>red</span> and <span style='color:#FFC40C'>orange</span> points are highlighted.\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\nWhether to enable the click element function\n\nIt can be dynamically controlled through functions, for example, only enabled when a node is selected.\n\n```js\n{\n  //⚠️ Note, you need to set both the node and the canvas, otherwise the user will not listen to the event when clicking the canvas\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\nSimilarly, if you only want edges to be selected:\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\nThe state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // State attached to the directly clicked node\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\nWhen an element is selected, the state applied to all other elements except the selected element and the spread neighbor elements.\n\nBuilt-in states: `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Example\n\n### Click to select nodes and their directly connected nodes\n\n**Clicking a node** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#0f0'>active</span>\n<br>\n**Adjacent nodes** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // Selected node state\n      active: {\n        fill: '#0f0',\n      },\n      // Adjacent node state\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n      // Unselected node state\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ClickSelect.zh.md":"---\ntitle: 点击选中 ClickSelect\norder: 3\n---\n\n## 概述\n\n当鼠标点击元素时，会使元素高亮。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 聚焦元素\n- 查看元素详情\n- 查看元素关系\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['click-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // 选中扩散范围\n      state: 'active', // 选中的状态\n      neighborState: 'neighborActive', // 相邻节点附着状态\n      unselectedState: 'inactive', // 未选中节点状态\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项          | 说明                                                                                                                                                                                                       | 类型                                                                     | 默认值         | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------- | ---- |\n| type            | 交互类型名称。此交互已内置，你可以通过 `type: 'click-select'` 来使用它。                                                                                                                                   | `click-select` \\| string                                                 | `click-select` | ✓    |\n| animation       | 是否在元素状态切换时启用动画效果                                                                                                                                                                           | boolean                                                                  | true           |      |\n| degree          | 控制了高亮扩散范围，[示例](#degree)                                                                                                                                                                        | number \\| (event:[Event](/api/event#事件对象属性)) => number             | 0              |      |\n| enable          | 是否启用点击元素的功能，支持通过函数的方式动态控制是否启用，[示例](#enable)                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)        | true           |      |\n| multiple        | 是否允许多选                                                                                                                                                                                               | boolean                                                                  | false          |      |\n| state           | 当元素被选中时应用的状态                                                                                                                                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| neighborState   | 当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素，[示例](#neighborstate)                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| unselectedState | 当有元素被选中时，除了选中元素及其受影响的邻居元素外，其他所有元素应用的状态，[示例](#unselectedState)                                                                                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` |                |      |\n| onClick         | 点击元素时的回调                                                                                                                                                                                           | (event: [Event](/api/event#事件对象属性)) => void                        |                |      |\n| trigger         | 按下该快捷键配合鼠标点击进行多选，按键参考： _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                 | `['shift']`    |      |\n\n### degree\n\n控制了高亮扩散范围\n\n- 对于节点来说，`0` 表示只选中当前节点，`1` 表示选中当前节点及其直接相邻的节点和边，以此类推。\n- 对于边来说，`0` 表示只选中当前边，`1` 表示选中当前边及其直接相邻的节点，以此类推。\n\n> 如下示例，当 `degree: 0` 仅高亮<span style='color:#E4504D'>红色</span>点;\n> 当 `degree: 1` 高亮<span style='color:#E4504D'>红色</span>和<span style='color:#FFC40C'>橙色</span>点。\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\n是否启用点击元素的功能\n\n可以通过函数的方式动态控制是否启用，例如只有节点被选中时才启用。\n\n```js\n{\n  //⚠️ 注意，这里需要同时设置节点和画布，否则用户点击画布时将不会监听到事件\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\n同理，如果只希望边能被选中：\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\n当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // 被直接点击的节点附着的状态\n      state: 'active',\n      // 相邻的节点附着的状态\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\n当有元素被选中时，除了被选中元素和扩散的邻居元素外，其他所有元素应用的状态。\n\n内置状态： `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 示例\n\n### 点击选中节点及其直接相连的节点\n\n**点击节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#0f0'>active</span>\n<br>\n**相邻节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // 选中节点状态\n      active: {\n        fill: '#0f0',\n      },\n      // 相邻节点状态\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // 相邻节点附着状态\n      neighborState: 'neighborActive',\n      // 未选中节点状态\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CollapseExpand.en.md":"---\ntitle: CollapseExpand\norder: 4\n---\n\n## Overview\n\nCollapseExpand is a built-in behavior in G6 used to implement the expand/collapse functionality for nodes or combos. Through double-click (default) or single-click actions, users can flexibly control the expand and collapse states of graph elements, effectively managing the visualization hierarchy of the graph structure and reducing visual complexity.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Managing large hierarchical graphs, enabling layered browsing of tree or network graphs\n- Simplifying the display of complex graphs, expanding areas of interest as needed\n- Hiding branch nodes that are temporarily not needed, focusing on important information\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates to the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // Change the trigger method to single-click\n      animation: true, // Enable animation effects\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                         | Type                                                                     | Default Value     | Required |\n| ---------- | --------------------------------------------------- | ------------------------------------------------------------------------ | ----------------- | -------- |\n| type       | Behavior type name                                  | `collapse-expand` \\| string                                              | `collapse-expand` | ✓        |\n| animation  | Enable expand/collapse animation effects            | boolean                                                                  | true              |          |\n| enable     | Enable expand/collapse functionality                | boolean \\| ((event: [/en/api/event#event-object-properties]) => boolean) | true              |          |\n| trigger    | Trigger method, can be single-click or double-click | `click` \\| `dblclick`                                                    | `dblclick`        |          |\n| onCollapse | Callback function when collapse is completed        | (id: string) => void                                                     | -                 |          |\n| onExpand   | Callback function when expand is completed          | (id: string) => void                                                     | -                 |          |\n| align      | Align with the target element to avoid view offset  | boolean                                                                  | true              |          |\n\n## Code Examples\n\n### Basic Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // other configurations...\n});\n```\n\n### Use Single-Click to Trigger Expand/Collapse\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // Change the default double-click trigger to single-click\n    },\n  ],\n});\n```\n\n### Custom Expand/Collapse Callback\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`Node ${id} has collapsed`);\n        // Execute custom logic\n      },\n      onExpand: (id) => {\n        console.log(`Node ${id} has expanded`);\n        // Execute custom logic\n      },\n    },\n  ],\n});\n```\n\n### Conditional Enablement of Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // Enable expand/collapse functionality only when the target is a node type\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Disable Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // Disable expand/collapse animation effects\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. How to determine if a node is collapsed?\n\nYou can check the `collapsed` property in the node data:\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. How to programmatically expand or collapse a node?\n\nIn addition to being triggered by user interaction, you can also directly control using [collapseElement](/en/api/element#graphcollapseelementid-options) or [expandElement](/en/api/element#graphexpandelementid-options):\n\n```javascript\n// Collapse node\ngraph.collapseElement('nodeId', { animation: true });\n\n// Expand node\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CollapseExpand.zh.md":"---\ntitle: 展开/收起元素 CollapseExpand\norder: 4\n---\n\n## 概述\n\nCollapseExpand 是 G6 中用于实现节点或组合（Combo）展开/收起功能的内置交互。通过双击（默认）或单击操作，用户可以灵活控制图元素的展开与收起状态，有效管理图结构的可视化层次，降低视觉复杂度。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 管理大型层次结构图，实现树状图或网络图的分层浏览\n- 简化复杂图的展示，按需展开关注区域\n- 隐藏暂时不需要查看的分支节点，聚焦于重要信息\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一 behavior：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // 修改触发方式为单击\n      animation: true, // 启用动画效果\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                           | 类型                                                                      | 默认值            | 必选 |\n| ---------- | ------------------------------ | ------------------------------------------------------------------------- | ----------------- | ---- |\n| type       | 交互类型名称                   | `collapse-expand` \\| string                                               | `collapse-expand` | ✓    |\n| animation  | 是否启用展开/收起动画效果      | boolean                                                                   | true              |      |\n| enable     | 是否启用展开/收起功能          | boolean \\| ((event: [IPointerEvent](/api/event#事件对象属性)) => boolean) | true              |      |\n| trigger    | 触发方式，可选单击或双击       | `click` \\| `dblclick`                                                     | `dblclick`        |      |\n| onCollapse | 完成收起时的回调函数           | (id: string) => void                                                      | -                 |      |\n| onExpand   | 完成展开时的回调函数           | (id: string) => void                                                      | -                 |      |\n| align      | 是否对准目标元素，避免视图偏移 | boolean                                                                   | true              |      |\n\n## 代码示例\n\n### 基础展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // 其他配置...\n});\n```\n\n### 使用单击触发展开/收起\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // 将默认的双击触发改为单击触发\n    },\n  ],\n});\n```\n\n### 自定义展开/收起回调\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`节点 ${id} 已收起`);\n        // 执行自定义逻辑\n      },\n      onExpand: (id) => {\n        console.log(`节点 ${id} 已展开`);\n        // 执行自定义逻辑\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // 只有当目标是节点类型时才启用展开/收起功能\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 关闭动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // 关闭展开/收起动画效果\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 如何判断一个节点是否处于收起状态？\n\n可以通过检查节点数据中的 `collapsed` 属性：\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. 如何以编程方式展开或收起节点？\n\n除了通过用户交互触发，你还可以使用 [collapseElement](/api/element#graphcollapseelementid-options) 或 [expandElement](/api/element#graphexpandelementid-options) 直接控制：\n\n```javascript\n// 收起节点\ngraph.collapseElement('nodeId', { animation: true });\n\n// 展开节点\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CreateEdge.en.md":"---\ntitle: CreateEdge\norder: 5\n---\n\n## Overview\n\nCreateEdge is a built-in behavior in G6 for interactively creating edges on the canvas. After the user triggers the behavior (click or drag), the edge will follow the mouse movement and connect to the target node to complete the creation. If canceled, it will be automatically removed.\n\nAdditionally, this behavior supports customizing the style of the edge, such as color, line style, arrow, etc., to meet different visualization needs.\n\nThe elements that can be connected by this behavior are `node` and `combo`.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Visualization scenarios that require interactive creation of connections between nodes, such as flowcharts, knowledge graphs, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration\n\n```javascript\n// Use default configuration\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['create-edge'], // Directly add, use default configuration\n});\n\n// Or use custom configuration\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // Behavior configuration, create edge by clicking\n      style: {}, // Custom edge style\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                 | Type                                                                                                     | Default       | Required |\n| -------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type     | Behavior type name                                                                                          | string                                                                                                   | `create-edge` | √        |\n| trigger  | The way to trigger the creation of a new edge: `click` means click to trigger; `drag` means drag to trigger | `click` \\| `drag`                                                                                        | `drag`        |          |\n| enable   | Whether to enable this behavior                                                                             | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                          | true          |          |\n| onCreate | Callback function for creating an edge, returns edge data                                                   | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => [EdgeData](/en/manual/data#edge-data-edgedata) | -             |          |\n| onFinish | Callback function for successfully creating an edge                                                         | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => void                                           | -             |          |\n| style    | Style of the newly created edge, [configuration options](#style)                                            | See below                                                                                                | -             |          |\n\n### style\n\nConfigure the style of the newly created edge, for detailed configuration options, please refer to [Element - Edge - General Edge Properties - Style](/en/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## Code Examples\n\n### Basic Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### Custom Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  // Other configurations,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: 'red',\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### Create Edge by Clicking\n\n```javascript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CreateEdge.zh.md":"---\ntitle: 创建边 CreateEdge\norder: 5\n---\n\n## 概述\n\nCreateEdge 是 G6 中用于实现画布中交互式创建边（Edge）的内置交互。用户触发交互（点击或拖拽）后，边会随鼠标移动，连接到目标节点即完成创建，若取消则自动移除。\n\n此外，该交互支持自定义边的样式，如颜色、线条样式、箭头等，以适应不同的可视化需求。\n\n该交互支持连接的元素为 `node` 和 `combo`。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要交互式创建节点间连接关系的可视化场景，如流程图、知识图谱等\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n```javascript\n// 使用默认配置\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['create-edge'], // 直接添加，使用默认配置\n});\n\n// 或使用自定义配置\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // 交互配置，通过点击创建边\n      style: {}, // 边自定义样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                        | 类型                                                                                       | 默认值        | 必选 |\n| -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------- | ---- |\n| type     | 交互类型名称                                                | string                                                                                     | `create-edge` | √    |\n| trigger  | 触发新建边的方式：`click` 表示点击触发；`drag` 表示拖拽触发 | `click` \\| `drag`                                                                          | `drag`        |      |\n| enable   | 是否启用该交互                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                          | true          |      |\n| onCreate | 创建边回调函数，返回边数据                                  | (edge: [EdgeData](/manual/data#边数据edgedata)) => [EdgeData](/manual/data#边数据edgedata) | -             |      |\n| onFinish | 成功创建边回调函数                                          | (edge: [EdgeData](/manual/data#边数据edgedata)) => void                                    | -             |      |\n| style    | 新建边的样式，[配置项](#style)                              | 见下面                                                                                     | -             |      |\n\n### style\n\n配置新创建边的样式，详细配置项请参考 [元素 - 边 - 通用边属性 - 样式](/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## 代码示例\n\n### 基础创建边功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### 自定义创建边功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: red,\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### 使用点击创建边\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragCanvas.en.md":"---\ntitle: DragCanvas\norder: 6\n---\n\n## Overview\n\nDragCanvas is a built-in behavior in G6 for implementing canvas dragging functionality, supporting panning the entire canvas by dragging with a mouse or touching the screen. This is the most basic and commonly used navigation behavior in graph visualization, allowing users to freely explore graph content beyond the current viewport.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Navigating and browsing large charts to view content outside the current viewport\n- Adjusting the view focus to move areas of interest to the center of the viewport\n- Combining with zoom interactions to achieve a complete canvas navigation experience\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // Only allow horizontal dragging\n      key: 'drag-behavior', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                          | Type                                                                                                                                                               | Default                                                                                                           | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | -------- |\n| type        | Behavior type name                                                                                                                                                                                                   | string                                                                                                                                                             | `drag-canvas`                                                                                                     | ✓        |\n| enable      | Whether to enable this behavior                                                                                                                                                                                      | boolean \\| ((event: [Event](/en/api/event#event-object-properties) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(Only enabled when clicking on the canvas) |          |\n| animation   | Drag animation configuration, only effective when using keyboard movement                                                                                                                                            | [ViewportAnimationEffectTiming](/en/api/graph#viewportanimationeffecttiming)                                                                                       | -                                                                                                                 |          |\n| direction   | Allowed drag direction, optional values are: <br/>- Set to `'both'` (default): Allow dragging in any direction <br/>- Set to `'x'`: Only allow horizontal dragging <br/>- Set to `'y'`: Only allow vertical dragging | `'x'` \\| `'y'` \\| `'both'`                                                                                                                                         | `'both'` (no direction restriction)                                                                               |          |\n| range       | Draggable viewport range (in viewport size units), [example](#range)                                                                                                                                                 | number \\| number[]                                                                                                                                                 | Infinity                                                                                                          |          |\n| sensitivity | Distance to trigger a single keyboard movement                                                                                                                                                                       | number                                                                                                                                                             | 10                                                                                                                |          |\n| trigger     | Keyboard keys to trigger dragging, [example](#trigger)                                                                                                                                                               | object                                                                                                                                                             | -                                                                                                                 |          |\n| onFinish    | Callback function when dragging is completed                                                                                                                                                                         | () => void                                                                                                                                                         | -                                                                                                                 |          |\n\n### range\n\n`range` is used to control the draggable range of the canvas:\n\n- Set as a single number: Use the same value for all four directions\n- Set as an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can drag 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can drag 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], 0 means no dragging, Infinity means unlimited dragging.\n\n### trigger\n\n`trigger` allows you to configure keyboard keys to control canvas movement:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for moving up\n    down: ['ArrowDown'], // Shortcut key for moving down\n    left: ['ArrowLeft'], // Shortcut key for moving left\n    right: ['ArrowRight'] // Shortcut key for moving right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Dragging Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### Only Allow Horizontal Dragging\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // Only allow horizontal dragging\n    },\n  ],\n});\n```\n\n### Limit Dragging Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // Limit dragging range to 1.5 viewport sizes\n    },\n  ],\n});\n```\n\n### Control Movement with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // Add smooth animation effect\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. Difference between DragCanvas and other behaviors\n\n- `DragCanvas` is used for dragging the entire canvas view\n- `DragElement` is used for dragging individual graph elements (nodes/edges/combinations)\n- `ScrollCanvas` is used for scrolling the canvas with the mouse wheel without changing the zoom ratio\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragCanvas.zh.md":"---\ntitle: 拖拽画布 DragCanvas\norder: 6\n---\n\n## 概述\n\nDragCanvas 是 G6 中用于实现画布拖拽功能的内置交互，支持通过鼠标或触摸屏幕拖动来平移整个画布。这是图可视化中最基础且常用的导航交互，让用户能够自由探索超出当前视口的图内容。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 导航和浏览大型图表，查看当前视口外的内容\n- 调整视图焦点，将感兴趣的区域移动到视口中心\n- 与缩放交互结合，实现完整的画布导航体验\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // 只允许水平方向拖拽\n      key: 'drag-behavior', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                                                                   | 类型                                                                                                                                                 | 默认值                                                                                      | 必选 |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                                                           | string                                                                                                                                               | `drag-canvas`                                                                               | ✓    |\n| enable      | 是否启用该交互                                                                                                                                         | boolean \\| ((event: [Event](/api/event#事件对象属性) \\| [KeyboardEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(仅在点击画布时启用) |      |\n| animation   | 拖拽动画配置，仅在使用按键移动时有效                                                                                                                   | [ViewportAnimationEffectTiming](/api/graph#viewportanimationeffecttiming)                                                                            | -                                                                                           |      |\n| direction   | 允许的拖拽方向，可选值有：<br/>- 设为 `'both'`（默认）：允许在任意方向拖拽 <br/>- 设为 `'x'`：只允许水平方向拖拽 <br/>- 设为 `'y'`：只允许垂直方向拖拽 | `'x'` \\| `'y'` \\| `'both'`                                                                                                                           | `'both'` (不限制方向)                                                                       |      |\n| range       | 可拖拽的视口范围(以视口大小为单位)，[示例](#range)                                                                                                     | number \\| number[]                                                                                                                                   | Infinity                                                                                    |      |\n| sensitivity | 触发一次按键移动的距离                                                                                                                                 | number                                                                                                                                               | 10                                                                                          |      |\n| trigger     | 触发拖拽的键盘按键，[示例](#trigger)                                                                                                                   | object                                                                                                                                               | -                                                                                           |      |\n| onFinish    | 拖拽完成时的回调函数                                                                                                                                   | () => void                                                                                                                                           | -                                                                                           |      |\n\n### range\n\n`range` 用于控制画布可拖拽的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以拖拽2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可拖拽1个视口，左右方向可拖拽2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能拖拽，Infinity表示无限拖拽。\n\n### trigger\n\n`trigger` 允许你配置键盘按键来控制画布移动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上移动的快捷键\n    down: ['ArrowDown'], // 向下移动的快捷键\n    left: ['ArrowLeft'], // 向左移动的快捷键\n    right: ['ArrowRight'] // 向右移动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础拖拽功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### 只允许水平拖拽\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // 只允许水平拖拽\n    },\n  ],\n});\n```\n\n### 限制拖拽范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // 限制拖拽范围为1.5个视口大小\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制移动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // 添加平滑动画效果\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. DragCanvas与其他交互的区别\n\n- `DragCanvas` 用于拖拽整个画布视图\n- `DragElement` 用于拖拽单个图元素（节点/边/组合）\n- `ScrollCanvas` 用于滚轮滚动画布，不改变缩放比例\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragElement.en.md":"---\ntitle: DragElement\norder: 7\n---\n\n## Overview\n\nDragElement is a built-in behavior in G6 for implementing **element dragging** functionality. It has the following core features:\n\n1. **Support for multiple element types**: Supports dragging of both nodes and combos simultaneously\n2. **Intelligent multi-selection**: Supports dragging multiple selected elements at the same time\n3. **Visual feedback**: Provides various visual feedback mechanisms such as ghost nodes, edge visibility, mouse styles, etc.\n4. **Flexible drag effects**: Supports various drag operation effects such as move, link, free drag, etc.\n5. **Parent-child relationship handling**: Automatically handles element hierarchy during dragging, especially when dealing with combo structures\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // Enable ghost node\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type       | Behavior type name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | `drag-element`                                 | ✓        |\n| key        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| enable     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| animation  | Whether to enable drag animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | boolean                                                  | true                                           |          |\n| 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`                                     |          |\n| dropEffect | Defines the operation effect after dragging ends, optional values are: <br/>- `link`: Set the dragged element as a child of the target element <br/>- `move`: Move the element and automatically update the size of the parent element (such as combo) <br/>- `none`: Only update the position of the drag target without performing other operations                                                                                                                                                           | `link` \\| `move` \\| `none`                               | `move`                                         |          |\n| hideEdge   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |          |\n| shadow     | Whether to enable ghost nodes, which use a shape to follow the mouse movement. [Customize ghost node style](#shadow-style-configuration) ⚠️Note: React nodes do not support enabling                                                                                                                                                                                                                                                                                                                            | boolean                                                  | false                                          |          |\n| cursor     | Customize the mouse style during dragging, [configuration options](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                     | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n### shadow Style Configuration\n\nWhen `shadow: true` is enabled, you can customize the style of the ghost node with the following properties:\n\n| Option               | Description                       | Type                                | Default                                     |\n| -------------------- | --------------------------------- | ----------------------------------- | ------------------------------------------- |\n| shadowFill           | Ghost node fill color             | string                              | `#F3F9FF`                                   |\n| shadowFillOpacity    | Ghost node fill color opacity     | number                              | 0.5                                         |\n| shadowStroke         | Ghost node stroke color           | string                              | `#1890FF`                                   |\n| shadowStrokeOpacity  | Ghost node stroke opacity         | number                              | 0.9                                         |\n| shadowLineDash       | Ghost node dash configuration     | number[]                            | [5, 5]                                      |\n| shadowZIndex         | Ghost node rendering level        | number                              | 100                                         |\n| shadowWidth          | Ghost node width                  | number                              | Width of the target element's bounding box  |\n| shadowHeight         | Ghost node height                 | number                              | Height of the target element's bounding box |\n| shadowOpacity        | Overall opacity of the ghost node | number                              |                                             |\n| shadowLineWidth      | Ghost node line width             | number                              |                                             |\n| shadowLineCap        | Ghost node line cap style         | `'butt'` \\| `'round'` \\| `'square'` |                                             |\n| shadowLineJoin       | Ghost node line join style        | `'miter'` \\| `'round'` \\| `'bevel'` |                                             |\n| shadowLineDashOffset | Ghost node dash offset            | number                              |                                             |\n| shadowCursor         | Ghost node mouse style            | string                              |                                             |\n| shadowVisibility     | Ghost node visibility             | `'visible'` \\| `'hidden'`           |                                             |\n\nExample configuration:\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // Customize ghost node style\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> Note: The ghost node style inherits from [BaseStyleProps](/en/manual/element/shape/properties#baseshapestyle), the above configuration items are obtained by adding the `shadow` prefix to the property name.\n\n## Code Examples\n\n### Multi-selection Dragging\n\nNeed to cooperate with the `click-select` behavior to achieve multi-selection, and then associate the selected state through the `state` parameter:\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // All nodes in the selected state will be moved simultaneously during dragging\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/DragElement.zh.md":"---\ntitle: 拖拽元素 DragElement\norder: 7\n---\n\n## 概述\n\nDragElement 是 G6 中用于实现 **元素拖拽** 功能的内置交互。它具有以下核心特性：\n\n1. **多元素类型支持**：可以同时支持节点（Node）和组合（Combo）的拖拽\n2. **智能多选**：支持同时拖拽多个选中状态的元素\n3. **视觉反馈**：提供幽灵节点、边的显隐、鼠标样式等多种视觉反馈机制\n4. **灵活的拖拽效果**：支持移动、链接、自由拖拽等多种拖拽操作效果\n5. **父子关系处理**：自动处理拖拽过程中的元素层级关系，特别是在处理 Combo 结构时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // 启用拖拽幽灵节点\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type       | 交互类型名称                                                                                                                                                                                                                                                                                                                                            | string                                                   | `drag-element`                                 | ✓    |\n| key        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| enable     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| animation  | 是否启用拖拽动画                                                                                                                                                                                                                                                                                                                                        | boolean                                                  | true                                           |      |\n| state      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| dropEffect | 定义拖拽结束后的操作效果，可选值有：<br/>- `link`: 将拖拽元素设置为目标元素的子元素 <br/>- `move`: 移动元素并自动更新父元素（如 Combo）的尺寸 <br/>- `none`: 仅更新拖拽目标的位置，不执行其他操作                                                                                                                                                       | `link` \\| `move` \\| `none`                               | `move`                                         |      |\n| hideEdge   | 控制拖拽过程中边的显示状态，可选值有： <br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                     | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |      |\n| shadow     | 是否启用幽灵节点，即用一个图形代替节点跟随鼠标移动。[自定义幽灵节点样式](#shadow-样式配置) ⚠️注意：React 节点不支持启用                                                                                                                                                                                                                                 | boolean                                                  | false                                          |      |\n| cursor     | 自定义鼠标样式，[配置项](#cursor)                                                                                                                                                                                                                                                                                                                       | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n### shadow 样式配置\n\n当启用 `shadow: true` 时，可以通过以下属性自定义幽灵节点的样式：\n\n| 配置项               | 说明                   | 类型                                | 默认值               |\n| -------------------- | ---------------------- | ----------------------------------- | -------------------- |\n| shadowFill           | 幽灵节点填充色         | string                              | `#F3F9FF`            |\n| shadowFillOpacity    | 幽灵节点填充色透明度   | number                              | 0.5                  |\n| shadowStroke         | 幽灵节点描边颜色       | string                              | `#1890FF`            |\n| shadowStrokeOpacity  | 幽灵节点描边透明度     | number                              | 0.9                  |\n| shadowLineDash       | 幽灵节点虚线配置       | number[]                            | [5, 5]               |\n| shadowZIndex         | 幽灵节点渲染层级       | number                              | 100                  |\n| shadowWidth          | 幽灵节点宽度           | number                              | 目标元素的包围盒宽度 |\n| shadowHeight         | 幽灵节点高度           | number                              | 目标元素的包围盒高度 |\n| shadowOpacity        | 幽灵节点整体透明度     | number                              |                      |\n| shadowLineWidth      | 幽灵节点线宽度         | number                              |                      |\n| shadowLineCap        | 幽灵节点线段端点样式   | `'butt'` \\| `'round'` \\| `'square'` |                      |\n| shadowLineJoin       | 幽灵节点线段连接处样式 | `'miter'` \\| `'round'` \\| `'bevel'` |                      |\n| shadowLineDashOffset | 幽灵节点虚线偏移量     | number                              |                      |\n| shadowCursor         | 幽灵节点鼠标样式       | string                              |                      |\n| shadowVisibility     | 幽灵节点可见性         | `'visible'` \\| `'hidden'`           |                      |\n\n示例配置：\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // 自定义幽灵节点样式\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> 注意：幽灵节点样式继承自 [BaseStyleProps](/manual/element/shape/properties#baseshapestyle)，上述配置项是在属性名前添加 `shadow` 前缀得到的。\n\n## 代码示例\n\n### 多选推拽\n\n需要配合 `click-select` 行为实现多选，然后通过 `state` 参数关联选中状态：\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // 拖拽时会同时移动所有 selected 状态的节点\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/DragElementForce.en.md":"---\ntitle: DragElementForce\norder: 8\n---\n\n## Overview\n\nDragElementForce 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.\n\n<img alt=\"Effect of DragElementForce\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // Fix node position after dragging\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type                                       | Behavior type name, set `type: 'drag-element-force'` to enable this behavior                                                                                                                                                                                                                                                                                                                                                                                                                                    | string                                                   | `drag-element-force`                           | ✓        |\n| key                                        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| fixed                                      | Whether to keep the node position fixed after dragging ends, boolean values represent: <br/>- true: After dragging ends, the node's position will remain fixed and not be affected by the layout algorithm <br/>- false: After dragging ends, the node's position will continue to be affected by the layout algorithm                                                                                                                                                                                          | boolean                                                  | false                                          |          |\n| enable                                     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| 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`                                     |          |\n| hideEdge                                   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                          |\n| cursor                                     | Customize the mouse style during dragging, [example](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                                   | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger                                    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n## FAQ\n\n### 1. What is the difference between DragElementForce and DragElement?\n\n- `DragElementForce` is specifically used for `d3-force` or `d3-force-3d` layouts, and recalculates the layout in real-time during dragging\n- `DragElement` is a general drag interaction and does not trigger layout recalculation\n\n## Practical Example\n\n### Mesh Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### Fix Dragged Nodes\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Shadow Style\n\n### shadow{[BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#%E7%BB%98%E5%9B%BE%E5%B1%9E%E6%80%A7)}\n\n<details><summary>An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.</summary>\n\nTextStyleProps includes the following properties:\n\n- fill\n- fontSize\n- fontWeight\n- ...\n\nicon{TextStyleProps} means you need to use the following property names:\n\n- iconFill\n- iconFontSize\n- iconFontWeight\n- ...\n\n</details>\n","packages/site/docs/manual/behavior/DragElementForce.zh.md":"---\ntitle: 力导向拖拽元素 DragElementForce\norder: 8\n---\n\n## 概述\n\nDragElementForce 是 G6 中用于实现 `d3-force` 和 `d3-force-3d` 布局下节点拖拽的内置交互。在拖拽过程中会 **实时重新计算布局**，使得图的布局能够动态调整以适应节点的新位置。\n\n<img alt=\"力导向拖拽元素效果图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // 拖拽后固定节点位置\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                                     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type                                       | 交互类型名称，这里设置 `type: 'drag-element-force'` 启用此交互                                                                                                                                                                                                                                                                                          | string                                                   | `drag-element-force`                           | ✓    |\n| key                                        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| fixed                                      | 在拖拽结束后，节点是否保持固定位置，布尔值代表：<br/>- true: 在拖拽结束后，节点的位置将保持固定，不受布局算法的影响 <br/>- false: 在拖拽结束后，节点的位置将继续受到布局算法的影响                                                                                                                                                                      | boolean                                                  | false                                          |      |\n| enable                                     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| state                                      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| hideEdge                                   | 控制拖拽过程中边的显示状态，可选值有：<br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                      | `none` \\| `all` \\| `in` \\| `out` \\| `both`                                      | `none`                                                                                                                                                                                                                                                                                                                                                  |                                                          |\n| cursor                                     | 自定义鼠标样式，[示例](#cursor)                                                                                                                                                                                                                                                                                                                         | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger                                    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n## 常见问题\n\n### 1. DragElementForce 和 DragElement 有什么区别？\n\n- `DragElementForce` 专门用于 `d3-force` 或 `d3-force-3d` 布局，拖拽时会实时重新计算布局\n- `DragElement` 是通用的拖拽交互，不会触发布局重新计算\n\n## 实际案例\n\n### 网格效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### 固定被拖拽的节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FixElementSize.en.md":"---\ntitle: FixElementSize\norder: 9\n---\n\n## Overview\n\nFixElementSize is a built-in interaction provided by G6, used to **maintain the size of certain elements within nodes unchanged during the zooming process.** It enhances visual consistency and operability during zooming.\nBy listening to viewport changes, it automatically scales elements marked as \"fixed size\" to ensure they maintain a relatively constant display size at different zoom levels. It supports global enablement and also allows control over specific elements or nodes as needed.\n\n## Use Cases\n\nThis interaction is mainly used for:\n\n- Graphical elements or embedded components (buttons, labels, etc.) that need to maintain a fixed visual size\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // Enable this interaction\n      state: 'selected', // State of elements to fix size\n      reset: true, // Restore style when elements are redrawn\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                    | Type                                                                         | Default                                                                                             | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------- |\n| type        | Interaction type name                                                                                                                                                                                          | string                                                                       | `fix-element-size`                                                                                  | ✓        |\n| enable      | Whether to enable this interaction, [example](#enable)                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean) | true                                                                                                |          |\n| reset       | Whether to restore style when elements are redrawn                                                                                                                                                             | boolean                                                                      | `false`                                                                                             |          |\n| state       | Specify the state of elements to fix size                                                                                                                                                                      | string                                                                       | \"\"                                                                                                  |          |\n| node        | Node configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed, [example](#node)                                     | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| nodeFilter  | Node filter, used to filter which nodes maintain a fixed size during zooming                                                                                                                                   | (datum: [NodeData](/manual/data#nodedata)) => boolean                        | `() => true`                                                                                        |          |\n| edge        | Edge configuration item, used to define which attributes maintain a fixed visual size. By default, the lineWidth and labelFontSize attributes are fixed, usage is the same as [node configuration item](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |          |\n| edgeFilter  | Edge filter, used to filter which edges maintain a fixed size during zooming                                                                                                                                   | (datum: [EdgeData](/manual/data#edgedata)) => boolean                        | `() => true`                                                                                        |          |\n| combo       | Combo configuration item, used to define which attributes maintain a fixed visual size. By default, the entire Combo will be fixed, usage is the same as [node configuration item](#node)                      | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| comboFilter | Combo filter, used to filter which Combos maintain a fixed size during zooming                                                                                                                                 | (datum: [ComboData](/manual/data#combodata)) => boolean                      | `() => true`                                                                                        |          |\n\n### enable\n\nWhether to enable the fixed element size interaction. By default, it is enabled when zooming out the canvas\n\nBy default, it is enabled when zooming out the canvas, set `enable: (event) => event.data.scale < 1`; if you want to enable it when zooming in, set `enable: (event) => event.data.scale > 1`; if you want to enable it when both zooming in and out, set `enable: true`\n\n### node\n\nNode configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed\n\n**Example**\n\nIf you want to fix the lineWidth of the main shape of the node during zooming, you can configure it like this:\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\nIf you want to keep the size of the element label unchanged during zooming, you can configure it like this:\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| Parameter | Description                                                                                                                                                        | Type                                                   | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | ------- | -------- |\n| shape     | Specify the shape to fix size, it can be the class name of the shape, or a function that receives all shapes constituting the element and returns the target shape | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -       | ✓        |\n| fields    | Specify the fields of the shape to fix size. If not specified, the entire shape size is fixed by default                                                           | string[]                                               | -       | ✘        |\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FixElementSize.zh.md":"---\ntitle: 缩放画布时固定元素大小 FixElementSize\norder: 9\n---\n\n## 概述\n\nFixElementSize 是 G6 提供的一种内置交互，用于在视图缩放过程中，**保持节点中某些元素的尺寸不随缩放变化。** 提升缩放过程中的视觉一致性与可操作性。\n通过监听视口变化，自动对标记为“固定尺寸”的元素进行缩放补偿，确保它们在不同缩放级别下保持相对恒定的显示尺寸。支持全局启用，也支持按需控制具体元素或节点的适配行为。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要固定视觉大小的图形元素或嵌入式组件（按钮、标签等）\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // 开启该交互\n      state: 'selected', // 要固定大小的元素状态\n      reset: true, // 元素重绘时还原样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                              | 类型                                                              | 默认值                                                                                              | 必选 |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                      | string                                                            | `fix-element-size`                                                                                  | √    |\n| enable      | 是否启用该交互，[示例](#enable)                                                                                   | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean) | true                                                                                                |      |\n| reset       | 元素重绘时是否还原样式                                                                                            | boolean                                                           | `false`                                                                                             |      |\n| state       | 指定要固定大小的元素状态                                                                                          | string                                                            | \"\"                                                                                                  |      |\n| node        | 节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定，[示例](#node)   | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| nodeFilter  | 节点过滤器，用于过滤哪些节点在缩放过程中保持固定大小                                                              | (datum: [NodeData](/manual/data#节点数据nodedata)) => boolean     | `() => true`                                                                                        |      |\n| edge        | 边配置项，用于定义哪些属性在视觉上保持固定大小。默认固定 lineWidth、labelFontSize 属性，用法同[node配置项](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |      |\n| edgeFilter  | 边过滤器，用于过滤哪些边在缩放过程中保持固定大小                                                                  | (datum: [EdgeData](/manual/data#边数据edgedata)) => boolean       | `() => true`                                                                                        |      |\n| combo       | Combo 配置项，用于定义哪些属性在视觉上保持固定大小。默认整个 Combo 将被固定，用法同[node配置项](#node)            | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| comboFilter | Combo 过滤器，用于过滤哪些 Combo 在缩放过程中保持固定大小                                                         | (datum: [ComboData](/manual/data#组合数据combodata)) => boolean   | `() => true`                                                                                        |      |\n\n### enable\n\n是否启用固定元素大小交互。默认在缩小画布时启用\n\n默认在缩小画布时启用，设置 `enable: (event) => event.data.scale < 1`；如果希望在放大画布时启用，设置 `enable: (event) => event.data.scale > 1`；如果希望在放大缩小画布时都启用，设置 `enable: true`\n\n### node\n\n节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定\n\n**示例**\n\n如果在缩放过程中希望固定节点主图形的 lineWidth，可以这样配置：\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\n如果在缩放过程中想保持元素标签大小不变，可以这样配置：\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| 参数   | 描述                                                                                                 | 类型                                                   | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------ | ---- |\n| shape  | 指定要固定大小的图形，可以是图形的类名字，或者是一个函数，该函数接收构成元素的所有图形并返回目标图形 | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -      | ✓    |\n| fields | 指定要固定大小的图形属性字段。如果未指定，则默认固定整个图形的大小                                   | string[]                                               | -      | ✘    |\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FocusElement.en.md":"---\ntitle: FocusElement\norder: 10\n---\n\n## Overview\n\nFocusElement is a built-in behavior in G6 used to implement the element focusing feature, allowing elements to be focused to the center of the view by clicking on them. This behavior helps users quickly locate and focus on specific graph elements.\n\n## Use Cases\n\n- Quickly center the focused nodes or edges in the display\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                                                                                                 | Type                                                            | Default                                | Required |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | -------- |\n| type      | Behavior type name                                                                                                                                                                                                                                                                                                                                                          | string                                                          | `focus-element`                        | ✓        |\n| animation | Focus animation settings                                                                                                                                                                                                                                                                                                                                                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |          |\n| enable    | Whether to enable the focus feature                                                                                                                                                                                                                                                                                                                                         | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |          |\n| trigger   | Press this shortcut key in combination with mouse perform foucs element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | [`shift`]                              |          |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## Code Examples\n\n### Basic Focus Feature\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### Custom Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### Conditional Focus Enablement\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // Enable focus only for nodes, not edges\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FocusElement.zh.md":"---\ntitle: 聚焦元素 FocusElement\norder: 10\n---\n\n## 概述\n\nFocusElement 是 G6 中用于实现元素聚焦功能的内置交互，支持通过点击元素将其聚焦到视图中心。这个交互可以帮助用户快速定位和关注特定的图元素。\n\n## 使用场景\n\n- 快速将关注的节点或边居中显示\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                                                                                           | 类型                                                            | 默认值                                 | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | ---- |\n| type      | 交互类型名称                                                                                                                                                                                                                                                   | string                                                          | `focus-element`                        | ✓    |\n| animation | 聚焦动画效果设置                                                                                                                                                                                                                                               | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |      |\n| enable    | 是否启用聚焦功能                                                                                                                                                                                                                                               | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |      |\n| trigger   | 同时按下快捷键才能聚焦元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | []                                     |      |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## 代码示例\n\n### 基础聚焦功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### 自定义动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用聚焦\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // 只对节点启用聚焦，边不聚焦\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/HoverActivate.en.md":"---\ntitle: HoverActivate\norder: 11\n---\n\n## Overview\n\nHoverActivate is a built-in behavior in G6 used to implement the hover activation effect on elements. When the mouse hovers over nodes or edges, it automatically triggers visual feedback such as highlighting and displaying. This behavior is an important means of enhancing data exploration in graph visualization, helping users quickly focus on target elements and obtain related information.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly locating elements of interest in complex relationship graphs\n- Displaying additional information of nodes through hover\n- Highlighting connection paths by activating edges when analyzing relationships between nodes\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option        | Description                                 | Type                                           | Default          | Required |\n| ------------- | ------------------------------------------- | ---------------------------------------------- | ---------------- | -------- |\n| type          | Behavior type name                          | string                                         | `hover-activate` | ✓        |\n| animation     | Whether to enable animation                 | boolean                                        | true             |          |\n| enable        | Whether to enable hover feature             | boolean \\| ((event: IPointerEvent) => boolean) | true             |          |\n| degree        | Degree of relationship to activate elements | number \\| ((event: IPointerEvent) => number);  | 0                |          |\n| direction     | Specify edge direction                      | `both` \\| `in` \\| `out`                        | `both`           |          |\n| state         | State of activated elements                 | string                                         | `active`         |          |\n| inactiveState | State of inactive elements                  | string                                         | -                |          |\n| onHover       | Callback when element is hovered            | (event: IPointerEvent) => void                 | -                |          |\n| onHoverEnd    | Callback when hover ends                    | (event: IPointerEvent) => void                 | -                |          |\n\n### enable\n\n`enable` is used to control whether to enable hover highlighting of elements, and can receive a function for dynamic control\n\nFor example: Enable hover highlighting only for nodes\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hover Usage\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n### Node Trigger Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### Flowchart Node Hover Next Node Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/behavior/HoverActivate.zh.md":"---\ntitle: 悬停激活 HoverActivate\norder: 11\n---\n\n## 概述\n\nHoverActivate 是 G6 中用于实现元素悬停激活效果的内置交互，当鼠标悬停在节点或边上时，会自动触发高亮、显示等视觉反馈。该交互是图可视化中增强数据探索的重要手段，有助于用户快速聚焦目标元素并获取相关信息。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 在复杂关系图中快速定位关注元素\n- 通过悬停信息展示节点额外信息\n- 分析节点间关联关系时，通过激活边凸显连接路径\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项        | 说明                 | 类型                                           | 默认值           | 必选 |\n| ------------- | -------------------- | ---------------------------------------------- | ---------------- | ---- |\n| type          | 交互类型名称         | string                                         | `hover-activate` | ✓    |\n| animation     | 是否开启动画效果     | boolean                                        | true             |      |\n| enable        | 是否开启悬浮元素功能 | boolean \\| ((event: IPointerEvent) => boolean) | true             |      |\n| degree        | 激活元素的n度关系    | number \\| ((event: IPointerEvent) => number);  | 0                |      |\n| direction     | 指定边方向           | `both` \\| `in` \\| `out`                        | `both`           |      |\n| state         | 激活元素的状态       | string                                         | `active`         |      |\n| inactiveState | 不激活元素的状态     | string                                         | -                |      |\n| onHover       | 当元素被悬停时的回调 | (event: IPointerEvent) => void                 | -                |      |\n| onHoverEnd    | 当悬停结束时的回调   | (event: IPointerEvent) => void                 | -                |      |\n\n### enable\n\n`enable` 用于控制是否开启元素的悬浮高亮，可接收一个函数来动态控制\n\n例如：只有节点开启悬浮高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础悬浮用法\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n### 节点触发高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### 流程图移入节点 下一步节点高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/behavior/LassoSelect.en.md":"---\ntitle: LassoSelect\norder: 12\n---\n\n## Overview\n\nClick and drag the mouse to draw an **irregular** box to enclose elements, and the elements within the selected range will be selected.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly selecting a batch of elements, making it easier to avoid elements you don't want to select\n- Quickly deselecting a batch of elements, making it easier to avoid elements you want to keep\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                      | Description                                                                                                                                                                                                                               | Type                                                                                                                           | Default                   | Required |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | -------- |\n| type                        | Behavior type name. This plugin is built-in, you can use it by `type: 'lasso-select'`.                                                                                                                                                    | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓        |\n| animation                   | Whether to enable animation                                                                                                                                                                                                               | boolean                                                                                                                        | false                     |          |\n| enable                      | Whether to enable lasso selection                                                                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean)                                                   | true                      |          |\n| enableElements              | Types of elements that can be selected                                                                                                                                                                                                    | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |          |\n| [immediately](#immediately) | Whether to select immediately, only effective when [selection mode](#mode) is `default`                                                                                                                                                   | boolean                                                                                                                        | false                     |          |\n| [mode](#mode)               | Selection mode                                                                                                                                                                                                                            | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |          |\n| onSelect                    | Callback for selected element state                                                                                                                                                                                                       | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |          |\n| state                       | State to switch to when selected                                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |          |\n| [style](#style)             | Style of the box during selection                                                                                                                                                                                                         | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [Default](#style)         |          |\n| trigger                     | Press this shortcut key along with mouse click to select **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: [], // No need for other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nSelection mode\n\n- `union`: Keep the current state of selected elements and add the specified state.\n- `intersect`: Retain the specified state if the selected elements already have it; otherwise, clear the state.\n- `diff`: Toggle the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Property          | Description             | Type                                     | Default   |\n| ----------------- | ----------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style             | string                                   |           |\n| fill              | Fill color              | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity            | number \\| string                         | 0.1       |\n| isBillboard       | Billboard mode          | boolean                                  |           |\n| isSizeAttenuation | Size attenuation        | boolean                                  |           |\n| lineCap           | Line cap style          | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash line config        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash line offset        | number                                   |           |\n| lineJoin          | Line join style         | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width              | number \\| string                         | 1         |\n| opacity           | Overall opacity         | number \\| string                         |           |\n| radius            | Rectangle corner radius | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur level       | number                                   |           |\n| shadowColor       | Shadow color            | string                                   |           |\n| shadowOffsetX     | Shadow X offset         | number                                   |           |\n| shadowOffsetY     | Shadow Y offset         | number                                   |           |\n| stroke            | Stroke color            | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity          | number \\| string                         |           |\n| visibility        | Visibility              | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level         | number                                   | 2         |\n\n**Example**:\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\nPress this shortcut key along with mouse click to select, if set to an **empty array**, it means mouse click to select without needing to press other keys.\n\nNote that setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to be disabled. They cannot be configured simultaneously.\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/LassoSelect.zh.md":"---\ntitle: 套索选择 LassoSelect\norder: 12\n---\n\n## 概述\n\n鼠标点击拖出一个 **不规则的** 框框笼罩元素，精准框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素，并且更容易的避开不想选的元素\n- 快速取消选中一批元素，并且更容易的避开想保留的元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                      | 说明                                                                                                                                                                                                          | 类型                                                                                                                           | 默认值                    | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---- |\n| type                        | 交互类型名称。此插件已内置，你可以通过 `type: 'lasso-select'` 来使用它。                                                                                                                                      | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓    |\n| animation                   | 是否启用动画                                                                                                                                                                                                  | boolean                                                                                                                        | false                     |      |\n| enable                      | 是否启用框选功能                                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                              | true                      |      |\n| enableElements              | 可框选的元素类型                                                                                                                                                                                              | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |      |\n| [immediately](#immediately) | 是否及时框选, 仅在[框选模式 mode](#mode)为 `default` 时生效                                                                                                                                                   | boolean                                                                                                                        | false                     |      |\n| [mode](#mode)               | 框选的选择模式                                                                                                                                                                                                | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |      |\n| onSelect                    | 框选元素状态回调                                                                                                                                                                                              | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |      |\n| state                       | 被选中时切换到该状态                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |      |\n| [style](#style)             | 框选时的 框样式                                                                                                                                                                                               | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [默认值](#style)          |      |\n| trigger                     | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n框选的选择模式\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\n按下该快捷键配合鼠标点击进行框选，若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合。\n\n注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md":"---\ntitle: OptimizeViewportTransform\norder: 13\n---\n\n## Overview\n\nOptimizeViewportTransform is a built-in behavior in G6 used to enhance the performance of large-scale graph behaviors.\n\nThis behavior implements a **selective rendering strategy**, temporarily hiding non-critical visual elements during viewport transformations (such as dragging, zooming, scrolling, etc.) to significantly reduce rendering computation load, improve frame rate, and response speed. After the viewport transformation operation ends, the system automatically restores the visibility of all elements after a set delay to ensure complete visual presentation.\n\nThis behavior is implemented based on the [event system](/en/api/event) by listening to the `GraphEvent.BEFORE_TRANSFORM` and `GraphEvent.AFTER_TRANSFORM` events, precisely capturing the start and end timing of viewport transformations, and dynamically controlling element visibility. Therefore, it must be used in conjunction with viewport operation behaviors (such as `drag-canvas`, `zoom-canvas`, or `scroll-canvas`) to be effective.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Smooth behavior of large-scale graphs (thousands of nodes/edges)\n- Performance-sensitive application scenarios\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // Specify an identifier for the behavior for dynamic updates\n      debounce: 300, // Set a longer debounce time\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                          | Type                                   | Default                       | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | -------- |\n| type     | Behavior type name                                                                                                   | string                                 | `optimize-viewport-transform` | ✓        |\n| enable   | Whether to enable this behavior                                                                                      | boolean \\| ((event: Event) => boolean) | true                          |          |\n| debounce | How long after the operation ends to restore the visibility of all elements (milliseconds)                           | number                                 | 200                           |          |\n| shapes   | Specify the graphical elements that should remain visible during canvas operations, [configuration options](#shapes) | function                               | `(type) => type === 'node'`   |          |\n\n### Shapes\n\n`shapes` is used to specify the graphical elements that need to remain visible during canvas operations. By default, nodes are always visible, while edges and combos are temporarily hidden during canvas operations to improve performance.\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // Dynamically decide whether to remain visible based on element type and graphical object\n    if (type === 'node') return true; // All nodes remain visible\n    if (type === 'edge' && shape.get('importante')) return true; // Important edges remain visible\n    return false; // Other graphics are hidden\n  };\n}\n```\n\n[Example](#keep-specific-elements-visible)\n\n## Code Examples\n\n### Basic Optimization Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### Custom Debounce Time\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // Set a longer debounce time, restoring visibility of all elements 0.5 seconds after the operation stops\n    },\n  ],\n});\n```\n\n### Keep Specific Elements Visible\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 Try dragging the canvas to see the effect\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Enable/Disable Optimization Based on Graph Element Count\n\nYou can dynamically decide whether to enable optimization based on the number of graph elements:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // Enable optimization when exceeding 500 elements\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. When should this behavior be used?\n\nWhen the graph contains a large number of nodes and edges (usually more than 500 elements), using this behavior can significantly improve operational smoothness. It is especially useful in environments with high performance requirements or limited hardware performance.\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md":"---\ntitle: 优化视口变换 OptimizeViewportTransform\norder: 13\n---\n\n## 概述\n\nOptimizeViewportTransform 是 G6 中用于提升大规模图表交互性能的内置交互。\n\n该交互通过实现**选择性渲染策略**，在视口变换过程中（即用户进行拖拽、缩放、滚动等操作时）临时隐藏非关键视觉元素，从而显著降低渲染计算负载，提高帧率和响应速度。当视口变换操作结束后，系统会在设定的延迟时间后自动恢复所有元素的可见性，确保完整的视觉呈现。\n\n此交互基于 [事件系统](/api/event) 实现，通过监听 `GraphEvent.BEFORE_TRANSFORM` 和 `GraphEvent.AFTER_TRANSFORM` 事件，精确捕捉视口变换的开始和结束时机，进而执行元素可见性的动态控制。因此，必须与视口操作类交互（如 `drag-canvas`、`zoom-canvas` 或 `scroll-canvas`）配合使用才能发挥作用。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 大规模图表（上千节点/边）的流畅交互\n- 性能敏感的应用场景\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // 为交互指定标识符，方便动态更新\n      debounce: 300, // 设置更长的防抖时间\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                          | 类型                                   | 默认值                        | 必选 |\n| -------- | ------------------------------------------------------------- | -------------------------------------- | ----------------------------- | ---- |\n| type     | 交互类型名称                                                  | string                                 | `optimize-viewport-transform` | ✓    |\n| enable   | 是否启用该交互                                                | boolean \\| ((event: Event) => boolean) | true                          |      |\n| debounce | 操作结束后多长时间恢复显示所有元素（毫秒）                    | number                                 | 200                           |      |\n| shapes   | 指定在操作画布过程中始终保持可见的图形元素，[配置项](#shapes) | function                               | `(type) => type === 'node'`   |      |\n\n### Shapes\n\n`shapes` 用于指定在画布操作过程中需要保持可见的图形元素。默认情况下，节点始终可见，而边和组合在操作画布时会被临时隐藏以提升性能。\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // 根据元素类型和图形对象动态决定是否保持可见\n    if (type === 'node') return true; // 所有节点保持可见\n    if (type === 'edge' && shape.get('importante')) return true; // 重要的边保持可见\n    return false; // 其他图形隐藏\n  };\n}\n```\n\n[示例](#保持特定元素可见)\n\n## 代码示例\n\n### 基础优化功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### 自定义防抖时间\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // 设置更长的防抖时间，在操作停止后0.5秒才恢复显示所有元素\n    },\n  ],\n});\n```\n\n### 保持特定元素可见\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 试试拖拽一下画布，看看效果吧\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 根据图表元素数量动态启用/禁用优化\n\n可以根据图表元素数量动态决定是否启用优化：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // 超出500个元素时启用优化\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 什么情况下应该使用此交互？\n\n当图表包含大量节点和边（通常超过500个元素）时，使用此交互可以显著提升操作流畅度。在性能要求高或硬件性能有限的环境中尤其有用。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ScrollCanvas.en.md":"---\ntitle: ScrollCanvas\norder: 14\n---\n\n## Overview\n\nScrollCanvas is a built-in behavior in G6 used to implement the canvas scrolling feature, supporting panning the canvas using the mouse wheel or keyboard arrow keys. This interaction is particularly useful for browsing larger charts, allowing users to explore different areas of the chart without changing the zoom level.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large chart content that exceeds the visible area\n- Exploring different parts of the graph while maintaining the current zoom level\n- Precisely adjusting the view position, especially when precise scrolling is needed in one-dimensional directions\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n      direction: 'y', // Allow only vertical scrolling\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                         | Type                                                                                                                                                                                          | Default                          | Required |\n| -------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------- |\n| type           | Behavior type name                                                                  | string                                                                                                                                                                                        | `scroll-canvas`                  | ✓        |\n| enable         | Whether to enable this behavior                                                     | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                             |          |\n| direction      | Allowed scrolling direction, [configuration options](#direction)                    | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (no direction limit) |          |\n| range          | Scrollable viewport range (in viewport size units), [configuration options](#range) | number \\| number[]                                                                                                                                                                            | 1                                |          |\n| sensitivity    | Scrolling sensitivity, the larger the value, the faster the scrolling               | number                                                                                                                                                                                        | 1                                |          |\n| trigger        | Keyboard shortcuts to trigger scrolling, [configuration options](#trigger)          | object                                                                                                                                                                                        | -                                |          |\n| onFinish       | Callback function when scrolling is finished                                        | () => void                                                                                                                                                                                    | -                                |          |\n| preventDefault | Whether to prevent the browser's default event                                      | boolean                                                                                                                                                                                       | true                             |          |\n\n### Direction\n\n`direction` is used to limit the scrolling direction:\n\n- Not set or set to `undefined`: Allow scrolling in any direction\n- Set to `'x'`: Allow only horizontal scrolling\n- Set to `'y'`: Allow only vertical scrolling\n\nThis is useful in specific visualization scenarios, such as in timeline charts where only horizontal scrolling may be needed.\n\n### Range\n\n`range` is used to control the scrollable range of the canvas:\n\n- Set to a single number: Use the same value for all four directions\n- Set to an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can scroll 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can scroll 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], where 0 means no scrolling, and Infinity means unlimited scrolling.\n\n### Trigger\n\n`trigger` allows you to configure keyboard arrow keys to control canvas scrolling:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for scrolling up\n    down: ['ArrowDown'], // Shortcut key for scrolling down\n    left: ['ArrowLeft'], // Shortcut key for scrolling left\n    right: ['ArrowRight'] // Shortcut key for scrolling right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Scrolling Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### Allow Only Horizontal Scrolling\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // Allow only horizontal scrolling\n    },\n  ],\n});\n```\n\n### Custom Scrolling Sensitivity and Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // Increase scrolling sensitivity\n      range: [0.5, 2, 0.5, 2], // Smaller limits up and down, larger limits left and right\n    },\n  ],\n});\n```\n\n### Control Scrolling with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What is the difference between ScrollCanvas and ZoomCanvas?\n\n- `ScrollCanvas` is used to pan the canvas without changing the zoom level\n- `ZoomCanvas` is used to zoom the canvas, changing the view's zoom level\n\nThey are often used together to provide complete canvas navigation functionality:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ScrollCanvas.zh.md":"---\ntitle: 滚动画布 ScrollCanvas\norder: 14\n---\n\n## 概述\n\nScrollCanvas 是 G6 中用于实现画布滚动功能的内置交互，支持通过鼠标滚轮或键盘方向键平移画布。这种交互方式对于浏览较大的图表特别有用，能让用户在不改变缩放比例的情况下探索图表的不同区域。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览超出可视区域的大型图表内容\n- 在保持当前缩放比例的情况下探索图的不同部分\n- 精确调整查看位置，尤其是在一维方向上需要精确滚动时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n      direction: 'y', // 只允许垂直方向滚动\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                 | 类型                                                                                                                                                                                          | 默认值                   | 必选 |\n| -------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ---- |\n| type           | 交互类型名称                                         | string                                                                                                                                                                                        | `scroll-canvas`          | ✓    |\n| enable         | 是否启用该交互                                       | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                     |      |\n| direction      | 允许的滚动方向，[配置项](#direction)                 | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (不限制方向) |      |\n| range          | 可滚动的视口范围(以视口大小为单位)，[配置项](#range) | number \\| number[]                                                                                                                                                                            | 1                        |      |\n| sensitivity    | 滚动灵敏度，值越大滚动速度越快                       | number                                                                                                                                                                                        | 1                        |      |\n| trigger        | 触发滚动的键盘快捷键，[配置项](#trigger)             | object                                                                                                                                                                                        | -                        |      |\n| onFinish       | 滚动完成时的回调函数                                 | () => void                                                                                                                                                                                    | -                        |      |\n| preventDefault | 是否阻止浏览器默认事件                               | boolean                                                                                                                                                                                       | true                     |      |\n\n### Direction\n\n`direction` 用于限制滚动的方向：\n\n- 不设置或设为 `undefined`：允许在任意方向滚动\n- 设为 `'x'`：只允许水平方向滚动\n- 设为 `'y'`：只允许垂直方向滚动\n\n这在特定的可视化场景下很有用，例如在时间轴图表中可能只需要水平滚动。\n\n### Range\n\n`range` 用于控制画布可滚动的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以滚动2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可滚动1个视口，左右方向可滚动2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能滚动，Infinity表示无限滚动。\n\n### Trigger\n\n`trigger` 允许你配置键盘方向键来控制画布滚动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上滚动的快捷键\n    down: ['ArrowDown'], // 向下滚动的快捷键\n    left: ['ArrowLeft'], // 向左滚动的快捷键\n    right: ['ArrowRight'] // 向右滚动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础滚动功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### 只允许水平滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // 只允许水平滚动\n    },\n  ],\n});\n```\n\n### 自定义滚动灵敏度和范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // 提高滚动灵敏度\n      range: [0.5, 2, 0.5, 2], // 上下方向限制较小，左右方向限制较大\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. ScrollCanvas 和 ZoomCanvas 有什么区别？\n\n- `ScrollCanvas` 用于平移画布，不改变缩放比例\n- `ZoomCanvas` 用于缩放画布，改变视图的缩放比例\n\n两者常结合使用，提供完整的画布导航功能：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ZoomCanvas.en.md":"---\ntitle: ZoomCanvas\nordeR: 15\n---\n\n## Overview\n\nZoomCanvas is a built-in behavior in G6 used to implement the canvas zooming feature, supporting zooming in and out of the canvas using the mouse wheel or keyboard shortcuts. This is one of the most commonly used interactions in graph visualization, helping users view both the overall structure and local details of the graph.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large-scale graph data, freely switching between the whole and details\n- Focusing on specific areas for detailed analysis\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                            | Type                                                                                | Default             | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------------- | -------- |\n| type           | Behavior type name                                                                                     | string                                                                              | `zoom-canvas`       | ✓        |\n| animation      | Zoom animation effect settings                                                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |          |\n| enable         | Whether to enable this behavior                                                                        | boolean \\| ((event: Event) => boolean)                                              | true                |          |\n| origin         | Zoom center point (viewport coordinates)                                                               | [Point](/api/viewport#point)                                                        | -                   |          |\n| onFinish       | Callback function when zooming is finished                                                             | () => void                                                                          | -                   |          |\n| preventDefault | Whether to prevent the browser's default event                                                         | boolean                                                                             | true                |          |\n| sensitivity    | Zoom sensitivity, the larger the value, the faster the zoom                                            | number                                                                              | 1                   |          |\n| trigger        | How to trigger zooming, supports mouse wheel and keyboard shortcuts, [configuration options](#trigger) | string[] \\| object                                                                  | -                   |          |\n\n### Trigger\n\n`trigger` has two usage methods, suitable for different scenarios:\n\n#### Method 1: Modifier keys combined with the mouse wheel\n\nIf you want to trigger zooming only when certain keys are pressed while scrolling the mouse wheel, you can configure it like this:\n\n```javascript\n{\n  trigger: ['Control']; // Hold down the Control key and scroll the mouse wheel to zoom\n}\n```\n\nCommon modifier keys include:\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> Not sure what value corresponds to a keyboard key? Refer to [MDN Key Values](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).\n\n#### Method 2: Pure keyboard shortcuts\n\nIf you want to control zooming entirely using the keyboard, you can set up key combinations:\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // Zoom in shortcut\n    zoomOut: ['Control', '-'], // Zoom out shortcut\n    reset: ['Control', '0']    // Reset zoom ratio shortcut\n  }\n}\n```\n\n## Code Examples\n\n### Basic Zoom Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### Custom Zoom Center\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n### Custom Zoom Sensitivity\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n    },\n  ],\n});\n```\n\n### Zoom with Shift + Mouse Wheel\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // Hold down the Shift key and scroll to zoom\n    },\n  ],\n});\n```\n\n### Control Zoom with Keyboard Shortcuts\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = to zoom in\n        zoomOut: ['Control', '-'], // Ctrl + - to zoom out\n        reset: ['Control', '0'], // Ctrl + 0 to reset\n      },\n    },\n  ],\n});\n```\n\n### Supports pinch-to-zoom on mobile devices\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // Other configurations for the PC side...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What if the canvas zoom exceeds the expected range?\n\nTo avoid excessive zooming in or out, you can set zoom limits:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  zoomRange: [0.5, 3], // Allow zooming out to 50% and zooming in to 300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. How to use it with other interactions?\n\nZooming and dragging are common combinations for a complete navigation experience:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. Conflicts when using two-finger touchpad input and scroll-canvas simultaneously\n\nOn a touchpad, both two-finger swipe (for scrolling) and pinch (for zooming) gestures are often interpreted as `wheel` events.\n\nBecause both `zoom-canvas` and `scroll-canvas` respond to `wheel` events by default, using them together can cause conflicts, such as a single gesture triggering both scrolling and zooming.\n\nYou can resolve this by checking the `event.ctrlKey` property. On most platforms, a pinch gesture sets `event.ctrlKey` to `true`, while a swipe does not. This allows you to conditionally enable `zoom-canvas` only for pinch gestures.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // When ctrlKey is true, it performs a two-finger pinch or spread operation; when false, it performs a two-finger swipe operation.\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ZoomCanvas.zh.md":"---\ntitle: 缩放画布 ZoomCanvas\nordeR: 15\n---\n\n## 概述\n\nZoomCanvas 是 G6 中用于实现画布缩放功能的内置交互，支持通过鼠标滚轮或键盘快捷键调整画布缩放比例。这是图可视化中最常用的交互之一，能帮助用户查看图的整体结构和局部细节。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览大规模图数据，在整体与细节之间自由切换\n- 聚焦到特定区域进行详细分析\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                     | 类型                                                                                | 默认值              | 必选 |\n| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------- | ---- |\n| type           | 交互类型名称                                             | string                                                                              | `zoom-canvas`       | ✓    |\n| animation      | 缩放动画效果设置                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |      |\n| enable         | 是否启用该交互                                           | boolean \\| ((event: Event) => boolean)                                              | true                |      |\n| origin         | 缩放中心点(视口坐标)                                     | [Point](/api/viewport#point)                                                        | -                   |      |\n| onFinish       | 缩放完成时的回调函数                                     | () => void                                                                          | -                   |      |\n| preventDefault | 是否阻止浏览器默认事件                                   | boolean                                                                             | true                |      |\n| sensitivity    | 缩放灵敏度，值越大缩放速度越快                           | number                                                                              | 1                   |      |\n| trigger        | 触发缩放的方式，支持滚轮和键盘快捷键，[配置项](#trigger) | string[] \\| object                                                                  | -                   |      |\n\n### Trigger\n\n`trigger`有两种使用方式，分别适用于不同场景：\n\n#### 方式一：与滚轮结合的修饰键\n\n当你希望只有在按下某些键的同时滚动滚轮才触发缩放时，可以这样配置：\n\n```javascript\n{\n  trigger: ['Control']; // 按住 Control 键同时滚动鼠标滚轮才能缩放\n}\n```\n\n常见的修饰键有：\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> 不知道键盘按键对应什么值？请参考 [MDN Key Values](https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values)。\n\n#### 方式二：纯键盘快捷键\n\n当你希望完全使用键盘控制缩放操作时，可以设置组合键：\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // 放大快捷键\n    zoomOut: ['Control', '-'], // 缩小快捷键\n    reset: ['Control', '0']    // 重置缩放比例快捷键\n  }\n}\n```\n\n## 代码示例\n\n### 基础缩放功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 自定义缩放中心\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n### 自定义缩放灵敏度\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n    },\n  ],\n});\n```\n\n### 使用Shift+滚轮进行缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // 按住 Shift 键同时滚动才能缩放\n    },\n  ],\n});\n```\n\n### 使用键盘快捷键控制缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = 放大\n        zoomOut: ['Control', '-'], // Ctrl + - 缩小\n        reset: ['Control', '0'], // Ctrl + 0 重置\n      },\n    },\n  ],\n});\n```\n\n### 支持移动端双指缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // PC 端其他配置...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 画布缩放超出了预期范围怎么办？\n\n为避免缩放过大或过小，可以设置缩放限制：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  zoomRange: [0.5, 3], // 允许缩小到50%和放大到300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. 如何与其他交互结合使用？\n\n缩放与拖拽是常见的组合，实现完整的导航体验：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. 触控板双指操作下，与 scroll-canvas 同时使用时的冲突\n\n在触控板上，双指滑动（用于滚动）和双指捏合（用于缩放）手势通常都会被解析为 `wheel` 事件。\n\n由于 `zoom-canvas` 和 `scroll-canvas` 默认都会响应 `wheel` 事件，当它们同时使用时会产生冲突，例如一个手势会同时触发滚动和缩放。\n\n你可以通过检查 `event.ctrlKey` 属性来解决这个问题。在多数平台上，捏合手势会使 `event.ctrlKey` 为 `true`，而滑动则不会。这允许你有条件地仅为捏合手势启用 `zoom-canvas`。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // ctrlKey 为 true 时，是双指捏合或扩张操作，false 时是双指滑动操作\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/custom-behavior.en.md":"---\ntitle: Custom Behavior\norder: 16\n---\n\n## Overview\n\nCustom behavior allows users to define one or more related interaction behaviors as a complete interaction based on the comprehensive [event mechanism](/en/api/event) provided by G6, thereby achieving interaction logic that fits business scenarios.\n\n### Execution Logic of Behavior\n\nTypically:\n\n1. Listen for user interaction events\n\n2. Update the canvas or perform other operations based on the events\n\nFor example, the `DragCanvas` behavior listens for pointer drag events and updates the camera position based on the drag distance.\n\n### Difference Between Behavior and Plugin\n\n- Both behavior and plugin base classes are derived from the [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) base class within G6, so the implementation methods for behavior and plugin are basically the same.\n- However, based on the concept of visualization, behavior is usually used to handle user interaction events, while plugins are usually used to handle canvas rendering logic, additional component rendering, etc.\n\n:::info{title=Tip}\nDue to conceptual distinctions, behavior instances cannot be obtained, while plugin instances can be obtained ([getPluginInstance](/en/api/plugin#graphgetplugininstancekey)).\n:::\n\n## When to Use Custom Behavior?\n\n- **Purpose**:\n\n  When users need to implement interaction logic that fits business scenarios, we usually need to cooperate with G6's event system to respond to related events and execute the required interaction logic.\n\n- **Without Custom Behavior**:\n\n  If custom behavior is not used, users need to perform a series of event listening and response processing through `graph.on` after creating a Graph instance, making code logic processing and orchestration extremely difficult.\n\n- **Advantages of Behavior**:\n\n  Each behavior is an independent code module, and the existence of the behavior system facilitates users to decouple business logic, avoid code bloat, and facilitate subsequent maintenance.\n\n- **Conclusion**:\n\n  > 1. When users need to implement any interaction logic, they should first consider custom behavior.\n  > 2. When built-in behavior cannot fully meet business needs, users can also adjust and modify through custom behavior (inheriting built-in behavior).\n  >\n  > _(If the features supported by built-in behavior are more general, or if there are bugs in built-in behavior, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Implementing Behavior\n\nThe implementation of a behavior is quite flexible, and you can implement your behavior in your preferred style.\n\nBelow is a simple custom behavior implementation. When the user clicks on the canvas, a node is added to the canvas (the fill color of the added node can be defined through behavior configuration):\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // Unbind events when destroyed\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In the example code, we implemented a `ClickAddNode` behavior, which adds an event listener to the Graph in the constructor. When the user clicks on the canvas, a node is added at the click position, and the fill color of the added node can be configured.\n- `BaseBehavior` is the base class for all behaviors, and each custom behavior needs to inherit this base class.\n\n> Click on the blank area of the canvas below to add a node, and switch the right panel to configure the node color.\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=Tip}\nThe above example is the simplest behavior implementation. In actual development, you may also need to handle logic such as enabling and disabling behaviors.\n\nIn addition, there may be event conflicts between multiple behaviors, and you need to handle these conflicts carefully.\n:::\n\n## Registering Behavior\n\nRegister through the register method provided by G6\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## Configuring Behavior\n\nYou can pass in the behavior type name or configuration parameter object in `behaviors`, such as the above ClickAddNode. See [Configuring Behavior](/en/manual/behavior/overview#配置和使用) for details.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/custom-behavior.zh.md":"---\ntitle: 自定义交互\norder: 16\n---\n\n## 概述\n\n自定义交互允许用户基于 G6 提供的完善的[事件机制](/api/event)，把一个或多个相关的交互行为定义为一个完整的交互，以此实现符合业务场景的交互逻辑。\n\n### 交互的执行逻辑\n\n通常为：\n\n1. 监听用户交互事件\n\n2. 根据事件更新画布或执行其他操作\n\n例如 `DragCanvas` 交互监听指针拖拽事件，根据拖拽的距离更新相机的位置。\n\n### 交互与插件的区别\n\n- 交互和插件的基类都是由 G6 内部的 [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) 基类派生而来，因此交互和插件的实现方式基本相同\n- 但基于可视化的概念区分，交互通常用于处理用户交互事件，而插件通常用于处理画布的渲染逻辑、额外组件渲染等\n\n:::info{title=提示}\n因概念上的区分，交互实例不可获取，插件实例可获取（ [getPluginInstance](/api/plugin#graphgetplugininstancekey) ）\n:::\n\n## 什么时候需要自定义交互？\n\n- **目的**：\n\n  当用户在实现符合业务场景的交互逻辑时，我们通常需要配合 G6 的事件系统，对相关事件作出响应，执行需要的交互逻辑。\n\n- **不使用自定义交互**：\n\n  如果不使用自定义交互，用户需要在创建 Graph 实例后，通过 `graph.on` 进行一系列的事件监听和响应处理，代码逻辑处理和编排会显得异常艰难。\n\n- **交互的优势**：\n\n  每个交互行为都是独立的代码模块，交互系统的存在方便用户解耦业务逻辑、避免代码臃肿以及方便用户后续维护等。\n\n- **结论**：\n\n  > 1、当用户需要实现任何交互逻辑时，应当首先考虑自定义交互。\n  >\n  > 2、当内置交互无法完全满足业务需求时，用户也可以通过自定义交互（继承内置交互）进行调整和修改。\n  >\n  > _（如果需要内置交互支持的特性是较通用的，或者内置交互存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 实现交互\n\n一个交互的实现相当灵活，你可以以你喜欢的风格实现你的交互。\n\n下面是一个简单的自定义交互实现，当用户点击画布时，会在画布上添加一个节点（可通过交互配置定义所添加节点的填充颜色）：\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // 销毁时解绑事件\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在示例代码中，我们实现了一个 `ClickAddNode` 交互，该交互在构造函数中添加了 Graph 的事件监听，当用户点击画布时，会在点击位置添加一个节点，并且支持配置所添加节点的填充颜色。\n- `BaseBehavior` 是所有交互的基类，每个自定义交互都需要继承这个基类实现。\n\n> 点击下面画布中的空白位置以添加一个节点，可切换右侧面板配置节点颜色\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=提示}\n上述示例是一个最简单的交互实现，实际开发过程中，你可能还需要处理交互的启用与禁用等逻辑。\n\n此外，多个交互之间可能会有事件冲突，你需要小心处理这些冲突。\n:::\n\n## 注册交互\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## 配置交互\n\n可在 `behaviors` 中传入交互类型名称或配置参数对象，比如上面的 ClickAddNode ，详见[配置交互](/manual/behavior/overview#配置和使用)\n\n```typescript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/overview.en.md":"---\ntitle: Behavior Overview\norder: 0\n---\n\n## What is Behavior\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nBehavior refers to the interactive operations between users and chart elements, such as dragging the canvas, selecting nodes, zooming the view, etc. Good behavior design allows users to explore and understand graph data more intuitively. **Proper configuration of behaviors is a key step in building efficient and usable charts**.\n\n### Changes in G6 5.0 Behavior System\n\nG6 5.0 removed the concept of \"Behavior Mode\" (Mode), and directly lists the required behavior behaviors in `behaviors`, simplifying the configuration. This makes behavior configuration more intuitive and easier to get started with.\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## Built-in Behaviors\n\nG6 provides a variety of built-in behaviors that are **ready to use without registration**:\n\n| Category            | Behavior Name                                                                  | Registration Type             | Function Description                                         |\n| ------------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------------------------------ |\n| Navigation          |                                                                                |                               |                                                              |\n|                     | [Drag Canvas](/en/manual/behavior/drag-canvas)                                 | `drag-canvas`                 | Drag the entire canvas view                                  |\n|                     | [Zoom Canvas](/en/manual/behavior/zoom-canvas)                                 | `zoom-canvas`                 | Zoom the canvas view                                         |\n|                     | [Scroll Canvas](/en/manual/behavior/scroll-canvas)                             | `scroll-canvas`               | Scroll the canvas using the wheel                            |\n|                     | [Optimize Viewport Transform](/en/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | Optimize view transform performance                          |\n| Selection           |                                                                                |                               |                                                              |\n|                     | [Click Select](/en/manual/behavior/click-select)                               | `click-select`                | Click to select graph elements                               |\n|                     | [Brush Select](/en/manual/behavior/brush-select)                               | `brush-select`                | Select elements by dragging a rectangular area               |\n|                     | [Lasso Select](/en/manual/behavior/lasso-select)                               | `lasso-select`                | Freely draw an area to select elements                       |\n| Editing             |                                                                                |                               |                                                              |\n|                     | [Create Edge](/en/manual/behavior/create-edge)                                 | `create-edge`                 | Interactively create new edges                               |\n|                     | [Drag Element](/en/manual/behavior/drag-element)                               | `drag-element`                | Drag nodes or combos                                         |\n|                     | [Force-directed Drag](/en/manual/behavior/drag-element-force)                  | `drag-element-force`          | Drag nodes in force-directed layout                          |\n| Data Exploration    |                                                                                |                               |                                                              |\n|                     | [Collapse/Expand](/en/manual/behavior/collapse-expand)                         | `collapse-expand`             | Expand or collapse subtree nodes                             |\n|                     | [Focus Element](/en/manual/behavior/focus-element)                             | `focus-element`               | Focus on specific elements and automatically adjust the view |\n|                     | [Hover Activate](/en/manual/behavior/hover-activate)                           | `hover-activate`              | Highlight elements when hovering                             |\n| Visual Optimization |                                                                                |                               |                                                              |\n|                     | [Fix Element Size](/en/manual/behavior/fix-element-size)                       | `fix-element-size`            | Fix the element size to a specified value                    |\n|                     | [Auto-adapt Label](/en/manual/behavior/auto-adapt-label)                       | `auto-adapt-label`            | Automatically adjust label position                          |\n\nFor detailed configuration of each behavior, refer to the [Built-in Behavior Documentation](/en/manual/behavior/drag-canvas).\n\n:::warning{title=Behavior Compatibility}\nSome behaviors may overlap in triggering mechanisms, such as `brush-select` and `drag-canvas` both using mouse dragging. In such cases, you can avoid conflicts by modifying the trigger key (e.g., hold `Shift` to drag and select).\n:::\n\n## Custom Behaviors\n\nWhen built-in behaviors cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend by inheriting built-in behaviors\n- Create entirely new behavior behaviors\n\nUnlike built-in behaviors, **custom behaviors need to be registered before use**. For detailed tutorials, refer to the [Custom Behavior](/en/manual/behavior/custom-behavior) documentation.\n\n## Configuration and Usage\n\n### Basic Configuration\n\nThe simplest way is to directly specify the required behaviors through the `behaviors` array when initializing the graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### Configure Behavior Parameters\n\nFor behaviors that require custom parameters, you can configure properties using the `object` form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // Configure sensitivity\n      key: 'zoom-behavior', // Specify a key for the behavior for subsequent updates\n    },\n  ],\n});\n```\n\n### Dynamically Update Behaviors\n\nG6 supports dynamically managing behavior behaviors during the runtime of the graph instance to meet complex behavior needs:\n\nYou can adjust behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method:\n\n```javascript\n// Add new behavior\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// Remove behavior\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\nYou can update the configuration of behaviors using the [updateBehavior](/en/api/behavior#graphupdatebehaviorbehavior) method:\n\n```javascript\n// Update a single behavior\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // Disable the behavior\n});\n```\n\n:::warning{title=Note}\nWhen using the `updateBehavior` method, you need to specify a unique `key` for the behavior during initialization.\n:::\n\n### Uninstall Behaviors\n\nYou can also uninstall behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method by setting the behavior configuration list to empty:\n\n```javascript\ngraph.setBehaviors([]);\n```\n\nFor more behavior-related APIs, refer to the [Behavior API Documentation](/en/api/behavior).\n\n## Behavior and Events\n\nBehaviors are essentially implemented through event listening and response. Although built-in behaviors have encapsulated common behavior behaviors, you can also directly implement custom behavior logic through the event API.\n\n### Event Listening Example\n\n```javascript\n// Use event constants (recommended)\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// Listen for node clicks\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen for edge hover\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\nThe event system is the foundation for implementing behaviors. Mastering the event API is crucial for understanding and extending behavior behaviors. For more event-related information, refer to the [Event Documentation](/en/api/event).\n","packages/site/docs/manual/behavior/overview.zh.md":"---\ntitle: 交互总览\norder: 0\n---\n\n## 什么是交互\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n交互(Behavior)是指用户与图表元素之间的互动操作，如拖拽画布、选择节点、缩放视图等。良好的交互设计能让用户更直观地探索和理解图数据。**合理配置交互是构建高效可用图表的关键环节**。\n\n### G6 5.0 交互系统变化\n\nG6 5.0 移除了 \"交互模式\"(Mode) 概念，直接在 `behaviors` 中列出需要的交互行为，简化了配置方式。这使得交互配置更加直观，上手更加简单。\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## 内置交互\n\nG6 提供了多种开箱即用的内置交互，**无需注册，直接配置即可使用**：\n\n| 分类     | 交互名称                                                     | 注册类型                      | 功能描述                   |\n| -------- | ------------------------------------------------------------ | ----------------------------- | -------------------------- |\n| 导航     |                                                              |                               |                            |\n|          | [拖拽画布](/manual/behavior/drag-canvas)                     | `drag-canvas`                 | 拖动整个画布视图           |\n|          | [缩放画布](/manual/behavior/zoom-canvas)                     | `zoom-canvas`                 | 缩放画布视图               |\n|          | [滚动画布](/manual/behavior/scroll-canvas)                   | `scroll-canvas`               | 使用滚轮滚动画布           |\n|          | [优化视口变换](/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | 优化视图变换性能           |\n| 选择     |                                                              |                               |                            |\n|          | [点击选择](/manual/behavior/click-select)                    | `click-select`                | 点击选择图元素             |\n|          | [框选](/manual/behavior/brush-select)                        | `brush-select`                | 通过拖拽矩形区域选择元素   |\n|          | [套索选择](/manual/behavior/lasso-select)                    | `lasso-select`                | 自由绘制区域选择元素       |\n| 编辑     |                                                              |                               |                            |\n|          | [创建边](/manual/behavior/create-edge)                       | `create-edge`                 | 交互式创建新的边           |\n|          | [拖拽元素](/manual/behavior/drag-element)                    | `drag-element`                | 拖动节点或组合             |\n|          | [力导向拖拽](/manual/behavior/drag-element-force)            | `drag-element-force`          | 力导向布局中拖动节点       |\n| 数据探索 |                                                              |                               |                            |\n|          | [折叠/展开](/manual/behavior/collapse-expand)                | `collapse-expand`             | 展开或收起子树节点         |\n|          | [聚焦元素](/manual/behavior/focus-element)                   | `focus-element`               | 聚焦特定元素，自动调整视图 |\n|          | [悬停激活](/manual/behavior/hover-activate)                  | `hover-activate`              | 鼠标悬停时高亮元素         |\n| 视觉优化 |                                                              |                               |                            |\n|          | [固定元素大小](/manual/behavior/fix-element-size)            | `fix-element-size`            | 将元素大小固定为指定值     |\n|          | [自适应标签](/manual/behavior/auto-adapt-label)              | `auto-adapt-label`            | 自动调整标签位置           |\n\n各交互的详细配置可参考 [内置交互文档](/manual/behavior/drag-canvas)。\n\n:::warning{title=交互兼容性}\n某些交互在触发机制上可能存在重叠，如 `brush-select` 和 `drag-canvas` 都使用鼠标拖拽。这种情况下可以通过修改触发按键（如按住 `Shift` 拖拽选择）来避免冲突。\n:::\n\n## 自定义交互\n\n当内置交互无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置交互进行扩展\n- 创建全新的交互行为\n\n与内置交互不同，**自定义交互需要先注册后使用**。详细教程请参考 [自定义交互](/manual/behavior/custom-behavior) 文档。\n\n## 配置和使用\n\n### 基本配置\n\n最简单的方式是在图实例初始化时，通过 `behaviors` 数组直接指定需要的交互：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### 配置交互参数\n\n对于需要自定义参数的交互，可以使用 `object` 的形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // 配置灵敏度\n      key: 'zoom-behavior', // 为交互指定key，便于后续更新\n    },\n  ],\n});\n```\n\n### 动态更新交互\n\nG6 支持在图实例运行期间动态管理交互行为，满足复杂交互需求：\n\n可以通过 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法调整交互：\n\n```javascript\n// 添加新交互\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// 移除交互\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\n可以使用 [updateBehavior](/api/behavior#graphupdatebehaviorbehavior) 方法更新交互的配置：\n\n```javascript\n// 更新单个交互\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // 禁用该交互\n});\n```\n\n:::warning{title=注意}\n使用`updateBehavior`方法时，需要在初始化时为交互指定唯一的`key`。\n:::\n\n### 卸载交互\n\n使用 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法同样可以卸载交互，将交互配置列表置为空即可：\n\n```javascript\ngraph.setBehaviors([]);\n```\n\n更多与交互相关的 API 请参考 [交互 API 文档](/api/behavior)。\n\n## 交互与事件\n\n交互本质上是通过事件监听和响应来实现的。虽然内置交互已经封装了常见的交互行为，但你也可以通过事件 API 直接实现自定义交互逻辑。\n\n### 事件监听示例\n\n```javascript\n// 使用事件常量（推荐）\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// 监听节点点击\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边悬停\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\n事件系统是实现交互的基础，掌握事件 API 对于理解和扩展交互行为至关重要。更多事件相关信息，请参考 [事件文档](/api/event)。\n","packages/site/docs/manual/contribute.en.md":"---\ntitle: contribute\norder: 14\n---\n\nTo contribute, you need to understand G6's code structure and development workflow. The code repository for G6 is located at: https://github.com/antvis/G6\n\nIf you want to fix a bug or add a new feature, you need to first fork a copy of the code to your repository, then make modifications in your repository, and finally submit a Pull Request (PR) to the G6 repository.\n\n## Project Structure\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 Core Implementation</small>\n          <ul>\n            <li>\n              __tests__\n              <small>Testing and Development Environment</small>\n              <ul>\n                <li>\n                  assets\n                  <small>Test Static Resources</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bugfix Test Case</small>\n                </li>\n                <li>\n                  dataset\n                  <small>Test Dataset</small>\n                </li>\n                <li>\n                  demos\n                  <small>Development Demos</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>Test Snapshots</small>\n                </li>\n                <li>\n                  perf\n                  <small>Performance Test Case</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>Performance Test Reports</small>\n                </li>\n                <li>\n                  unit\n                  <small>Test Cases</small>\n                </li>\n                <li>\n                  utils\n                  <small>Test Utility Functions</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>Animation Executors and Built-in Animations</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>Built-in Interactions</small>   \n                </li>\n                <li>\n                  constants\n                  <small>Constants and Enumeration Values</small>   \n                </li>\n                <li>\n                  elements\n                  <small>Built-in Elements</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>Built-in Combos</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>Built-in Edges</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>Built-in Nodes</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>Composite Shapes</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>Layout References and Encapsulation</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>Built-in Palettes</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>Built-in Plugins</small>   \n                </li>\n                <li>\n                  registry\n                  <small>Registry Module</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph and Core Controller</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification Type Definitions</small>   \n                </li>\n                <li>\n                  themes\n                  <small>Built-in Themes</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>Built-in Data Transformations</small>   \n                </li>\n                <li>\n                  types\n                  <small>Type Definitions</small>   \n                </li>\n                <li>\n                  utils\n                  <small>Utility Functions</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>Export Items</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>Pre-operations</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>Development Environment Vite Configuration</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D Extension</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D Behaviors</small>\n            </li>\n            <li>\n              elements\n              <small>3D Elements</small>\n            </li>\n            <li>\n              plugins\n              <small>3D Plugins</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D Renderer</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React Node Extension</small>\n          <ul>\n            <li>\n              elements\n              <small>React Elements</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph Encapsulation</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>Official Website and Documentation</small>\n          <ul>\n            <li>\n              docs\n              <small>Tutorials and API</small>\n            </li>\n            <li>\n              examples\n              <small>Graph Examples</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>Configuration File</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## Development Process\n\n1. Fork and Pull the Code\n\nFork the G6 repository on Github to your account, then clone it locally.\n\n```bash\n# Navigate to your workspace\ncd /path/to/your/workspace\n\n# Navigate to the G6 directory\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. Install Dependencies\n\n:::warning{title=Warning}\nPlease ensure your local environment meets the following requirements:\n\n- [Node.js](https://nodejs.org/) version >= 18\n- [pnpm](https://pnpm.io/) version >= 8\n\n:::\n\n```bash\n# Enter the G6 code directory\ncd G6\n\n# Install Dependencies\npnpm install\n```\n\n3. Start the Development Environment\n\n```bash\n# Enter the g6 code directory.\ncd ./packages/g6\n\n# Start the development environment\npnpm dev\n```\n\nAt this point, you can access G6's development environment and preview the examples by visiting http://127.0.0.1:8080 in your web browser.\n\n4. Develop New Features or Fix Bugs\n\nSwitch to a development branch:\n\n```bash\ngit checkout -b [branch name]\n```\n\nMake code modifications according to your needs and test locally.\n\n5. Write Test Cases\n\nIn the `packages/g6/__tests__/unit` directory, write test cases to ensure your code behaves as expected.\n\nValidate Your Code with Tests：\n\n```bash\npnpm test\n```\n\n6. Submit a Pull Request (PR)\n\n```bash\n# Stage changes\ngit add .\n\n# Commit Changes\ngit commit -m \"[commit type]: commit message\"\n\n# Push to Your Repository\ngit push\n```\n\nSubmit a Pull Request (PR) to the G6 repository on GitHub.\n\n## Testing and Coverage\n\nG6 utilizes Jest for conducting unit tests, with the test cases situated in the `packages/g6/__tests__/unit` directory.\n\nWe require that all code submissions must pass tests to ensure code quality.\n\nThe coverage rate for the current PR (Pull Request) submission is advised not to fall below the coverage rate of the existing codebase, and it is <text style=\"color: red;\">not to fall below 90%</text>.\n\n### Update Test Snapshots\n\nG6 extends Jest tests and provides the `toMatchSnapshot` assertion for generating and comparing snapshots.\n\nIf the current possible modification affects the generation of some screenshots, it is necessary to check whether there are failed test cases by executing `pnpm test`.\n\nWhen a failed test case is found, the console will print the path of the failed test, as well as the path information of the benchmark screenshot and the current screenshot. You can hold the `Ctrl` or `Command` key and click the path to view the specific test case or screenshot.\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\nIf it is confirmed that this modification is correct, then please manually delete the corresponding benchmark screenshots and regenerate the screenshots:\n\n**Regenerate all screenshots**:\n\n1. Delete all files in the `packages/g6/__tests__/unit/snapshots` directory\n2. Execute `pnpm test`\n\n**Regenerate a single screenshot**:\n\n1. Delete the corresponding file in the `packages/g6/__tests__/snapshots` directory (test cases in the `unit` directory will generate the corresponding directory under `snapshots`)\n2. Execute `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## Code Standards\n\nThe G6 code adheres to the following standards:\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## Commit Conventions\n\nG6 adopts the [Conventional Commits](https://www.conventionalcommits.org/) specification, and the commit message format is as follows:\n\n```\n<type>[optional scope]: <description>\n```\n\nThe type field can be one of the following:\n\n- feat: A new feature\n- fix: A bug fix\n- docs: Documentation update\n- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)\n- refactor: Code change that neither fixes a bug nor adds a feature\n- perf: A code change that improves performance\n- test: Adding missing or correcting existing tests\n- build: Changes that affect the build system or external dependencies\n- ci: Changes to our CI configuration files and scripts\n- chore: Other changes that don't modify src or test files\n- revert: Reverts a previous commit\n\nFor example:\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\nPlease ensure that your commit messages conform to the standards, and try to use English descriptions whenever possible. This helps us better manage the code.\n\n## Pull Request (PR) Standards\n\nAfter completing the above steps, you can submit a PR to the G6 repository. Please ensure that your PR adheres to the following standards:\n\n- A single PR should address only one issue.\n- The title of the PR should be concise and clear.\n- The description of the PR should be clear and detailed. If the changes involve the user interface, please include screenshots.\n- The PR must pass CI (Continuous Integration) checks.\n\n## Code Review\n\nAfter your PR is submitted, we will review your code. Please be patient and await the results of the review. If there are any areas that require modification, we will point them out within the PR.\n\n## Release Process\n\nWe regularly release new versions. If your PR is for a non-urgent bug fix, it will be included in the next release. If your PR addresses an urgent bug fix, we will release a new version as soon as possible.\n\nThis project uses changeset to manage version release, and the specific release process is as follows:\n\n1. Complete related development work\n2. Create a branch from v5 (any name you want)\n3. Run `npm run version` command, fill in the information according to the prompt, and the version number will be updated automatically\n4. Commit the changes to the remote repository\n5. Create a PR on GitHub, add the `publish` label, and merge the branch to v5\n6. After the branch is merged, GitHub Actions will be triggered automatically, and the package will be published to npm\n7. After the release, the Release note needs to be updated. Execute \"pnpm tag\" in the packages/g6\n8. Fill in the tag information on the newly opened Github link. First, select the previous tag, and then select the current tag to obtain the changes. After confirming that there are no issues, release it.\n","packages/site/docs/manual/contribute.zh.md":"---\ntitle: 参与贡献\norder: 14\n---\n\n要参与贡献，你需要了解 G6 的代码结构和开发流程。G6 的代码仓库地址是：https://github.com/antvis/G6\n\n如果你想要修复一个 bug 或者增加一个新功能，你需要先 fork 一份代码到你的仓库，然后在你的仓库中进行修改，最后提交 PR 到 G6 的仓库。\n\n## 项目结构\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 核心实现</small>\n          <ul>\n            <li>\n              __tests__\n              <small>测试及开发环境</small>\n              <ul>\n                <li>\n                  assets\n                  <small>测试静态资源</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bug 修复测试用例</small>\n                </li>\n                <li>\n                  dataset\n                  <small>测试数据集</small>\n                </li>\n                <li>\n                  demos\n                  <small>开发示例</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>测试截图</small>\n                </li>\n                <li>\n                  perf\n                  <small>性能测试用例</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>性能测试报告</small>\n                </li>\n                <li>\n                  unit\n                  <small>测试用例</small>\n                </li>\n                <li>\n                  utils\n                  <small>测试工具函数</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>动画执行器及内置动画</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>内置交互</small>   \n                </li>\n                <li>\n                  constants\n                  <small>常量及枚举值</small>   \n                </li>\n                <li>\n                  elements\n                  <small>内置元素</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>内置组合</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>内置边</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>内置节点</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>复合图形</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>布局引用及封装</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>内置色板</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>内置插件</small>   \n                </li>\n                <li>\n                  registry\n                  <small>注册模块</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph 及核心控制器</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification 类型定义</small>   \n                </li>\n                <li>\n                  themes\n                  <small>内置主题</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>内置数据转换</small>   \n                </li>\n                <li>\n                  types\n                  <small>类型定义</small>   \n                </li>\n                <li>\n                  utils\n                  <small>工具函数</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>导出项</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>预操作</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>开发环境 Vite 配置</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D 扩展</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D 交互</small>\n            </li>\n            <li>\n              elements\n              <small>3D 元素</small>\n            </li>\n            <li>\n              plugins\n              <small>3D 插件</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D 渲染器</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React 节点扩展</small>\n          <ul>\n            <li>\n              elements\n              <small>React 元素</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph 封装</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>官网及文档</small>\n          <ul>\n            <li>\n              docs\n              <small>教程及 API</small>\n            </li>\n            <li>\n              examples\n              <small>图表示例</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>配置文件</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## 开发流程\n\n1. Fork 并拉取代码\n\n在 Github 中 Fork [G6](https://github.com/antvis/G6) 到你的仓库，并拉取到本地。\n\n```bash\n# 进入你的工作目录\ncd /path/to/your/workspace\n\n# 克隆 G6 代码\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. 安装依赖\n\n:::warning{title=注意}\n请验证你的本地环境是否符合要求：\n\n- [Node.js](https://nodejs.org/) 版本 >= 18\n- [pnpm](https://pnpm.io/) 版本 >= 8\n\n:::\n\n```bash\n# 进入 G6 代码目录\ncd G6\n\n# 安装依赖\npnpm install\n```\n\n3. 启动开发环境\n\n```bash\n# 进入 G6 代码目录\ncd ./packages/g6\n\n# 启动开发环境\npnpm dev\n```\n\n此时，你可以在浏览器中访问 `http://127.0.0.1:8080` 查看 G6 的开发环境并预览开发示例。\n\n4. 开发新功能或修复 bug\n\n切换到开发分支：\n\n```bash\ngit checkout -b [branch name]\n```\n\n根据你的需求，修改代码并在本地测试。\n\n5. 编写测试用例\n\n在 `packages/g6/__tests__/unit` 目录下编写测试用例，确保你的代码符合预期。\n\n确保你的代码通过测试：\n\n```bash\npnpm test\n```\n\n6. 提交 PR\n\n```bash\n# 添加修改\ngit add .\n\n# 提交修改\ngit commit -m \"[commit type]: commit message\"\n\n# 推送到你的仓库\ngit push\n```\n\n在 Github 中提交 PR 到 G6 仓库。\n\n## 测试与覆盖率\n\nG6 使用 Jest 进行单元测试，测试用例位于 `packages/g6/__tests__/unit` 目录下。\n\n我们要求所有的代码提交都需要通过测试，确保代码质量。\n\n当前 PR 提交的覆盖率不建议低于当前代码库的覆盖率，且<text style=\"color: red;\">不得低于 90%</text>。\n\n### 更新测试截图\n\nG6 扩展了 Jest 测试，提供了 `toMatchSnapshot` 断言用于生成以及对比快照。\n\n如果当前可能修改影响了部分截图的生成，需要通过执行 `pnpm test` 检查是否有测试用例失败。\n\n当发现测试失败的用例时，控制台会打印出失败的测试路径，以及基准截图和当前截图的路径信息。你可以按住 `Ctrl` 或 `Command` 键并点击路径，查看具体的测试用例或截图。\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\n如果确认本次修改是正确的，那么请手动删除对应的基准截图，并重新生成截图：\n\n**重新生成全部截图**：\n\n1. 删除 `packages/g6/__tests__/unit/snapshots` 目录下的所有文件\n2. 执行 `pnpm test`\n\n**重新生成单个截图**：\n\n1. 删除 `packages/g6/__tests__/snapshots` 目录下对应的文件（`unit`目录下测试用例会在`snapshots`下生成对应的目录）\n2. 执行 `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## 代码规范\n\nG6 编码尊循以下规范：\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## 提交规范\n\nG6 采用 [Conventional Commits](https://www.conventionalcommits.org/) 规范，提交信息格式如下：\n\n```\n<type>[optional scope]: <description>\n```\n\ntype 有以下几种：\n\n- feat: 新功能\n- fix: 修复 bug\n- docs: 文档更新\n- style: 代码格式（不影响代码运行的变动）\n- refactor: 重构\n- perf: 性能优化\n- test: 测试\n- build: 构建工具相关的变动\n- ci: CI 配置\n- chore: 其他无关紧要的变动\n- revert: 撤销\n\n例如：\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\n请确保你的提交信息符合规范，并尽量使用英文描述，这样有助于我们更好地管理代码。\n\n## PR 规范\n\n完成上述步骤后，你可以提交 PR 到 G6 仓库。请确保你的 PR 符合以下规范：\n\n- 一个 PR 只解决一个问题\n- PR 的标题简洁明了\n- PR 的描述清晰详细，涉及视图的变动请附上截图\n- PR 必需能够通过 CI 检查\n\n## 代码 Review\n\nPR 提交后，我们会对你的代码进行 Review。请耐心等待 Review 结果，如果有需要修改的地方，我们会在 PR 中提出。\n\n## 发布流程\n\n我们会定期发布新版本，如果你的 PR 是非紧急缺陷修复，我们会在下一个版本中发布。如果你的 PR 是紧急缺陷修复，我们会尽快发布新版本。\n\n本项目通过 changeset 来管理版本发布，具体的发布流程如下：\n\n1. 完成相关的开发工作\n2. 从 v5 分支创建一个分支（任意分支名均可）\n3. 根目录执行 `npm run version` 命令，根据提示填写相关信息，会自动更新版本号\n4. 将变更提交到远程仓库\n5. 在 GitHub 上创建一个 PR，并添加 `publish` 标签，将该分支合并到 v5 分支\n6. 分支合并后，会自动触发 GitHub Actions，发布到 npm\n7. 发布后，需更新 Release note，在 packages/g6 目录下执行 pnpm tag\n8. 在新打开的 Github 链接填写 tag 信息，先选择前一个 tag, 然后选择当前 tag 后得到变更，确认没有问题后发布\n","packages/site/docs/manual/data.en.md":"---\ntitle: Data\norder: 1\n---\n\n## Overview\n\nG6 is a data-driven charting library, where data is one of the most important concepts. In G6, data is the core of the chart, and both display and interaction are based on data.\n\nCommon graph data formats include:CSV, [DOT](https://graphviz.org/doc/info/lang.html), GDF, GML, [GraphML](http://graphml.graphdrawing.org/), [GEXF](https://gexf.net/) etc。\n\nG6 uses JSON format to describe the graph structure, which includes information about nodes and edges. Here is a simple JSON data example:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\" }, { \"id\": \"node2\" }],\n  \"edges\": [{ \"source\": \"node1\", \"target\": \"node2\" }]\n}\n```\n\nCompared to the other formats mentioned above, the JSON format has a more intuitive and understandable data structure. It is also more flexible, allowing for easy expansion of node and edge attributes.\n\nIt is a data exchange format widely supported by computers, so you do not have to worry about data format compatibility issues.\n\n## Data Structure\n\nIn G6, graph data consists of three parts: `nodes` (node data), `edges` (edge data), and `combos` (combo data). Each part corresponds to different elements in the graph, and their types and data determine how the graph is displayed.\n\n```ts\ninterface GraphData {\n  nodes: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data (optional)\n  combos?: ComboData[]; // Combo data (optional)\n}\n```\n\n### Node Data\n\nA node is the basic building block of a graph and represents an entity within the graph. Each node has a unique `id` used to identify it, and nodes can also have data, styles, and states.\n\n| Attribute                                 | Type               | Description                                                                                                        |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the node, used to distinguish different nodes                                                |\n| type                                      | _string_           | Node type. It can be the type of built-in Node, or the custom Node                                                 |\n| data                                      | _Object_           | Custom data for the node, such as name, description, etc. Can be accessed in style mappings via callback functions |\n| style                                     | _Object_           | Node style, including position, size, color, and other visual properties                                           |\n| states                                    | _string[]_         | Initial states for the node, such as selected, active, hover, etc.                                                 |\n| combo                                     | _string_ \\| _null_ | ID of the combo the node belongs to. Used to organize hierarchical relationships. If none, it is null              |\n| children                                  | _string[]_         | Collection of child node IDs, used only in tree diagrams                                                           |\n\n**Example:**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### Edge Data\n\nAn edge connects nodes and represents the relationship between them. Each edge is associated with two nodes (source and target), and edges themselves can have data, styles, and states. Edge data is often used to represent logical relationships, such as user connections in social networks or step flows in flowcharts.\n\n| Attribute                                     | Type       | Description                                                                                                             |\n| --------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |\n| <Badge type=\"success\">Required</Badge> source | _string_   | Source node ID                                                                                                          |\n| <Badge type=\"success\">Required</Badge> target | _string_   | Target node ID                                                                                                          |\n| id                                            | _string_   | Unique identifier for the edge. If not specified, `id` is automatically generated with the format `${source}-${target}` |\n| type                                          | _string_   | Edge type.It can be the type of built-in Edge, or the custom Edge                                                       |\n| data                                          | _Object_   | Custom data for the edge, accessible in style mappings via callback functions                                           |\n| style                                         | _Object_   | Edge style, including stroke color, line width, arrowhead, etc.                                                         |\n| states                                        | _string[]_ | Initial states for the edge                                                                                             |\n\n**Example:**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Combo Data\n\nCombos allow you to create a logical unit for multiple nodes, used for layering, grouping, or other structural purposes. A combo can contain child nodes or other combos, forming a nested structure.\n\n| Attribute                                 | Type               | Description                                                                    |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the combo                                                |\n| type                                      | _string_           | Combo type.It can be the type of built-in Combo, or the custom Combo           |\n| data                                      | _Object_           | Custom data for the combo, accessible in style mappings via callback functions |\n| style                                     | _Object_           | Combo style                                                                    |\n| states                                    | _string[]_         | Initial states for the combo                                                   |\n| combo                                     | _string_ \\| _null_ | Parent combo ID. If there is no parent combo, it is null                       |\n\n**Example:**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## Data Organization and Best Practices\n\nTo ensure correct rendering and interaction of the graph, it is recommended to organize the data according to G6's standard data structure. Each element (node, edge, combo) should contain a `data` field to store business data and custom properties.\n\n- **Avoid using identifiers that conflict with internal G6 field names**, such as `id`, `type`, `style`, etc., to prevent naming conflicts.\n- Store business data (such as user information, social network relationships, etc.) in the `data` field. This ensures flexibility and scalability of the data.\n\n**Example:**\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"node1\",\n      \"data\": { \"name\": \"Alice\", \"role\": \"Admin\" }\n    },\n    {\n      \"id\": \"node2\",\n      \"data\": { \"name\": \"Bob\", \"role\": \"User\" }\n    }\n  ],\n  \"edges\": [\n    {\n      \"source\": \"node1\",\n      \"target\": \"node2\",\n      \"data\": { \"relationship\": \"friend\" }\n    }\n  ]\n}\n```\n\n## API\n\nG6 provides a series of APIs to access and manipulate data, including:\n\n- [getData](/en/api/data#graphgetdata)\n- [setData](/en/api/data#graphsetdata)\n- [getNodeData](/en/api/data#graphgetnodedata)\n- [getEdgeData](/en/api/data#graphgetedgedata)\n- [getComboData](/en/api/data#graphgetcombodata)\n- [addData](/en/api/data#graphadddata)\n- [addNodeData](/en/api/data#graphaddnodedata)\n- [addEdgeData](/en/api/data#graphaddedgedata)\n- [addComboData](/en/api/data#graphaddcombodata)\n- [updateData](/en/api/data#graphupdatedata)\n- [updateNodeData](/en/api/data#graphupdatenodedata)\n- [updateEdgeData](/en/api/data#graphupdateedgedata)\n- [updateComboData](/en/api/data#graphupdatecombodata)\n- [removeData](/en/api/data#graphremovedata)\n- [removeNodeData](/en/api/data#graphremovenodedata)\n- [removeEdgeData](/en/api/data#graphremoveedgedata)\n- [removeComboData](/en/api/data#graphremovecombodata)\n\nThrough different APIs, you can conveniently access and manipulate graph data, performing operations such as adding, deleting, modifying, and querying the graph.\n\n## Use Remote Data\n\nG6 does not provide functionality for data retrieval and parsing. For local JSON data, you can directly import and use it as follows:\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\nFor remote data, you can use `fetch` or other networking libraries to retrieve the data:\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // Use data\n  });\n```\n","packages/site/docs/manual/data.zh.md":"---\ntitle: 数据 Data\norder: 4\n---\n\n## 概述\n\nG6 是一款数据驱动的图可视化引擎，数据是 G6 中最重要的概念之一。\n\nG6 使用标准的 JSON 格式描述图数据结构。以下是一个基础的图数据示例：\n\n```javascript {4-7}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n});\n```\n\n## 数据结构\n\n图数据包含三部分：`nodes`（节点数据）、`edges`（边数据）、`combos`（组合数据）。每一部分对应图中的不同元素，它们的类型和数据决定了图如何展示。\n\n### 图数据（GraphData）\n\n| 属性   | 描述     | 类型                              | 默认值 | 必选 |\n| ------ | -------- | --------------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#节点数据nodedata)[]   | -      |      |\n| edges  | 边数据   | [EdgeData](#边数据edgedata)[]     | -      |      |\n| combos | 组合数据 | [ComboData](#组合数据combodata)[] | -      |      |\n\n### 节点数据（NodeData）\n\n节点是图中的基本构成单元，它代表图中的实体。每个节点都有一个唯一的 `id`，用于标识节点，同时节点也可以有数据、样式和状态。\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### 边数据（EdgeData）\n\n边是连接节点的元素，表示节点之间的关系。每条边都与两个节点（起始节点和目标节点）关联，并且边本身可以有数据、样式和状态。边的数据常用于表示节点之间的逻辑或关系，如社交网络中的用户关系、流程图中的步骤流转等。\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n**示例：**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 组合数据（ComboData）\n\n通过组合，可以为多个节点创建一个逻辑单元，用于图形的分层、分组或其他结构化需求。组合可以包含子节点或其他组合，从而形成嵌套层次。\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## 数据操作\n\nG6 提供了丰富的 API 来操作图数据，下面展示一些常见的数据操作示例。\n\n### 数据初始化\n\n在创建图实例时，可以直接传入数据：\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n```\n\n或者通过 `setData` 方法设置数据：\n\n```javascript\ngraph.setData({\n  nodes: [\n    { id: 'node3', data: { label: '节点3' } },\n    { id: 'node4', data: { label: '节点4' } },\n  ],\n  edges: [{ source: 'node3', target: 'node4', data: { label: '新关系' } }],\n});\n```\n\n### 数据增删改查\n\n#### 添加节点和边\n\n```javascript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node5',\n    data: {\n      label: '新节点',\n      category: 'person',\n    },\n    style: {\n      fill: '#6395F9',\n      stroke: '#5B8FF9',\n    },\n  },\n]);\n\n// 批量添加多个节点\ngraph.addNodeData([\n  { id: 'node6', data: { label: '批量节点1' } },\n  { id: 'node7', data: { label: '批量节点2' } },\n]);\n\n// 添加连接新节点的边\ngraph.addEdgeData([\n  {\n    source: 'node1',\n    target: 'node5',\n    data: {\n      label: '连接到新节点',\n      weight: 2,\n    },\n    style: {\n      stroke: '#F6BD16',\n      lineWidth: 3,\n    },\n  },\n]);\n```\n\n#### 更新数据\n\n```javascript\n// 更新单个节点\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    data: {\n      label: '已更新的节点1',\n      status: 'updated',\n    },\n    style: {\n      fill: '#F6BD16',\n      stroke: '#EBEBEB',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 更新多个节点\ngraph.updateNodeData([\n  {\n    id: 'node2',\n    style: { size: 40, fill: '#5AD8A6' },\n  },\n  {\n    id: 'node3',\n    data: { importance: 'high' },\n  },\n]);\n\n// 更新边\ngraph.updateEdgeData([\n  {\n    source: 'node1',\n    target: 'node2',\n    style: {\n      stroke: '#5B8FF9',\n      lineWidth: 2,\n      lineDash: [5, 5],\n    },\n  },\n]);\n```\n\n#### 删除数据\n\n```javascript\n// 删除单个节点（以及与该节点相连的所有边）\ngraph.removeNodeData(['node7']);\n\n// 删除多个节点\ngraph.removeNodeData(['node5', 'node6']);\n\n// 删除边\ngraph.removeEdgeData(['node1-node2']);\n```\n\n#### 查询数据\n\n```javascript\n// 获取所有节点数据\nconst nodes = graph.getNodeData();\n\n// 获取所有边数据\nconst edges = graph.getEdgeData();\n\n// 获取特定节点数据\nconst node1 = graph.getNodeData('node1');\n\n// 获取特定边数据\nconst edge1 = graph.getEdgeData('node1-node2');\n```\n\n### 复杂数据结构操作\n\n#### 嵌套组合（Combo）\n\n下面是创建和操作嵌套组合的示例：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', data: { label: '节点1' }, combo: 'combo1' },\n    { id: 'node2', data: { label: '节点2' }, combo: 'combo1' },\n    { id: 'node3', data: { label: '节点3' }, combo: 'combo2' },\n    { id: 'node4', data: { label: '节点4' }, combo: 'combo2' },\n    { id: 'node5', data: { label: '节点5' }, combo: 'combo3' },\n  ],\n  edges: [\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n  combos: [\n    { id: 'combo1', data: { label: '组1' } },\n    { id: 'combo2', data: { label: '组2' } },\n    { id: 'combo3', data: { label: '组3' }, combo: 'combo1' }, // 嵌套组合\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'force',\n  },\n});\n\n// 添加新的组合\ngraph.addComboData([\n  {\n    id: 'combo4',\n    data: { label: '新组' },\n    combo: 'combo2', // 添加到现有组合中\n  },\n]);\n\n// 将节点移动到不同的组合\ngraph.updateNodeData([\n  {\n    id: 'node5',\n    combo: 'combo4', // 将节点5移动到新组合\n  },\n]);\n\n// 展开/折叠组合\ngraph.updateComboData([\n  {\n    id: 'combo1',\n    style: { collapsed: true }, // 折叠组合1\n  },\n]);\n\ngraph.render();\n```\n\n#### 树形结构数据\n\n对于树形结构，G6 支持使用 `children` 属性表示层次关系：\n\n```javascript\n// 树形结构数据\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst treeData = {\n  id: 'root',\n  children: [\n    {\n      id: 'child1',\n      children: [{ id: 'grandchild1' }],\n    },\n    {\n      id: 'child2',\n      children: [{ id: 'grandchild2' }],\n    },\n  ],\n};\n\nconst data = treeToGraphData(treeData);\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'dendrogram', // 或 'compactBox', 'mindmap' 等树布局\n    direction: 'TB', // 从上到下布局\n    nodeSep: 50, // 节点间距\n    rankSep: 100, // 层级间距\n  },\n});\n\ngraph.render();\n```\n\n通过 `treeToGraphData` 方法，可以将树形结构数据转换为 G6 的标准数据结构，实际传入到 `data` 中的数据结构如下：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"root\", \"depth\": 0, \"children\": [\"child1\", \"child2\"] },\n    { \"id\": \"child1\", \"depth\": 1, \"children\": [\"grandchild1\"] },\n    { \"id\": \"grandchild1\", \"depth\": 2 },\n    { \"id\": \"child2\", \"depth\": 1, \"children\": [\"grandchild2\"] },\n    { \"id\": \"grandchild2\", \"depth\": 2 }\n  ],\n  \"edges\": [\n    { \"source\": \"root\", \"target\": \"child1\" },\n    { \"source\": \"root\", \"target\": \"child2\" },\n    { \"source\": \"child1\", \"target\": \"grandchild1\" },\n    { \"source\": \"child2\", \"target\": \"grandchild2\" }\n  ]\n}\n```\n\n## 数据组织与最佳实践\n\n为了确保图的正确渲染和交互，建议按照 G6 标准数据结构组织数据。每个元素（节点、边、组合）应包含一个 `data` 字段，用于存放业务数据和自定义属性。\n\n- **避免使用与 G6 内部字段名称相同的标识符**，如 `id`、`type`、`style` 等，防止发生命名冲突。\n- 将业务数据（如用户信息、社交网络关系等）存储在 `data` 字段中，这样可以确保数据的灵活性和可扩展性。\n- **使用样式映射**来根据业务数据动态设置视觉属性，而不是直接修改样式对象。\n\n### 数据与样式分离\n\n良好的做法是将数据和样式分离，通过映射函数将数据属性转换为视觉属性：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 使用数据驱动样式\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', data: { value: 10, category: 'A' } },\n      { id: 'node2', data: { value: 5, category: 'B' } },\n    ],\n  },\n  node: {\n    style: {\n      // 根据数据中的 value 字段动态设置节点大小\n      size: (node) => 20 + node.data.value * 2,\n      // 根据数据中的 category 字段设置不同颜色\n      fill: (node) => {\n        const categoryColors = { A: '#F6BD16', B: '#5B8FF9' };\n        return categoryColors[node.data.category] || '#CCC';\n      },\n    },\n  },\n});\n```\n\n## API\n\nG6 提供了一系列的 API 来访问和操作数据，包括：\n\n- [getData](/api/data#graphgetdata)\n- [setData](/api/data#graphsetdata)\n- [getNodeData](/api/data#graphgetnodedata)\n- [getEdgeData](/api/data#graphgetedgedata)\n- [getComboData](/api/data#graphgetcombodata)\n- [addData](/api/data#graphadddata)\n- [addNodeData](/api/data#graphaddnodedata)\n- [addEdgeData](/api/data#graphaddedgedata)\n- [addComboData](/api/data#graphaddcombodata)\n- [updateData](/api/data#graphupdatedata)\n- [updateNodeData](/api/data#graphupdatenodedata)\n- [updateEdgeData](/api/data#graphupdateedgedata)\n- [updateComboData](/api/data#graphupdatecombodata)\n- [removeData](/api/data#graphremovedata)\n- [removeNodeData](/api/data#graphremovenodedata)\n- [removeEdgeData](/api/data#graphremoveedgedata)\n- [removeComboData](/api/data#graphremovecombodata)\n\n通过不同的 API，你可以方便地访问和操作图数据，实现图的增删改查等操作。\n\n## 使用远程数据\n\nG6 并不提供数据的获取和解析功能，对于本地 JSON 数据，你可以直接引入使用：\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\n对于远程数据，你可以使用 `fetch` 或者其他网络请求库来获取数据：\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // 使用 data\n    const graph = new Graph({\n      container: 'container',\n      data,\n    });\n    // 触发布局和渲染\n    graph.render();\n  })\n  .catch((error) => {\n    console.error('加载数据失败:', error);\n  });\n```\n","packages/site/docs/manual/element/combo/BaseCombo.en.md":"---\ntitle: Combo Common Options\norder: 1\n---\n\nThis document introduces the built-in combo common property configurations.\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {}, // Combo style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                               | Type                    | Default  | Required |\n| --------- | --------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name | [Type](#type)           | `circle` |          |\n| style     | Combo style configuration, including color, size, etc.    | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                  | [State](#state)         | -        |          |\n| palette   | Define combo palette for mapping colors based on data     | [Palette](#palette)     | -        |          |\n| animation | Define combo animation effects                            | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the combo type, built-in combo type name or custom combo name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select combo types based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Combo](/en/manual/element/combo/circle)\n- `rect`: [Rect Combo](/en/manual/element/combo/rect)\n\n## Style\n\nDefines combo style, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All style properties below support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Combo: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the combo data object (`ComboData`), containing all combo data information.\n\nA complete combo consists of the following parts:\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the primary shape of the combo, such as circle, rectangle, etc.\n- `label`: Text label, usually used to display the combo's name or description\n- `halo`: Graphic displaying halo effect around the main graphic\n- `badge`: Badge displayed at the top-right corner of the combo by default\n\nThe following style configurations will be explained by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the combo, defining the basic shape and appearance of the combo. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdd transparency and shadow effects to combos:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreate combos with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                              | Type                          | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current combo is collapsed                                                                                                   | boolean                       | false     |          |\n| cursor                          | Combo mouse hover style, [options](#cursor)                                                                                              | string                        | default   |          |\n| fill                            | Combo fill color                                                                                                                         | string                        | `#99ADD1` |          |\n| fillOpacity                     | Combo fill opacity                                                                                                                       | number \\| string              | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick | number                        | 0         |          |\n| lineCap                         | Combo stroke end cap style                                                                                                               | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                  | number[]                      | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                 | number                        | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                  | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                       | number                        | 1         |          |\n| opacity                         | Combo opacity                                                                                                                            | number \\| string              | 1         |          |\n| pointerEvents                   | How combo responds to pointer events, [options](#pointerevents)                                                                          | string                        | `auto`    |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                        | number                        | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                       | string                        | -         |          |\n| shadowOffsetX                   | Combo shadow offset in x direction                                                                                                       | number \\| string              | -         |          |\n| shadowOffsetY                   | Combo shadow offset in y direction                                                                                                       | number \\| string              | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                        | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Combo size, quick setting for combo width and height, [options](#size)                                                                   | number \\| number[]            | -         |          |\n| stroke                          | Combo stroke color                                                                                                                       | string                        | `#99ADD1` |          |\n| strokeOpacity                   | Combo stroke opacity                                                                                                                     | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given combo                                                        | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                           | string                        | -         |          |\n| visibility                      | Whether combo is visible                                                                                                                 | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                       | number                        | 0         |          |\n| y                               | Combo y coordinate                                                                                                                       | number                        | 0         |          |\n| z                               | Combo z coordinate                                                                                                                       | number                        | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                    | number                        | 0         |          |\n\n#### Size\n\nCombo size, quick setting for combo width and height, supports three configuration methods:\n\n- number: Indicates that combo width and height are the same as the specified value\n- [number, number]: Indicates that combo width and height are represented by array elements in order for combo width and height\n- [number, number, number]: Indicates that combo width, height, and depth are represented by array elements in order\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be the target of responding events\n- **`visiblepainted`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the `fill` value\n- **`visiblestroke`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n- **`visible`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by `fill` and `stroke` values\n- **`painted`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`fill`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the `fill` value\n  - Not affected by `visibility` value\n- **`stroke`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Will respond to events as long as entering the graphic fill and stroke areas, not affected by `fill`, `stroke`, `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Does not respond to events at all\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // Combo does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Style When Expanded\n\nMain graphic style when the combo is expanded\n\n| Attribute                       | Description                                                                                                                                       | Type                                                                            | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------- | -------- |\n| collapsed                       | Whether the combo is currently collapsed                                                                                                          | boolean                                                                         | false     |          |\n| cursor                          | Combo mouse hover style, [configuration item](#cursor)                                                                                            | string                                                                          | default   |          |\n| fill                            | Combo fill color                                                                                                                                  | string                                                                          | `#99ADD1` |          |\n| fillOpacity                     | Combo fill color opacity                                                                                                                          | number  string                                                                 | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0         |          |\n| lineCap                         | Combo stroke end style                                                                                                                            | `round`  `square`  `butt`                                                     | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                           | number[]                                                                        | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                          | number                                                                          | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                           | `round`  `bevel`  `miter`                                                     | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                                | number                                                                          | 1         |          |\n| opacity                         | Combo opacity                                                                                                                                     | number  string                                                                 | 1         |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                                 | number                                                                          | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                                | string                                                                          | -         |          |\n| shadowOffsetX                   | Combo shadow offset in the x-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowOffsetY                   | Combo shadow offset in the y-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                                 | `inner`  `outer`                                                               | `outer`   |          |\n| stroke                          | Combo stroke color                                                                                                                                | string                                                                          | `#99add1` |          |\n| strokeOpacity                   | Combo stroke color opacity                                                                                                                        | number  string                                                                 | 1         |          |\n| visibility                      | Whether the combo is visible                                                                                                                      | `visible`  `hidden`                                                            | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                                | number                                                                          | 0         |          |\n| y                               | Combo y coordinate                                                                                                                                | number                                                                          | 0         |          |\n| z                               | Combo z coordinate                                                                                                                                | number                                                                          | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                             | number                                                                          | 0         |          |\n| `{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items         | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -         |          |\n\n#### Cursor\n\nOptional 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`\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      fill: '#1783FF', // Fill color\n      stroke: '#000', // Stroke color\n      lineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: { fill: '#1783FF', stroke: '#000', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Style When Collapsed\n\nEffective when `collapsed` is `true`\n\n| Attribute                                | Description                                                                                                                                                                  | Type                                                                            | Default                                  | Required |\n| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------- | -------- |\n| collapsedCursor                          | Mouse hover style when the combo is collapsed, [configuration item](#cursor)                                                                                                 | string                                                                          | Same as the cursor when expanded         |          |\n| collapsedFill                            | Fill color when the combo is collapsed                                                                                                                                       | string                                                                          | Same as the fill when expanded           |          |\n| collapsedFillOpacity                     | Fill color opacity when the combo is collapsed                                                                                                                               | number  string                                                                 | 1                                        |          |\n| collapsedIncreasedLineWidthForHitTesting | When the combo is collapsed, if lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0                                        |          |\n| collapsedLineCap                         | Stroke end style when the combo is collapsed                                                                                                                                 | `round`  `square`  `butt`                                                     | Same as the lineCap when expanded        |          |\n| collapsedLineDash                        | Stroke dash style when the combo is collapsed                                                                                                                                | number[]                                                                        | Same as the lineDash when expanded       |          |\n| collapsedLineDashOffset                  | Stroke dash offset when the combo is collapsed                                                                                                                               | number                                                                          | Same as the lineDashOffset when expanded |          |\n| collapsedLineJoin                        | Stroke join style when the combo is collapsed                                                                                                                                | `round`  `bevel`  `miter`                                                     | Same as the lineJoin when expanded       |          |\n| collapsedLineWidth                       | Stroke width when the combo is collapsed                                                                                                                                     | number                                                                          | Same as the lineWidth when expanded      |          |\n| collapsedMarker                          | Whether to display the marker when the combo is collapsed, [configuration item](#collapsedMarkerStyle)                                                                       | boolean                                                                         | true                                     |          |\n| collapsedOpacity                         | Opacity when the combo is collapsed                                                                                                                                          | number  string                                                                 | Same as the opacity when expanded        |          |\n| collapsedShadowBlur                      | Shadow blur when the combo is collapsed                                                                                                                                      | number                                                                          | Same as the shadowBlur when expanded     |          |\n| collapsedShadowColor                     | Shadow color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the shadowColor when expanded    |          |\n| collapsedShadowOffsetX                   | Shadow offset in the x-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetX when expanded  |          |\n| collapsedShadowOffsetY                   | Shadow offset in the y-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetY when expanded  |          |\n| collapsedShadowType                      | Shadow type when the combo is collapsed                                                                                                                                      | `inner`  `outer`                                                               | Same as the shadowType when expanded     |          |\n| collapsedSize                            | Size when the combo is collapsed                                                                                                                                             | number &#124; [number, number] &#124; [number, number, number]                  | 32                                       |          |\n| collapsedStroke                          | Stroke color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the stroke when expanded         |          |\n| collapsedStrokeOpacity                   | Stroke color opacity when the combo is collapsed                                                                                                                             | number  string                                                                 | Same as the strokeOpacity when expanded  |          |\n| collapsedVisibility                      | Whether the combo is visible when collapsed                                                                                                                                  | `visible`  `hidden`                                                            | Same as the visibility when expanded     |          |\n| `collapsed{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items                                    | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -                                        |          |\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedFill: '#1783FF', // Fill color\n      collapsedStroke: '#000', // Stroke color\n      collapsedLineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: { collapsedFill: '#1783FF', collapsedStroke: '#000', collapsedLineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Collapsed Marker Style\n\nEffective when `collapsedMarker` is `true`\n\n| Attribute                     | Description                                                                                                                                                                                                                                                                                                                                                         | Type                                                                                                                               | Default       | Required |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| collapsedMarkerType           | Marker type displayed when the combo is collapsed <br> - `'child-count'`: Number of child elements (including Node and Combo) <br>- `'descendant-count'`: Number of descendant elements (including Node and Combo) <br>- `'node-count'`: Number of descendant elements (only including Node) <br> - `(children: NodeLikeData[]) => string`: Custom processing logic | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string)                             | `child-count` |          |\n| collapsedMarkerFill           | Icon text color                                                                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | #fff          |          |\n| collapsedMarkerFillOpacity    | Icon text color opacity                                                                                                                                                                                                                                                                                                                                             | number                                                                                                                             | 1             |          |\n| collapsedMarkerFontSize       | Icon font size                                                                                                                                                                                                                                                                                                                                                      | number                                                                                                                             | 12            |          |\n| collapsedMarkerFontWeight     | Icon font weight                                                                                                                                                                                                                                                                                                                                                    | number \\| string                                                                                                                   | `normal`      |          |\n| collapsedMarkerRadius         | Icon corner radius                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                             | 0             |          |\n| collapsedMarkerSrc            | Image source. Its priority is higher than `collapsedMarkerText`                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | -             |          |\n| collapsedMarkerText           | Icon text                                                                                                                                                                                                                                                                                                                                                           | string                                                                                                                             | -             |          |\n| collapsedMarkerTextAlign      | Icon text horizontal alignment                                                                                                                                                                                                                                                                                                                                      | `center`  `end`  `left`  `right`  `start`                                                                                      | `center`      |          |\n| collapsedMarkerTextBaseline   | Icon text alignment baseline                                                                                                                                                                                                                                                                                                                                        | `alphabetic`  `bottom`  `hanging`  `ideographic`  `middle`  `top`                                                             | `middle`      |          |\n| collapsedMarkerWidth          | Icon width                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                             | -             |          |\n| collapsedMarkerHeight         | Icon height                                                                                                                                                                                                                                                                                                                                                         | number                                                                                                                             | -             |          |\n| collapsedMarkerZIndex         | Icon rendering layer                                                                                                                                                                                                                                                                                                                                                | number                                                                                                                             | 1             |          |\n| `collapsedMarker{StyleProps}` | More icon style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text), [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) configuration items. For example, collapsedMarkerFontSize represents the font size of the text icon                                                                                           | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) &#124; [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) | -             |          |\n\n**Example:**\n\n```js {5-6}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF', // Fill color\n      collapsedMarkerFontSize: 30, // Icon font size\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 30,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Label Style\n\nLabels are used to display text information for combos, supporting rich text style configuration and flexible position layout.\n\n#### Basic Label Configuration\n\nAdd basic text label to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Sales Department', // Label text content\n      labelFill: '#1A1A1A', // Label text color\n      labelFontSize: 14, // Label font size\n      labelPlacement: 'bottom', // Label position: bottom\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nConfigure labels that support multi-line display:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'This is a combo label text content that supports multi-line display',\n      labelWordWrap: true, // Enable text wrapping\n      labelMaxWidth: 100, // Maximum width 100px\n      labelMaxLines: 3, // Maximum 3 lines\n      labelTextAlign: 'center', // Center text alignment\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Style Label\n\nCreate labels with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // Red text\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // Bold\n      labelFontStyle: 'italic', // Italic\n      labelTextDecorationLine: 'underline', // Underline\n      labelLetterSpacing: 2, // Letter spacing\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label style configurations:\n\n| Property                 | Description                                                                                                                                                                | Type                                                                        | Default   | Required |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show combo label                                                                                                                                                | boolean                                                                     | true      |          |\n| labelCursor              | Cursor style when hovering over combo label, [options](#cursor)                                                                                                            | string                                                                      | `default` |          |\n| labelFill                | Combo label text color                                                                                                                                                     | string                                                                      | #000      |          |\n| labelFillOpacity         | Combo label text color opacity                                                                                                                                             | number                                                                      | 1         |          |\n| labelFontFamily          | Combo label font family                                                                                                                                                    | string                                                                      | -         |          |\n| labelFontSize            | Combo label font size                                                                                                                                                      | number                                                                      | 12        |          |\n| labelFontStyle           | Combo label font style                                                                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Combo label font variant                                                                                                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Combo label font weight                                                                                                                                                    | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |          |\n| labelLeading             | Line spacing                                                                                                                                                               | number                                                                      | 0         |          |\n| labelLetterSpacing       | Combo label letter spacing                                                                                                                                                 | number \\| string                                                            | -         |          |\n| labelLineHeight          | Combo label line height                                                                                                                                                    | number \\| string                                                            | -         |          |\n| labelMaxLines            | Combo label maximum lines                                                                                                                                                  | number                                                                      | 1         |          |\n| labelMaxWidth            | Combo label maximum width, [options](#labelmaxwidth)                                                                                                                       | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Combo label X offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelOffsetY             | Combo label Y offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelPadding             | Combo label padding                                                                                                                                                        | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Combo label position relative to combo main graphic, [options](#labelplacement)                                                                                            | string                                                                      | `bottom`  |          |\n| labelText                | Combo label text content                                                                                                                                                   | string                                                                      | -         |          |\n| labelTextAlign           | Combo label text horizontal alignment                                                                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Combo label text baseline                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Combo label text decoration color                                                                                                                                          | string                                                                      | -         |          |\n| labelTextDecorationLine  | Combo label text decoration line                                                                                                                                           | string                                                                      | -         |          |\n| labelTextDecorationStyle | Combo label text decoration style                                                                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Combo label text overflow handling                                                                                                                                         | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Combo label text path                                                                                                                                                      | Path                                                                        | -         |          |\n| labelWordWrap            | Whether combo label enables auto line wrapping. When labelWordWrap is enabled, parts exceeding labelMaxWidth automatically wrap                                            | boolean                                                                     | false     |          |\n| labelZIndex              | Combo label rendering layer                                                                                                                                                | number                                                                      | 0         |          |\n| `label{StyleProps}`      | More label style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) property values. For example, labelOpacity represents label opacity | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |          |\n\n#### LabelPlacement\n\nLabel position relative to combo main graphic, available values:\n\n- `center`: Label at combo center\n- `top`, `bottom`, `left`, `right`: Label at top, bottom, left, right of combo\n- `top-left`, `top-right`, `bottom-left`, `bottom-right`: Label at four corners of combo\n- `left-top`, `left-bottom`, `right-top`, `right-bottom`: Label at edge endpoints of combo\n\n#### LabelMaxWidth\n\nWhen auto line wrapping `labelWordWrap` is enabled, text wraps when exceeding this width:\n\n- string: Defines maximum width as percentage relative to combo element width. For example, `50%` means label width doesn't exceed half of combo width\n- number: Defines maximum width in pixels. For example, 100 means label maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background provides background decoration for label text, improving label readability and visual effects.\n\n#### Basic Background Style\n\nAdd simple background to label:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Important Combo',\n      labelFill: '#fff', // White text\n      labelBackground: true, // Enable background\n      labelBackgroundFill: '#1783FF', // Blue background\n      labelBackgroundPadding: [4, 8], // Padding: vertical 4px, horizontal 8px\n      labelBackgroundRadius: 4, // Border radius\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Gradient Background Effect\n\nCreate label background with gradient effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP Combo',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // Gradient background\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // Large border radius\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Stroke-only Background Style\n\nCreate label background with stroke only:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Border Label',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // Transparent background\n      labelBackgroundStroke: '#1783FF', // Blue stroke\n      labelBackgroundLineWidth: 2, // Stroke width\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label background style configurations:\n\n| Property                      | Description                                                                                                                                                                                                | Type                                                         | Default      |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | Whether to show combo label background                                                                                                                                                                     | boolean                                                      | false        |\n| labelBackgroundCursor         | Combo label background cursor style, [options](#cursor)                                                                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | Combo label background fill color                                                                                                                                                                          | string                                                       | #000         |\n| labelBackgroundFillOpacity    | Combo label background opacity                                                                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | Combo label background height                                                                                                                                                                              | string \\| number                                             | -            |\n| labelBackgroundLineDash       | Combo label background dash configuration                                                                                                                                                                  | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | Combo label background dash offset                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | Combo label background stroke line width                                                                                                                                                                   | number                                                       | -            |\n| labelBackgroundPadding        | Combo label background padding                                                                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | Combo label background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values auto-filled                                    | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | Combo label background shadow blur                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundShadowColor    | Combo label background shadow color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | Combo label background shadow X offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | Combo label background shadow Y offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundStroke         | Combo label background stroke color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | Combo label background stroke opacity                                                                                                                                                                      | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | Whether combo label background is visible                                                                                                                                                                  | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | Combo label background rendering layer                                                                                                                                                                     | number                                                       | 1            |\n| `labelBackground{StyleProps}` | More label background style configurations, refer to [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) property values. For example, labelBackgroundOpacity represents label background opacity | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### Badge Style\n\nBadges are small markers displayed on combos, usually used to show status, quantity, or other auxiliary information. Multiple badges can be displayed simultaneously with customizable positions.\n\n#### Single Badge\n\nAdd a simple badge to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Display at top by default\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdd multiple badges at different positions to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // Whether to show badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nFully customize badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete badge style configurations:\n\n| Property     | Description                    | Type                                  | Default                           |\n| ------------ | ------------------------------ | ------------------------------------- | --------------------------------- |\n| badge        | Whether to show combo badge    | boolean                               | true                              |\n| badgePalette | Combo badge background palette | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Combo badge settings           | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                            | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether to show combo badge background                                                                                                                                                                                                                                                                 | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Combo badge background cursor style, [options](#cursor)                                                                                                                                                                                                                                                | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Combo badge background fill color. If not specified, consider badgePalette for sequential allocation                                                                                                                                                                                                   | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Combo badge background fill opacity                                                                                                                                                                                                                                                                    | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Combo badge background filter                                                                                                                                                                                                                                                                          | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Combo badge background height                                                                                                                                                                                                                                                                          | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Combo badge background dash configuration                                                                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Combo badge background dash offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Combo badge background stroke line width                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Combo badge background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values will be filled <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, space-separated | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Combo badge background shadow blur                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Combo badge background shadow color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Combo badge background shadow X offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Combo badge background shadow Y offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Combo badge background stroke color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Combo badge background stroke opacity                                                                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether combo badge background is visible                                                                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | Combo badge text color                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                 | -            |\n| fontFamily               | Combo badge font family                                                                                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| fontSize                 | Combo badge font size                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | Combo badge font style                                                                                                                                                                                                                                                                                 | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Combo badge font variant                                                                                                                                                                                                                                                                               | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Combo badge font weight                                                                                                                                                                                                                                                                                | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Combo badge line height                                                                                                                                                                                                                                                                                | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Combo badge line width                                                                                                                                                                                                                                                                                 | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Combo badge text maximum lines                                                                                                                                                                                                                                                                         | number                                                                                                                                                                 | 1            |\n| offsetX                  | Combo badge X offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| offsetY                  | Combo badge Y offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| padding                  | Combo badge padding                                                                                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Combo badge position relative to combo main graphic. If not specified, defaults to clockwise placement starting from top-right                                                                                                                                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Combo badge text content                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textAlign                | Combo badge text horizontal alignment                                                                                                                                                                                                                                                                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Combo badge text baseline                                                                                                                                                                                                                                                                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Combo badge text decoration color                                                                                                                                                                                                                                                                      | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Combo badge text decoration line                                                                                                                                                                                                                                                                       | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Combo badge text decoration style                                                                                                                                                                                                                                                                      | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Combo badge text overflow handling                                                                                                                                                                                                                                                                     | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether combo badge is visible                                                                                                                                                                                                                                                                         | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether combo badge text auto-wraps                                                                                                                                                                                                                                                                    | boolean                                                                                                                                                                | -            |\n| zIndex                   | Combo badge rendering layer                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | 3            |\n\n### Halo Style\n\nHalo effect is used to highlight combos, usually used in mouse hover, selected, or active states, adding glow effect around combos.\n\n#### Basic Halo Effect\n\nAdd simple halo effect to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // Enable halo\n      haloStroke: '#1783FF', // Blue halo\n      haloLineWidth: 8, // Halo width\n      haloStrokeOpacity: 0.3, // Halo opacity\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Halo Effect\n\nCreate colorful gradient halo effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // Red halo\n      haloLineWidth: 12, // Thicker halo\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // Blur filter effect\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dynamic Halo Effect\n\nUse halo effect in state transitions:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // No halo in default state\n      halo: false,\n    },\n    state: {\n      // Show orange halo in hover state\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // Show green halo in selected state\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete halo style configurations:\n\n| Property           | Description                                                                                                                                                                       | Type                                                                  | Default                         | Required |\n| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------- | -------- |\n| halo               | Whether to show combo halo                                                                                                                                                        | boolean                                                               | false                           |          |\n| haloCursor         | Combo halo cursor style, [options](#cursor)                                                                                                                                       | string                                                                | `default`                       |          |\n| haloDraggable      | Whether combo halo allows dragging                                                                                                                                                | boolean                                                               | true                            |          |\n| haloDroppable      | Whether combo halo allows receiving dragged elements                                                                                                                              | boolean                                                               | false                           |          |\n| haloFill           | Halo fill color                                                                                                                                                                   | string                                                                | Same as main graphic fill color |          |\n| haloFillRule       | Combo halo fill rule                                                                                                                                                              | `nonzero` \\| `evenodd`                                                | -                               |          |\n| haloFilter         | Combo halo filter effect, such as 'blur(2px)' for blur effect                                                                                                                     | string                                                                | -                               |          |\n| haloLineWidth      | Combo halo stroke width, controls halo thickness                                                                                                                                  | number                                                                | 12                              |          |\n| haloPointerEvents  | Whether combo halo effect responds to pointer events, [options](#pointerevents)                                                                                                   | string                                                                | `none`                          |          |\n| haloStroke         | Combo halo stroke color, **this property is used to set the color of halo around combo, helping to highlight the combo**                                                          | string                                                                | `#99add1`                       |          |\n| haloStrokeOpacity  | Combo halo stroke opacity, recommended to use 0.2-0.6 values for natural halo effect                                                                                              | number                                                                | 0.25                            |          |\n| haloVisibility     | Combo halo visibility                                                                                                                                                             | `visible` \\| `hidden`                                                 | `visible`                       |          |\n| haloZIndex         | Combo halo rendering layer, usually set to negative value to ensure halo is below combo main graphic                                                                              | number                                                                | -1                              |          |\n| `halo{StyleProps}` | More halo style configurations, refer to [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) options. For example, haloFillOpacity represents halo fill opacity | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                               |          |\n\n**Halo Usage Recommendations:**\n\n1. **Performance Consideration**: Halo effects increase rendering burden, recommend enabling only when necessary\n2. **Color Matching**: Halo color should coordinate with combo main color tone, avoid being too abrupt\n3. **Opacity Setting**: Reasonable opacity (0.2-0.6) can create natural halo effect\n4. **State Application**: Halo is usually used for hover, selected, active and other interactive states\n\n### Icon Style\n\nIcons are used to display text or image content in combos, usually located at the center of the combo, can be used to represent combo type or function.\n\n#### Text Icon\n\nUse text as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // Display letter A\n      iconFill: '#1783FF', // Blue text\n      iconFontSize: 24, // Large font\n      iconFontWeight: 'bold', // Bold\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Image Icon\n\nUse image as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Text Icon\n\nCreate text icon with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'Dept',\n      iconFill: '#FF4D4F', // Red text\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // Italic\n      iconTextDecorationLine: 'underline', // Underline\n      iconLetterSpacing: 1, // Letter spacing\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete icon style configurations:\n\n| Property                | Description                                                                                                               | Type                                                                        | Default                     |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to show combo icon                                                                                                | boolean                                                                     | true                        |\n| iconCursor              | Combo icon cursor style, [options](#cursor)                                                                               | string                                                                      | `default`                   |\n| iconFill                | Combo icon text color                                                                                                     | string                                                                      | -                           |\n| iconFillOpacity         | Combo icon text color opacity                                                                                             | number                                                                      | 1                           |\n| iconFontFamily          | Combo icon font family                                                                                                    | string                                                                      | -                           |\n| iconFontSize            | Combo icon font size                                                                                                      | number                                                                      | 16                          |\n| iconFontStyle           | Combo icon font style                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Combo icon font variant                                                                                                   | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Combo icon font weight                                                                                                    | number \\| string                                                            | `normal`                    |\n| iconHeight              | Combo icon height, used to control image size when using image icon                                                       | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Combo icon text letter spacing                                                                                            | number \\| string                                                            | -                           |\n| iconLineHeight          | Combo icon text line height                                                                                               | number \\| string                                                            | -                           |\n| iconMaxLines            | Combo icon text maximum lines                                                                                             | number                                                                      | 1                           |\n| iconOffsetX             | Combo icon X offset                                                                                                       | number                                                                      | 0                           |\n| iconOffsetY             | Combo icon Y offset                                                                                                       | number                                                                      | 0                           |\n| iconOpacity             | Combo icon opacity                                                                                                        | number                                                                      | 1                           |\n| iconRadius              | Combo icon border radius (only effective for rectangular icons)                                                           | number                                                                      | 0                           |\n| iconSrc                 | Combo image source. Has higher priority than iconText, supports local and network images                                  | string                                                                      | -                           |\n| iconText                | Combo icon text content, supports text, Unicode characters, etc.                                                          | string                                                                      | -                           |\n| iconTextAlign           | Combo icon text horizontal alignment                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`                    |\n| iconTextBaseline        | Combo icon text baseline                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`                    |\n| iconTextDecorationColor | Combo icon text decoration color                                                                                          | string                                                                      | -                           |\n| iconTextDecorationLine  | Combo icon text decoration line, such as underline, strikethrough, etc.                                                   | string                                                                      | -                           |\n| iconTextDecorationStyle | Combo icon text decoration style                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Combo icon text overflow handling                                                                                         | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconVisibility          | Whether combo icon is visible                                                                                             | `visible` \\| `hidden`                                                       | `visible`                   |\n| iconWidth               | Combo icon width, used to control image size when using image icon                                                        | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether combo icon text auto-wraps                                                                                        | boolean                                                                     | false                       |\n| iconZIndex              | Combo icon rendering layer                                                                                                | number                                                                      | 1                           |\n| `icon{StyleProps}`      | More icon style configurations, refer to specific icon type options. For example, iconStroke represents icon stroke color | -                                                                           | -                           |\n\n**Icon Usage Recommendations:**\n\n1. **Priority**: `iconSrc` (image) has higher priority than `iconText` (text), if both are set, image will be displayed first\n2. **Size Control**: Recommend setting icon size reasonably according to combo size, avoid icons being too large or small affecting visual effect\n3. **Performance Optimization**: Text icons have better performance, image icons require additional network requests and rendering overhead\n4. **Style Consistency**: Icon styles in the same graph should be consistent to improve overall visual effect\n5. **Accessibility**: Ensure icon color has sufficient contrast with background for easy user identification\n\n## State\n\nIn some interactive behaviors, such as clicking to select a combo or hovering to activate an edge, it is merely marking certain states on the element. To reflect these states in the visual space seen by the end user, we need to set different graphic element styles for different states to respond to changes in the element's state.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the default styles of the element.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\nFor example, when the combo is in the `focus` state, you can add a stroke with a width of 3 and a color of orange.\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n**⚠️ Dynamic Configuration**: State configuration also supports dynamic configuration, which can be used to set styles dynamically based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    state: {\n      // Static configuration\n      selected: {\n        stroke: '#1783FF',\n        lineWidth: 2,\n      },\n\n      // Dynamic configuration - arrow function form\n      hover: (datum) => ({\n        fill: datum.data.isVIP ? '#FFD700' : '#1783FF',\n        fillOpacity: 0.3,\n      }),\n\n      // Dynamic configuration - regular function form (access to graph instance)\n      active: function (datum) {\n        console.log(this); // graph instance\n        return {\n          stroke: datum.data.level > 3 ? '#FF4D4F' : '#52C41A',\n          lineWidth: 3,\n        };\n      },\n    },\n  },\n});\n```\n\n**⚠️ State Priority**: When a combo has multiple states simultaneously, the style merge follows the following priority (high to low):\n\n1. Later defined states override earlier defined states\n2. More specific selectors have higher priority\n3. Dynamic configuration has higher priority than static configuration\n\nFor example, if a combo has both `selected` and `hover` states, and `hover` is defined after `selected`, then `hover` state styles will override `selected` state styles.\n\n## Animation\n\nDefines the animation effects for combos, supporting the following two configuration methods:\n\n1. Disable all combo animations\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when combos enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when combo enters the canvas\n- `update`: Animation when combo updates\n- `exit`: Animation when combo leaves the canvas\n- `show`: Animation when combo shows from hidden state\n- `hide`: Animation when combo hides\n- `collapse`: Animation when combo collapses\n- `expand`: Animation when combo expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure combos, such as:\n\n#### Enter Animation\n\nConfigure animation when combo enters the canvas:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    animation: {\n      enter: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          from: 0, // Start from 0\n          to: 1, // End at 1\n          duration: 1000, // Animation duration\n          easing: 'ease-out', // Easing function\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Update Animation\n\nConfigure animation when combo updates:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      update: [\n        {\n          fields: ['x', 'y'], // Only animate x and y properties during update\n          duration: 1000, // Animation duration\n          easing: 'linear', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Exit Animation\n\nConfigure animation when combo leaves the canvas:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      exit: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          to: 0, // End at 0\n          duration: 500, // Animation duration\n          easing: 'ease-in', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Show/Hide Animation\n\nConfigure animation when combo shows/hides:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      show: [\n        {\n          fields: ['opacity'],\n          from: 0,\n          to: 1,\n          duration: 300,\n        },\n      ],\n      hide: [\n        {\n          fields: ['opacity'],\n          to: 0,\n          duration: 300,\n        },\n      ],\n    },\n  },\n});\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass `false` to disable specific stage animations:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // Disable combo enter animation\n    }\n  }\n}\n```\n\n**Animation Configuration Options:**\n\n| Property  | Description                             | Type                                                        | Default  |\n| --------- | --------------------------------------- | ----------------------------------------------------------- | -------- |\n| fields    | Properties to animate                   | string[]                                                    | -        |\n| from      | Starting value                          | number \\| string                                            | -        |\n| to        | Ending value                            | number \\| string                                            | -        |\n| duration  | Animation duration (milliseconds)       | number                                                      | 1000     |\n| easing    | Easing function                         | string                                                      | 'ease'   |\n| delay     | Animation delay (milliseconds)          | number                                                      | 0        |\n| repeat    | Number of repetitions (-1 for infinite) | number                                                      | 0        |\n| direction | Animation direction                     | 'normal' \\| 'reverse' \\| 'alternate' \\| 'alternate-reverse' | 'normal' |\n\n## Palette\n\nDefines combo color palette, i.e., predefined combo color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For palette definition, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                          | Type                              | Default |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |\n| type     | Specifies current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                  | `group` &#124; `value`            | `group` |\n| field    | Specifies grouping field in element data. If not specified, defaults to id as grouping field                         | string &#124; ((datum) => string) | `id`    |\n| color    | Palette colors. If palette is registered, you can directly specify its registration name, also accepts a color array | string &#124; string[]            | -       |\n| invert   | Whether to invert the palette                                                                                        | boolean                           | false   |\n\nFor example, assign combo colors to a group of data by `category` field, so that combos of the same category have the same color:\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau is palette name, defaults to assign colors by ID\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/combo/BaseCombo.zh.md":"---\ntitle: 组合通用配置项\norder: 1\n---\n\n本文介绍内置组合通用属性配置。\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {}, // 组合样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](#type)           | `circle` |      |\n| style     | 组合样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定组合类型，内置组合类型名称或自定义组合的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据组合数据动态选择组合类型：\n\n```js\nconst graph = new Graph({\n  combo: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形组合](/manual/element/combo/circle)\n- `rect`：[矩形组合](/manual/element/combo/rect)\n\n## Style\n\n定义组合的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据组合数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `组合: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为组合数据对象 (`ComboData`)，包含组合的所有数据信息。\n\n一个完整的组合由以下几部分构成：\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：组合的主图形，表示组合的主要形状，例如圆形、矩形等；\n- `label` ：文本标签，通常用于展示组合的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `badge` ：默认位于组合右上角的徽标；\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是组合的核心部分，定义了组合的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置组合的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为组合添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的组合：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前组合是否折叠                                                                          | boolean                       | false     |      |\n| cursor                          | 组合鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 组合填充色                                                                                | string                        | `#99ADD1` |      |\n| fillOpacity                     | 组合填充色透明度                                                                          | number \\| string              | 0.04      |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 组合描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 组合描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 组合描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 组合描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 组合描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 组合透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 组合如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 组合阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 组合阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 组合阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 组合阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 组合阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 组合大小，快捷设置组合宽高，[配置项](#size)                                               | number \\| number[]            | -         |      |\n| stroke                          | 组合描边色                                                                                | string                        | `#99ADD1` |      |\n| strokeOpacity                   | 组合描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定组合                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 组合是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 组合 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 组合 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 组合 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 组合渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n组合大小，快捷设置组合宽高，支持三种配置方式：\n\n- number：表示组合宽高相同为指定值\n- [number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度\n- [number, number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // 组合不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 收起时样式\n\n当组合处于收起状态时（`collapsed` 为 `true`），可以为其配置特殊的样式。收起时的样式属性以 `collapsed` 为前缀。\n\n#### 基础收起样式\n\n为收起状态的组合设置不同的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedFill: '#1783FF',\n      collapsedStroke: '#000',\n      collapsedLineWidth: 2,\n      collapsedSize: 40,\n      collapsedMarkerFill: '#fff',\n      collapsedMarkerFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时样式的完整配置：\n\n| 属性                                     | 描述                                                                                                  | 类型                          | 默认值                             | 必选 |\n| ---------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------------------------- | ---- |\n| collapsedCursor                          | 组合收起时的鼠标移入样式，[配置项](#cursor)                                                           | string                        | 默认与展开时的 cursor 一致         |      |\n| collapsedFill                            | 组合收起时的填充色                                                                                    | string                        | 默认与展开时的 fill 一致           |      |\n| collapsedFillOpacity                     | 组合收起时的填充色透明度                                                                              | number \\| string              | 1                                  |      |\n| collapsedIncreasedLineWidthForHitTesting | 组合收起时，当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0                                  |      |\n| collapsedLineCap                         | 组合收起时的描边端点样式                                                                              | `round` \\| `square` \\| `butt` | 默认与展开时的 lineCap 一致        |      |\n| collapsedLineDash                        | 组合收起时的描边虚线样式                                                                              | number[]                      | 默认与展开时的 lineDash 一致       |      |\n| collapsedLineDashOffset                  | 组合收起时的描边虚线偏移量                                                                            | number                        | 默认与展开时的 lineDashOffset 一致 |      |\n| collapsedLineJoin                        | 组合收起时的描边连接处样式                                                                            | `round` \\| `bevel` \\| `miter` | 默认与展开时的 lineJoin 一致       |      |\n| collapsedLineWidth                       | 组合收起时的描边宽度                                                                                  | number                        | 默认与展开时的 lineWidth 一致      |      |\n| collapsedMarker                          | 组合收起时是否显示标记，[配置项](#收起时标记样式)                                                     | boolean                       | true                               |      |\n| collapsedOpacity                         | 组合收起时的透明度                                                                                    | number \\| string              | 默认与展开时的 opacity 一致        |      |\n| collapsedShadowBlur                      | 组合收起时的阴影模糊度                                                                                | number                        | 默认与展开时的 shadowBlur 一致     |      |\n| collapsedShadowColor                     | 组合收起时的阴影颜色                                                                                  | string                        | 默认与展开时的 shadowColor 一致    |      |\n| collapsedShadowOffsetX                   | 组合收起时的阴影在 x 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetX 一致  |      |\n| collapsedShadowOffsetY                   | 组合收起时的阴影在 y 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetY 一致  |      |\n| collapsedShadowType                      | 组合收起时的阴影类型                                                                                  | `inner` \\| `outer`            | 默认与展开时的 shadowType 一致     |      |\n| collapsedSize                            | 组合收起时的大小                                                                                      | number \\| [number, number]    | 32                                 |      |\n| collapsedStroke                          | 组合收起时的描边色                                                                                    | string                        | 默认与展开时的 stroke 一致         |      |\n| collapsedStrokeOpacity                   | 组合收起时的描边色透明度                                                                              | number \\| string              | 默认与展开时的 strokeOpacity 一致  |      |\n| collapsedVisibility                      | 组合收起时是否可见                                                                                    | `visible` \\| `hidden`         | 默认与展开时的 visibility 一致     |      |\n\n### 收起时标记样式\n\n当 `collapsedMarker` 为 `true` 时显示的标记，用于显示收起组合内包含的元素数量。\n\n#### 自定义标记内容\n\n可以自定义收起标记显示的内容：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n      { id: 'node3', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerType: 'child-count',\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 14,\n      collapsedMarkerFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时标记样式的完整配置：\n\n| 属性                        | 描述                                                                                                                                                                                                                                                          | 类型                                                                                                   | 默认值        | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | ---- |\n| collapsedMarkerType         | 组合收起时显示的标记类型 <br> - `'child-count'`: 子元素数量（包括 Node 和 Combo）<br>- `'descendant-count'`: 后代元素数量（包括 Node 和 Combo）<br>- `'node-count'`: 后代元素数量（只包括 Node）<br> - `(children: NodeLikeData[]) => string`: 自定义处理逻辑 | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string) | `child-count` |      |\n| collapsedMarkerFill         | 标记文字颜色                                                                                                                                                                                                                                                  | string                                                                                                 | #fff          |      |\n| collapsedMarkerFillOpacity  | 标记文字颜色透明度                                                                                                                                                                                                                                            | number                                                                                                 | 1             |      |\n| collapsedMarkerFontSize     | 标记字体大小                                                                                                                                                                                                                                                  | number                                                                                                 | 12            |      |\n| collapsedMarkerFontWeight   | 标记字体粗细                                                                                                                                                                                                                                                  | number \\| string                                                                                       | `normal`      |      |\n| collapsedMarkerRadius       | 标记圆角半径                                                                                                                                                                                                                                                  | number                                                                                                 | 0             |      |\n| collapsedMarkerSrc          | 图片来源。其优先级高于 `collapsedMarkerText`                                                                                                                                                                                                                  | string                                                                                                 | -             |      |\n| collapsedMarkerText         | 标记文字                                                                                                                                                                                                                                                      | string                                                                                                 | -             |      |\n| collapsedMarkerTextAlign    | 标记文字水平对齐方式                                                                                                                                                                                                                                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                                                      | `center`      |      |\n| collapsedMarkerTextBaseline | 标记文字对齐基线                                                                                                                                                                                                                                              | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top`                            | `middle`      |      |\n| collapsedMarkerWidth        | 标记宽度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerHeight       | 标记高度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerZIndex       | 标记层级                                                                                                                                                                                                                                                      | number                                                                                                 | 1             |      |\n\n### 徽标样式\n\n徽标是组合上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为组合添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为组合添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 组合是否显示徽标   | boolean                               | true                              |\n| badgePalette | 组合徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 组合徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 组合徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 组合徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 组合徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 组合徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 组合徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 组合徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 组合徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 组合徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 组合徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 组合徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 组合徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 组合徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 组合徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 组合徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 组合徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 组合徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 组合徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | 组合徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 组合徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 组合徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 组合徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 组合徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 组合徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 组合徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 组合徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 组合徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 组合徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 组合徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 组合徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 组合徽标相对于组合主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 组合徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 组合徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 组合徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 组合徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 组合徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 组合徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 组合徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 组合徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 组合徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 组合徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 标签样式\n\n标签用于显示组合的文本信息，支持丰富的文本样式配置和灵活的位置布局。\n\n#### 基础标签配置\n\n为组合添加基本的文本标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '销售部门', // 标签文字内容\n      labelFill: '#1A1A1A', // 标签文字颜色\n      labelFontSize: 14, // 标签字体大小\n      labelPlacement: 'bottom', // 标签位置：底部\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n配置支持多行显示的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '这是一个支持多行显示的组合标签文本内容',\n      labelWordWrap: true, // 开启文本换行\n      labelMaxWidth: 100, // 最大宽度 100px\n      labelMaxLines: 3, // 最多显示 3 行\n      labelTextAlign: 'center', // 文本居中对齐\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义样式标签\n\n创建具有特殊样式的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // 红色文字\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // 粗体\n      labelFontStyle: 'italic', // 斜体\n      labelTextDecorationLine: 'underline', // 下划线\n      labelLetterSpacing: 2, // 字间距\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                                                                         | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示组合标签                                                                                                             | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入组合标签时显示的样式，[配置项](#cursor)                                                                              | string                                                                      | `default` |      |\n| labelFill                | 组合标签文字颜色                                                                                                             | string                                                                      | #000      |      |\n| labelFillOpacity         | 组合标签文字颜色的透明度                                                                                                     | number                                                                      | 1         |      |\n| labelFontFamily          | 组合标签字体族                                                                                                               | string                                                                      | -         |      |\n| labelFontSize            | 组合标签字体大小                                                                                                             | number                                                                      | 12        |      |\n| labelFontStyle           | 组合标签字体样式                                                                                                             | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 组合标签字体变种                                                                                                             | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 组合标签字体粗细                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |      |\n| labelLeading             | 行间距                                                                                                                       | number                                                                      | 0         |      |\n| labelLetterSpacing       | 组合标签字间距                                                                                                               | number \\| string                                                            | -         |      |\n| labelLineHeight          | 组合标签行高                                                                                                                 | number \\| string                                                            | -         |      |\n| labelMaxLines            | 组合标签最大行数                                                                                                             | number                                                                      | 1         |      |\n| labelMaxWidth            | 组合标签最大宽度，[配置项](#labelmaxwidth)                                                                                   | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 组合标签在 x 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelOffsetY             | 组合标签在 y 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelPadding             | 组合标签内边距                                                                                                               | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 组合标签相对于组合主图形的位置，[配置项](#labelplacement)                                                                    | string                                                                      | `bottom`  |      |\n| labelText                | 组合标签文字内容                                                                                                             | string                                                                      | -         |      |\n| labelTextAlign           | 组合标签文本水平对齐方式                                                                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 组合标签文本基线                                                                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 组合标签文本装饰线颜色                                                                                                       | string                                                                      | -         |      |\n| labelTextDecorationLine  | 组合标签文本装饰线                                                                                                           | string                                                                      | -         |      |\n| labelTextDecorationStyle | 组合标签文本装饰线样式                                                                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 组合标签文本溢出处理方式                                                                                                     | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 组合标签文本路径                                                                                                             | Path                                                                        | -         |      |\n| labelWordWrap            | 组合标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行                                           | boolean                                                                     | false     |      |\n| labelZIndex              | 组合标签渲染层级                                                                                                             | number                                                                      | 0         |      |\n| `label{StyleProps}`      | 更多标签样式配置，参考 [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) 属性值。比如 labelOpacity 代表标签透明度 | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |      |\n\n#### LabelPlacement\n\n标签相对于组合主图形的位置，可选值有：\n\n- `center`：标签位于组合中心\n- `top`、`bottom`、`left`、`right`：标签位于组合的上、下、左、右方\n- `top-left`、`top-right`、`bottom-left`、`bottom-right`：标签位于组合的四个角\n- `left-top`、`left-bottom`、`right-top`、`right-bottom`：标签位于组合边的端点\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于组合元素宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过组合宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景为标签文字提供背景装饰，可以提升标签的可读性和视觉效果。\n\n#### 基础背景样式\n\n为标签添加简单的背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '重要组合',\n      labelFill: '#fff', // 白色文字\n      labelBackground: true, // 启用背景\n      labelBackgroundFill: '#1783FF', // 蓝色背景\n      labelBackgroundPadding: [4, 8], // 内边距：垂直4px，水平8px\n      labelBackgroundRadius: 4, // 圆角半径\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 渐变背景效果\n\n创建带渐变效果的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP组合',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // 渐变背景\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // 大圆角\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 描边背景样式\n\n创建只有描边的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '边框标签',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // 透明背景\n      labelBackgroundStroke: '#1783FF', // 蓝色描边\n      labelBackgroundLineWidth: 2, // 描边宽度\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签背景样式配置：\n\n| 属性                          | 描述                                                                                                                                           | 类型                                                         | 默认值       |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | 组合标签背景是否显示                                                                                                                           | boolean                                                      | false        |\n| labelBackgroundCursor         | 组合标签背景鼠标移入样式，[配置项](#cursor)                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | 组合标签背景填充色                                                                                                                             | string                                                       | #000         |\n| labelBackgroundFillOpacity    | 组合标签背景透明度                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | 组合标签背景高度                                                                                                                               | string \\| number                                             | -            |\n| labelBackgroundLineDash       | 组合标签背景虚线配置                                                                                                                           | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | 组合标签背景虚线偏移量                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | 组合标签背景描边线宽                                                                                                                           | number                                                       | -            |\n| labelBackgroundPadding        | 组合标签背景内间距                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | 组合标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充                                 | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | 组合标签背景阴影模糊程度                                                                                                                       | number                                                       | -            |\n| labelBackgroundShadowColor    | 组合标签背景阴影颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | 组合标签背景阴影 X 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | 组合标签背景阴影 Y 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundStroke         | 组合标签背景描边颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | 组合标签背景描边透明度                                                                                                                         | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | 组合标签背景是否可见                                                                                                                           | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | 组合标签背景渲染层级                                                                                                                           | number                                                       | 1            |\n| `labelBackground{StyleProps}` | 更多标签背景样式配置，参考 [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) 属性值。例如 labelBackgroundOpacity 代表标签背景透明度 | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### 光晕样式\n\n光晕效果用于突出显示组合，通常在鼠标悬停、选中或激活状态下使用，为组合周围添加发光效果。\n\n#### 基础光晕效果\n\n为组合添加简单的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // 启用光晕\n      haloStroke: '#1783FF', // 蓝色光晕\n      haloLineWidth: 8, // 光晕宽度\n      haloStrokeOpacity: 0.3, // 光晕透明度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色光晕效果\n\n创建彩色渐变的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // 红色光晕\n      haloLineWidth: 12, // 较粗的光晕\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // 模糊滤镜效果\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 动态光晕效果\n\n在状态切换时使用光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // 默认状态下不显示光晕\n      halo: false,\n    },\n    state: {\n      // 悬停状态显示橙色光晕\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // 选中状态显示绿色光晕\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性               | 描述                                                                                                                                           | 类型                                                                  | 默认值                       | 必选 |\n| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------- | ---- |\n| halo               | 是否显示组合光晕                                                                                                                               | boolean                                                               | false                        |      |\n| haloCursor         | 组合光晕鼠标移入样式，[配置项](#cursor)                                                                                                        | string                                                                | `default`                    |      |\n| haloDraggable      | 组合光晕是否允许拖拽                                                                                                                           | boolean                                                               | true                         |      |\n| haloDroppable      | 组合光晕是否允许接收被拖拽的元素                                                                                                               | boolean                                                               | false                        |      |\n| haloFill           | 光晕填充色                                                                                                                                     | string                                                                | 与主图形的填充色 `fill` 一致 |      |\n| haloFillRule       | 组合光晕填充规则                                                                                                                               | `nonzero` \\| `evenodd`                                                | -                            |      |\n| haloFilter         | 组合光晕滤镜效果，如 'blur(2px)' 可创建模糊效果                                                                                                | string                                                                | -                            |      |\n| haloLineWidth      | 组合光晕描边宽度，控制光晕的粗细程度                                                                                                           | number                                                                | 12                           |      |\n| haloPointerEvents  | 组合光晕效果是否响应指针事件，[配置项](#pointerevents)                                                                                         | string                                                                | `none`                       |      |\n| haloStroke         | 组合光晕描边色，**此属性用于设置组合周围光晕的颜色，帮助突出显示组合**                                                                         | string                                                                | `#99add1`                    |      |\n| haloStrokeOpacity  | 组合光晕描边色透明度，建议使用 0.2-0.6 的值以获得自然的光晕效果                                                                                | number                                                                | 0.25                         |      |\n| haloVisibility     | 组合光晕可见性                                                                                                                                 | `visible` \\| `hidden`                                                 | `visible`                    |      |\n| haloZIndex         | 组合光晕渲染层级，通常设置为负值以确保光晕在组合主图形下方                                                                                     | number                                                                | -1                           |      |\n| `halo{StyleProps}` | 更多光晕样式配置，参考 [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) 配置项。例如 haloFillOpacity 代表光晕填充色透明度 | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                            |      |\n\n**光晕使用建议：**\n\n1. **性能考虑**：光晕效果会增加渲染负担，建议在必要时才启用\n2. **颜色搭配**：光晕颜色应与组合主色调协调，避免过于突兀\n3. **透明度设置**：合理的透明度（0.2-0.6）可以创造自然的光晕效果\n4. **状态应用**：光晕通常用于 hover、selected、active 等交互状态\n\n### 图标样式\n\n图标用于在组合中显示文字或图片内容，通常位于组合的中心位置，可以用来表示组合的类型或功能。\n\n#### 文字图标\n\n使用文字作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // 显示字母 A\n      iconFill: '#1783FF', // 蓝色文字\n      iconFontSize: 24, // 大字体\n      iconFontWeight: 'bold', // 粗体\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 图片图标\n\n使用图片作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色文字图标\n\n创建带有特殊样式的文字图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: '部门',\n      iconFill: '#FF4D4F', // 红色文字\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // 斜体\n      iconTextDecorationLine: 'underline', // 下划线\n      iconLetterSpacing: 1, // 字间距\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                                                         | 类型                                                                        | 默认值           |\n| ----------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示组合图标                                                             | boolean                                                                     | true             |\n| iconCursor              | 组合图标鼠标移入样式，[配置项](#cursor)                                      | string                                                                      | `default`        |\n| iconFill                | 组合图标文字颜色                                                             | string                                                                      | -                |\n| iconFillOpacity         | 组合图标文字颜色透明度                                                       | number                                                                      | 1                |\n| iconFontFamily          | 组合图标字体族                                                               | string                                                                      | -                |\n| iconFontSize            | 组合图标字体大小                                                             | number                                                                      | 16               |\n| iconFontStyle           | 组合图标字体样式                                                             | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 组合图标字体变种                                                             | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 组合图标字体粗细                                                             | number \\| string                                                            | `normal`         |\n| iconHeight              | 组合图标高度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 组合图标文本字间距                                                           | number \\| string                                                            | -                |\n| iconLineHeight          | 组合图标文本行高                                                             | number \\| string                                                            | -                |\n| iconMaxLines            | 组合图标文本最大行数                                                         | number                                                                      | 1                |\n| iconOffsetX             | 组合图标在 x 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOffsetY             | 组合图标在 y 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOpacity             | 组合图标透明度                                                               | number                                                                      | 1                |\n| iconRadius              | 组合图标圆角半径（仅对矩形图标有效）                                         | number                                                                      | 0                |\n| iconSrc                 | 组合图片来源。其优先级高于 iconText，支持本地图片和网络图片                  | string                                                                      | -                |\n| iconText                | 组合图标文字内容，支持文字、Unicode 字符等                                   | string                                                                      | -                |\n| iconTextAlign           | 组合图标文本水平对齐方式                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`         |\n| iconTextBaseline        | 组合图标文本基线                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`         |\n| iconTextDecorationColor | 组合图标文本装饰线颜色                                                       | string                                                                      | -                |\n| iconTextDecorationLine  | 组合图标文本装饰线，如下划线、删除线等                                       | string                                                                      | -                |\n| iconTextDecorationStyle | 组合图标文本装饰线样式                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 组合图标文本溢出处理方式                                                     | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconVisibility          | 组合图标是否可见                                                             | `visible` \\| `hidden`                                                       | `visible`        |\n| iconWidth               | 组合图标宽度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 组合图标文本是否自动换行                                                     | boolean                                                                     | false            |\n| iconZIndex              | 组合图标渲染层级                                                             | number                                                                      | 1                |\n| `icon{StyleProps}`      | 更多图标样式配置，参考图标的具体类型配置项。例如 iconStroke 代表图标描边颜色 | -                                                                           | -                |\n\n**图标使用建议：**\n\n1. **优先级**：`iconSrc`（图片）的优先级高于 `iconText`（文字），如果同时设置，会优先显示图片\n2. **尺寸控制**：建议根据组合大小合理设置图标尺寸，避免图标过大或过小影响视觉效果\n3. **性能优化**：使用文字图标性能更好，图片图标需要额外的网络请求和渲染开销\n4. **样式一致性**：在同一个图中的组合图标样式应保持一致，提升整体视觉效果\n5. **可访问性**：确保图标颜色与背景有足够的对比度，便于用户识别\n\n## State\n\n在一些交互行为中，比如点击选中一个组合或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\n例如，当组合处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义组合的动画效果，支持下列两种配置方式：\n\n1. 关闭组合全部动画\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指组合在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 组合进入画布时的动画\n- `update`: 组合更新时的动画\n- `exit`: 组合离开画布时的动画\n- `show`: 组合从隐藏状态显示时的动画\n- `hide`: 组合隐藏时的动画\n- `collapse`: 组合收起时的动画\n- `expand`: 组合展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置组合，如：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // 关闭组合入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义组合的色板，即预定义组合颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                              | 默认值  |\n| ------ | ------------------------------------------------------------------- | --------------------------------- | ------- |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` &#124; `value`            | `group` |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string &#124; ((datum) => string) | `id`    |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string &#124; string[]            | -       |\n| invert | 是否反转色板                                                        | boolean                           | false   |\n\n如将一组数据按 `category` 字段分配组合颜色，使得同类别的组合颜色相同：\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/combo/CircleCombo.en.md":"---\ntitle: Circle Combo\norder: 2\n---\n\n## Overview\n\nThe circular combo wraps child nodes or child combos with a circular boundary, suitable for representing equal or non-hierarchical group relationships.\n\nApplicable scenarios:\n\n- Suitable for representing node groups without a clear hierarchical relationship. The circular combo can reflect the equality of members, such as user groups in social networks or decentralized team structures (highlighting collaboration).\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example shows the distribution of interest group members:\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","packages/site/docs/manual/element/combo/CircleCombo.zh.md":"---\ntitle: 圆形组合 Circle\norder: 2\n---\n\n## 概述\n\n圆形组合以圆形边界包裹子节点或子组合，适合表示平等或非层级化的群组关系。\n\n适用场景：\n\n- 适合表示无明确层级关系的节点群组，圆形组合能体现成员的平等性，如社交网络中的用户群体、分散式团队结构（突出协作性）。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为兴趣小组人员分布：\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","packages/site/docs/manual/element/combo/RectCombo.en.md":"---\ntitle: Rect Combo\norder: 3\n---\n\n## Overview\n\nThe rectangular combo organizes content with right-angle boundaries, supporting strict hierarchical structures.\n\nApplicable scenarios:\n\n- **System Architecture Diagrams**: Such as service layering within system architecture, and subdivisions within each layer.\n- **Geographical Area Division**: Such as cities containing multiple areas, where the rectangular combo can intuitively display administrative boundaries or functional divisions.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example is a simple microservice architecture service layer:\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","packages/site/docs/manual/element/combo/RectCombo.zh.md":"---\ntitle: 矩形组合 Rect\norder: 3\n---\n\n## 概述\n\n矩形组合以直角边界组织内容，支持严格的层级结构。\n\n适用场景：\n\n- **系统架构图**：如系统架构里面的服务分层，以及每层服务里面的细分等。\n- **地理区域划分**：如城市包含多个区域，矩形组合能直观展示行政边界或功能分区。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为简单的微服务架构服务层：\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","packages/site/docs/manual/element/combo/custom-combo.en.md":"---\ntitle: Custom Combo\norder: 4\n---\n\nG6 provides two types of [built-in combos](/en/manual/element/combo/base-combo): circular combos and rectangular combos. However, in complex business scenarios, you may need to create custom combos with specific styles, interactive effects, or behavior logic.\n\n## Before You Start: Understanding the Basic Composition of Combos\n\nIn G6, a complete combo typically consists of the following parts:\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the main shape of the combo, such as a circle, rectangle, etc.\n- `label`: Text label, usually used to display the name or description of the combo.\n- `halo`: A graphic that displays a halo effect around the main graphic.\n\n### Special Characteristics of Combos\n\nCombos differ from ordinary nodes and have the following characteristics:\n\n1. **Containment**: Combos can contain nodes and other combos, forming a hierarchical structure.\n2. **Two States**: Expanded and Collapsed states.\n3. **Adaptive Size**: Automatically adjusts size based on internal elements.\n4. **Drag Behavior**: Supports overall dragging and dragging elements in/out.\n\n## Ways to Customize Combos <Badge type=\"warning\">Choose the Right Way</Badge>\n\nThere are two ways to create custom combos:\n\n### 1. Inherit Existing Combo Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most common way, and you can choose to inherit one of the following types:\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - The most basic combo class, providing core functionality for combos.\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - Circular combo.\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - Rectangular combo.\n\n**Why choose this way?**\n\n- 📌 **Less Code**: Reuse existing combo properties and methods, focusing only on new features.\n- 📌 **Fast Development**: Suitable for most project needs, quickly achieving business goals.\n- 📌 **Easy Maintenance**: Clear code structure and clear inheritance relationships.\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing combo types (recommended), you can jump directly to [Create Your First Custom Combo in Three Steps](#create-your-first-custom-combo-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Develop from Scratch Based on the G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing combo types do not meet your needs, you can create combos from scratch based on the underlying graphics system of G.\n\n**Why choose this way?**\n\n- 📌 **Maximum Freedom**: Full control over every detail of the combo, achieving any complex effect.\n- 📌 **Special Needs**: Highly customized scenarios that existing combo types cannot meet.\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios.\n\n:::warning{title=Note}\nDeveloping custom combos from scratch requires handling all details yourself, including graphic drawing, event response, state changes, expand/collapse logic, etc., which is quite challenging. You can directly refer to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) for implementation.\n:::\n\n## Create Your First Custom Combo in Three Steps\n\nLet's start by inheriting `BaseCombo` to implement a custom hexagon combo:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// Define the path for the collapsed state button\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// Define the path for the expanded state button\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the expand/collapse button, using paths for finer control\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Override the render method to add more custom graphics\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // Use lifecycle hooks to add event listeners\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// Register the custom combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// Create a graph instance and use the custom combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Step 1: Write the Custom Combo Class\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// Define button path generation functions\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic, directly using path data\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic, using path type to directly pass in style objects\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the collapse/expand button, using SVG paths for finer control\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Use lifecycle hook methods to bind events\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### Step 2: Register the Custom Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### Step 3: Apply the Custom Combo\n\n```js\nconst graph = new Graph({\n  // ...other configurations\n  combo: {\n    type: 'hexagon-combo', // Use the name registered\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // Since we implemented the collapse/expand feature ourselves, only drag behavior is needed here\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 Congratulations! You have created your first custom combo.\n\n## Going Further: Understanding the Principles of Combo Drawing\n\n### Differences Between Combos and Nodes\n\nAlthough Combos inherit from `BaseNode`, there are some key differences:\n\n1. **Adaptive Size**: Combos automatically calculate the appropriate size based on internal elements.\n2. **Expand/Collapse States**: Combos have two display states and need to handle state transitions.\n3. **Hierarchical Structure**: Combos can be nested, forming hierarchical relationships.\n4. **Internal Element Management**: Combos need to manage the nodes and sub-combos they contain.\n\n### Atomic Graphics\n\nG6's Combos are drawn using atomic graphic units provided by the [G Graphics System](https://g.antv.antgroup.com/). For an introduction to atomic graphics, please refer to the [Element - Shape (Optional)](/en/manual/element/shape/overview) documentation.\n\nAll these graphics can be dynamically created or updated using `upsert()` and automatically manage graphic states and lifecycles.\n\n### Element Base Class\n\nBefore customizing Combos, you need to understand some important properties and methods in the G6 element base class:\n\n#### Properties\n\n| Property   | Type                          | Description                                               |\n| ---------- | ----------------------------- | --------------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under the current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under the current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom Combos, you will frequently use the `upsert` method. It is short for \"update or insert\" and is responsible for adding or updating graphics in the element:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| key       | string                                  | Key of the graphic, corresponding to the key in `shapeMap`. Built-in keys include `'key'`, `'label'`, `'halo'`, `'icon'`, `'port'`, `'badge'`<br/> Keys should not use special symbols, and will be converted to camel case to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                  |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                 |\n\nFor example, insert a fixed-position purple circle:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics with `container.appendChild()`? Because:\n\n1. **Better Performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and recreating them, greatly improving rendering performance.\n2. **Simpler Code**: No need to manually check if elements exist.\n3. **Easy Management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, and you can easily access them with `this.getShape(key)`.\n\n#### `render(attributes, container)`: Main Entry for Rendering Combos\n\nEvery custom combo class must implement the `render(attributes, container)` method, which defines how the combo is \"drawn\". You can use various atomic graphics here to create the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation or have interactions between sub-graphics. In this case, the `getShape` method can help you access any graphics previously created with `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, make sure A is created first.\n\n### Element Conventions\n\n- **Use Convention Properties**\n\nThe convention properties in combos include:\n\n- Use `this.getKeySize(attributes)` to get the size of the combo, considering the collapsed state and sub-elements.\n- Use `this.getContentBBox(attributes)` to get the bounding box of the content area.\n- Use `this.getComboPosition(attributes)` to get the current position of the combo, based on state and sub-elements.\n\n- **Use `getXxxStyle` and `drawXxxShape` Pairing for Graphic Drawing**\n\n`getXxxStyle` is used to get the graphic style, and `drawXxxShape` is used to draw the graphic. Graphics created this way support automatic animation execution.\n\n> `Xxx` is the camel case form of the key passed to the [upsert](#methods) method.\n\n- **Access Graph Context via `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, and you can override these methods in custom combos to execute specific logic at key moments:\n\n| Hook Function | Trigger Timing                                                     | Typical Use Cases                                                                |\n| ------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| `onCreate`    | After the combo is created and the entrance animation is completed | Bind interactive events, initialize combo state, add external listeners          |\n| `onUpdate`    | After the combo is updated and the update animation is completed   | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | After the combo is destroyed and the exit animation is completed   | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"drawing logic\"**.\n\nYou can define styles for each state in the combo configuration:\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\nThis state will be passed into the `render()` method's `attributes` and automatically applied to the graphics as a result of the internal system merging.\n\nYou can also customize rendering logic based on the state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","packages/site/docs/manual/element/combo/custom-combo.zh.md":"---\ntitle: 自定义 Combo\norder: 4\n---\n\nG6 提供了两种 [内置组合](/manual/element/combo/base-combo) 类型：圆形组合和矩形 Combo 。但在复杂的业务场景中，你可能需要创建具有特定样式、交互效果或行为逻辑的自定义 Combo 。\n\n## 开始之前：了解 Combo 的基本构成\n\n在 G6 中，一个完整的 Combo 通常由以下几个部分组成：\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ： Combo 的主图形，表示 Combo 的主要形状，如圆形、矩形等；\n- `label` ：文本标签，通常用于展示 Combo 的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n\n### Combo 的特殊性\n\nCombo 不同于普通节点，它具有以下特性：\n\n1. **包含性**： Combo 可以包含节点和其他 Combo ，形成层级结构\n2. **两种状态**：展开(Expanded)和收起(Collapsed)状态\n3. **自适应大小**：根据内部元素动态调整大小\n4. **拖拽行为**：支持整体拖拽及内部元素拖入/拖出\n\n## 自定义 Combo 的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义 Combo 的方式有两种途径：\n\n### 1. 继承现有 Combo 类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - 最基础的 Combo 类，提供 Combo 的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - 圆形 Combo\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - 矩形 Combo\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有 Combo 的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有组合类型（推荐），可以直接跳到 [三步创建你的第一个自定义 Combo](#三步创建你的第一个自定义-combo) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有 Combo 类型都不满足需求，你可以基于 G 的底层图形系统从零创建 Combo。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制 Combo 的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有 Combo 类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义 Combo 需要自行处理所有细节，包括图形绘制、事件响应、状态变化、展开/收起逻辑等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义 Combo\n\n让我们从继承 `BaseCombo` 开始，实现一个自定义六边形 Combo ：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// 定义收起状态的按钮路径\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// 定义展开状态的按钮路径\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建SVG路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制展开/收起按钮，使用路径实现更精细的控制\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 重写render方法，添加更多自定义图形\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // 使用生命周期钩子添加事件监听\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// 注册自定义 Combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// 创建图实例并使用自定义 Combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义 Combo 类\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// 定义按钮路径生成函数\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建 SVG 路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式，直接使用路径数据\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形，使用 path 类型直接传入样式对象\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制收起/展开按钮，使用 SVG 路径实现更精细的控制\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 使用生命周期钩子方法绑定事件\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### 第二步：注册自定义 Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### 第三步：应用自定义 Combo\n\n```js\nconst graph = new Graph({\n  // ...其他配置\n  combo: {\n    type: 'hexagon-combo', // 使用注册时的名称\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // 由于我们自己实现了折叠展开功能，这里只需要拖拽行为\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 恭喜！你已经创建了第一个自定义 Combo 。\n\n## 更进一步：理解 Combo 绘制的原理\n\n### Combo 与节点的区别\n\n虽然 Combo 继承自 `BaseNode`，但有一些关键区别：\n\n1. **自适应大小**： Combo 会根据内部元素自动计算合适的大小\n2. **展开/收起状态**： Combo 有两种显示状态，并需要处理状态切换\n3. **层级结构**： Combo 可以嵌套，形成层级关系\n4. **内部元素管理**： Combo 需要管理其包含的节点和子 Combo\n\n### 原子图形\n\nG6 的 Combo 是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。原子图形的介绍请参考 [元素 - 图形（可选）](/manual/element/shape/overview) 文档。\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义 Combo 之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义 Combo 时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见 [元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                                |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                          |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染组合的主入口\n\n每个自定义 Combo 类都必须实现 `render(attributes, container)` 方法，它定义了该组合如何被\"绘制\"出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n组合中约定的元素属性包括：\n\n- 通过 `this.getKeySize(attributes)` 获取组合的尺寸，考虑折叠状态和子元素\n- 通过 `this.getContentBBox(attributes)` 获取内容区域的边界盒\n- 通过 `this.getComboPosition(attributes)` 获取组合的当前位置，基于状态和子元素\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义 Combo 中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                   | 典型用途                                     |\n| ----------- | -------------------------- | -------------------------------------------- |\n| `onCreate`  | 当组合创建后完成入场动画时 | 绑定交互事件、初始化组合状态、添加外部监听器 |\n| `onUpdate`  | 当组合更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果     |\n| `onDestroy` | 当组合完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知       |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **\"状态响应\"** 与 **\"绘制逻辑\"** 分离。\n\n你可以在组合配置中定义每种状态下的样式：\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","packages/site/docs/manual/element/combo/overview.en.md":"---\ntitle: Combo Overview\norder: 0\n---\n\n## What is a Combo\n\nA Combo, short for Combination, is a special type of graph element in G6 that can contain nodes and sub-combos, similar to the concept of \"groups\" or \"containers.\" It is typically used to represent set relationships, such as a department containing multiple employees or a city containing multiple regions.\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=Note}\nIt is not recommended to use Combos in **tree graphs**. The layout mechanism of tree graphs is incompatible with that of Combos, which can lead to node misalignment or style confusion.\n:::\n\nG6 has built-in Combos including `circle` (circular combo) and `rect` (rectangular combo), as shown in the images below:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## Data Structure\n\nWhen defining a Combo, you need to add a `combos` field to the graph's data object. Each Combo is an object with the following structure:\n\n| Attribute | Description                                                                                            | Type           | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------ | -------------- | ------- | -------- |\n| id        | Unique identifier of the combo                                                                         | string         | -       | ✓        |\n| type      | Combo type, name of built-in combo type or custom combo name, such as `circle` or `rect`               | string         | -       |          |\n| data      | Combo data, used to store custom data of the combo, accessible via callback functions in style mapping | object         | -       |          |\n| style     | Combo style                                                                                            | object         | -       |          |\n| states    | Initial states of the combo                                                                            | string[]       | -       |          |\n| combo     | Parent combo ID. If there is no parent combo, it is null                                               | string \\| null | -       |          |\n\nAn example of a data item in the `combos` array:\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\nTo assign a node to a Combo, you can add a `combo` field to the node data:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 belongs to comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // define comboA\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure Combos, listed in order of priority from highest to lowest:\n\n- Use `graph.setCombo()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setCombo()`\n\nYou can dynamically set the style mapping logic of Combos using `graph.setCombo()` after the graph instance is created.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nYou can configure Combo style mapping globally during graph instantiation. This configuration will apply to all Combos.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Specify combo type and combo style type in the combo configuration\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different Combos, you can write the configuration into the Combo data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\n// Specify combo type and combo style type in the data\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## Example\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo Interaction\n\nSimply rendering a Combo does not provide much practical value; it is only when a series of interactive operations are supported that the value of Combos can be maximized.\n\nIn G6, we have built-in interactions such as `drag-element` and `collapse-expand`.\n\n#### drag-element\n\nSupports dragging nodes and Combos. During the dragging of a Combo, the positions of nodes and edges within the Combo will dynamically change. After dragging is complete, the relative positions of the Combo and nodes remain unchanged. You can also change the affiliation of the Combo during dragging by setting `dropEffect: 'link'`.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\nSupports double-clicking a Combo to collapse and expand it. After collapsing a Combo, all nodes within the Combo are hidden. If there are connections between external nodes and nodes within the Combo, all connections will connect to the Combo.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## Custom Combos\n\nWhen built-in Combos cannot meet your needs, G6 provides powerful customization capabilities:\n\n- Extend built-in Combos\n- Create new Combo types\n\nUnlike Combos, custom Combos need to be registered before use. For detailed tutorials, please refer to the [Custom Combo](/en/manual/element/combo/custom-combo) documentation.\n","packages/site/docs/manual/element/combo/overview.zh.md":"---\ntitle: 组合总览\norder: 0\n---\n\n## 什么是组合\n\n组合(Combo) 全称为 Combination，是 G6 中的一种特殊的图元素，它可以包含节点和子组合，类似“群组”或“容器”的概念。它通常用于表示集合关系，例如一个部门包含多个员工，一个城市包含多个区域等。\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=注意}\n不推荐在**树图**中使用 Combo。因为树图的布局与 Combo 的布局机制不兼容，容易导致节点错位或样式混乱。\n:::\n\nG6 的内置 Combo 包括 `circle`（圆形组合）和 `rect` (矩形组合) 两种类型，分别如下图所示：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## 数据结构\n\n定义 Combo 时，需要在图的数据对象中添加 `combos` 字段，每个 Combo 是一个对象，结构如下：\n\n| 属性   | 描述                                                                    | 类型           | 默认值 | 必选 |\n| ------ | ----------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                        | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称，比如 `circle` 或者 `rect` | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取    | object         | -      |      |\n| style  | 组合样式                                                                | object         | -      |      |\n| states | 组合初始状态                                                            | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                              | string \\| null | -      |      |\n\n`combos` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n要将节点归属到某个 Combo，可以在节点数据中添加 `combo` 字段：\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 属于 comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // 定义 comboA\n}\n```\n\n## 配置方法\n\n配置 Combo 的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setCombo()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setCombo()`\n\n可在图实例创建后，使用 `graph.setCombo()` 动态设置 Combo 的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `combo` 配置 Combo 样式映射，这里的配置是全局的配置，将会在所有 Combo 上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 在组合配置中指定组合类型以及组合样式类型\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同 Combo 进行不同的配置，可以将配置写入到 Combo 数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\n// 在数据中指定组合类型以及组合样式类型\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## 示例\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo 交互\n\n只是简单地将 Combo 渲染出来，并没有多大的实用价值，只有支持一系列的交互操作后，才能最大程度地体现 Combo 的价值。\n\n在 G6 中，我们内置了 `drag-element`、`collapse-expand` 三个交互。\n\n#### drag-element\n\n支持拖动节点和 Combo。拖动 Combo 过程中，会动态改变 Combo 中节点和边的位置，在拖拽完成以后，保持 Combo 和节点的相对位置不变。还可以通过设置 `dropEffect: 'link'` 在拖拽时改变 Combo 的从属关系。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\n支持双击 Combo 收起和展开 Combo ，收起 Combo 以后，隐藏 Combo 中的所有节点，外部节点和 Combo 中节点有连线的情况下，所有连接会连接到 Combo 上面。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## 自定义组合\n\n当内置组合无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置组合进行扩展\n- 创建全新的组合类型\n\n与组合不同，自定义组合需要先注册后使用。详细教程请参考 [自定义组合](/manual/element/combo/custom-combo) 文档。\n","packages/site/docs/manual/element/edge/BaseEdge.en.md":"---\ntitle: Edge Common Configuration\norder: 1\n---\n\nThis document introduces the built-in edge common property configurations.\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // Edge type\n    style: {}, // Edge style\n    state: {}, // State styles\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name         | [Type](#type)           | `line`  |          |\n| style     | Edge style configuration, including color, thickness, etc.     | [Style](#style)         | -       |          |\n| state     | Style configuration for different states                       | [State](#state)         | -       |          |\n| palette   | Define edge palette for mapping colors based on different data | [Palette](#palette)     | -       |          |\n| animation | Define edge animation effects                                  | [Animation](#animation) | -       |          |\n\n## Type\n\nSpecify the edge type, built-in edge type name or custom edge name. Default is `line` (straight line edge). **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select edge types based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    // Static configuration\n    type: 'line',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `line`: [Straight line edge](/en/manual/element/edge/line)\n- `polyline`: [Polyline edge](/en/manual/element/edge/polyline)\n- `cubic`: [Cubic Bezier curve edge](/en/manual/element/edge/cubic)\n- `cubic-horizontal`: [Horizontal cubic Bezier curve edge](/en/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`: [Vertical cubic Bezier curve edge](/en/manual/element/edge/cubic-vertical)\n- `quadratic`: [Quadratic Bezier curve edge](/en/manual/element/edge/quadratic)\n\n## Style\n\nDefine edge styles, including color, thickness, etc.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // Static configuration\n      stroke: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineDash: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Edge: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the edge data object (`EdgeData`), containing all data information of the edge.\n\nA complete edge consists of the following parts:\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the main path of the edge, such as straight lines, curves, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `badge`: Badge on the edge\n- `halo`: The halo effect graphic displayed around the main graphic\n- `startArrow`: Arrow at the starting end of the edge\n- `endArrow`: Arrow at the ending end of the edge\n\nThe following style configurations will be explained by atomic graphics in order:\n\n### Main Graphic Styles\n\nThe main graphic is the core part of the edge, defining the basic path and appearance of the edge. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // Blue edge\n      lineWidth: 2, // Edge width\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Line Style\n\nCreate edges with dashed line style:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // Dashed line style\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Shadow Effect\n\nAdd shadow effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                        | Type                  | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------- | -------- |\n| cursor                          | Mouse cursor style when hovering over edge, [options](#cursor)                                                                     | string                | `default` |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. We can increase this area to make \"thin lines\" easier to pick up | number                | 0         |          |\n| lineDash                        | Edge dash line style                                                                                                               | number[]              | -         |          |\n| lineDashOffset                  | Edge dash line offset                                                                                                              | number                | 0         |          |\n| lineWidth                       | Edge width                                                                                                                         | number                | 1         |          |\n| opacity                         | Edge opacity                                                                                                                       | number \\| string      | 1         |          |\n| pointerEvents                   | How edge responds to pointer events, [options](#pointerevents)                                                                     | string                | `auto`    |          |\n| shadowBlur                      | Edge shadow blur                                                                                                                   | number                | -         |          |\n| shadowColor                     | Edge shadow color                                                                                                                  | string                | -         |          |\n| shadowOffsetX                   | Edge shadow offset in x direction                                                                                                  | number \\| string      | -         |          |\n| shadowOffsetY                   | Edge shadow offset in y direction                                                                                                  | number \\| string      | -         |          |\n| shadowType                      | Edge shadow type                                                                                                                   | `inner` \\| `outer`    | `outer`   |          |\n| sourcePort                      | Connection port at the source end of the edge                                                                                      | string                | -         |          |\n| stroke                          | Edge color                                                                                                                         | string                | `#000`    |          |\n| strokeOpacity                   | Edge color opacity                                                                                                                 | number \\| string      | 1         |          |\n| targetPort                      | Connection port at the target end of the edge                                                                                      | string                | -         |          |\n| transform                       | Transform property allows you to rotate, scale, skew, or translate the given edge                                                  | string                | -         |          |\n| transformOrigin                 | The center of rotation and scaling, also known as the transform center                                                             | string                | -         |          |\n| visibility                      | Whether the edge is visible                                                                                                        | `visible` \\| `hidden` | `visible` |          |\n| zIndex                          | Edge rendering layer                                                                                                               | number                | 1         |          |\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, both `stroke` and `visibility` can independently or in combination affect hit testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Never becomes a target for responding to events\n- **`visiblepainted`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n- **`visiblestroke`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`visible`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`painted`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`stroke`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Responds to events as long as entering the graphic stroke area, not affected by `stroke` or `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely non-responsive to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // Edge does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Styles\n\nLabels are used to display text information for edges, supporting various style configurations and layout options. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Edge Label',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'This is a very long edge label that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdd background to labels for better readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Important Connection',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Auto-rotating Label\n\nLabels can automatically rotate to align with edge direction:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Auto Rotate',\n      labelAutoRotate: true, // Auto rotate\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete label style configuration:\n\n| Property                 | Description                                                                                                     | Type                                                                        | Default   | Required |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show edge label                                                                                      | boolean                                                                     | true      |          |\n| labelAutoRotate          | Whether edge label automatically rotates to align with edge direction                                           | boolean                                                                     | true      |          |\n| labelCursor              | Mouse cursor style when hovering over edge label, [options](#cursor)                                            | string                                                                      | `default` |          |\n| labelFill                | Edge label text color                                                                                           | string                                                                      | -         |          |\n| labelFontFamily          | Edge label font family                                                                                          | string                                                                      | -         |          |\n| labelFontSize            | Edge label font size                                                                                            | number                                                                      | 12        |          |\n| labelFontStyle           | Edge label font style                                                                                           | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Edge label font variant                                                                                         | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Edge label font weight                                                                                          | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                    | number                                                                      | 0         |          |\n| labelLetterSpacing       | Edge label letter spacing                                                                                       | number \\| string                                                            | -         |          |\n| labelLineHeight          | Edge label line height                                                                                          | number \\| string                                                            | -         |          |\n| labelMaxLines            | Edge label maximum lines                                                                                        | number                                                                      | 1         |          |\n| labelMaxWidth            | Edge label maximum width, [options](#labelmaxwidth)                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Edge label offset in x direction                                                                                | number                                                                      | 0         |          |\n| labelOffsetY             | Edge label offset in y direction                                                                                | number                                                                      | 0         |          |\n| labelPadding             | Edge label padding                                                                                              | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Edge label position relative to edge, [options](#labelplacement)                                                | string \\| number                                                            | `center`  |          |\n| labelText                | Edge label text content                                                                                         | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Edge label text horizontal alignment                                                                            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Edge label text baseline                                                                                        | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Edge label text decoration line color                                                                           | string                                                                      | -         |          |\n| labelTextDecorationLine  | Edge label text decoration line                                                                                 | string                                                                      | -         |          |\n| labelTextDecorationStyle | Edge label text decoration line style                                                                           | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Edge label text overflow handling                                                                               | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Edge label text path                                                                                            | Path                                                                        | -         |          |\n| labelWordWrap            | Whether to enable automatic line wrapping for edge labels. When enabled, text exceeding labelMaxWidth will wrap | boolean                                                                     | false     |          |\n| labelZIndex              | Edge label rendering layer                                                                                      | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nEdge label position relative to the edge, can be set to:\n\n- `start`: Label positioned at the starting point of the edge\n- `center`: Label positioned at the center of the edge (default)\n- `end`: Label positioned at the ending point of the edge\n- `number`: Value range 0-1, representing the specific position ratio of the label on the edge, 0 for start position, 1 for end position\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text exceeding this width will wrap:\n\n- string: Represents the maximum width defined as a percentage relative to the edge length. For example, `50%` means the label width does not exceed half the edge length\n- number: Represents the maximum width defined in pixels. For example, 100 means the label's maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Styles\n\nLabel background is used to display the background of edge labels:\n\n| Property                      | Description                                                                                                                                                       | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to show edge label background                                                                                                                             | boolean                                  | false     |\n| labelBackgroundCursor         | Edge label background mouse cursor style, [options](#cursor)                                                                                                      | string                                   | `default` |\n| labelBackgroundFill           | Edge label background fill color                                                                                                                                  | string                                   | -         |\n| labelBackgroundFillOpacity    | Edge label background opacity                                                                                                                                     | number                                   | 1         |\n| labelBackgroundHeight         | Edge label background height                                                                                                                                      | string \\| number                         | -         |\n| labelBackgroundLineDash       | Edge label background dash line configuration                                                                                                                     | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Edge label background dash line offset                                                                                                                            | number                                   | -         |\n| labelBackgroundLineWidth      | Edge label background stroke line width                                                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | Edge label background border radius <br> - number: Uniform radius for all corners <br> - number[]: Individual radius for each corner, auto-filled if insufficient | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Edge label background shadow blur                                                                                                                                 | number                                   | -         |\n| labelBackgroundShadowColor    | Edge label background shadow color                                                                                                                                | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Edge label background shadow X offset                                                                                                                             | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Edge label background shadow Y offset                                                                                                                             | number                                   | -         |\n| labelBackgroundStroke         | Edge label background stroke color                                                                                                                                | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Edge label background stroke opacity                                                                                                                              | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Edge label background visibility                                                                                                                                  | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Edge label background rendering layer                                                                                                                             | number                                   | 1         |\n\n### Halo Styles\n\nHalo is an effect displayed around the edge main graphic, usually used for highlighting or indicating special states of the edge.\n\n#### Basic Halo Effect\n\nAdd basic halo effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete halo style configuration:\n\n| Property          | Description                                                                          | Type                   | Default                                   | Required |\n| ----------------- | ------------------------------------------------------------------------------------ | ---------------------- | ----------------------------------------- | -------- |\n| halo              | Whether to show edge halo                                                            | boolean                | false                                     |          |\n| haloCursor        | Edge halo mouse cursor style, [options](#cursor)                                     | string                 | `default`                                 |          |\n| haloDraggable     | Whether edge halo allows dragging                                                    | boolean                | true                                      |          |\n| haloDroppable     | Whether edge halo allows receiving dragged elements                                  | boolean                | true                                      |          |\n| haloFillRule      | Edge halo fill rule                                                                  | `nonzero` \\| `evenodd` | -                                         |          |\n| haloFilter        | Edge halo filter                                                                     | string                 | -                                         |          |\n| haloLineWidth     | Edge halo stroke width                                                               | number                 | 3                                         |          |\n| haloPointerEvents | Whether edge halo responds to pointer events, [options](#pointerevents)              | string                 | `none`                                    |          |\n| haloStroke        | Edge halo stroke color, **this property sets the color of the halo around the edge** | string                 | Consistent with main graphic stroke color |          |\n| haloStrokeOpacity | Edge halo stroke opacity                                                             | number                 | 0.25                                      |          |\n| haloVisibility    | Edge halo visibility                                                                 | `visible` \\| `hidden`  | `visible`                                 |          |\n| haloZIndex        | Edge halo rendering layer                                                            | number                 | -1                                        |          |\n\n### Arrow Styles\n\nEdges support adding arrows at the start and end points to indicate the directionality of the edge.\n\n#### Basic Arrow\n\nAdd basic arrow to the end of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // End arrow\n      endArrowType: 'vee', // Arrow type\n      endArrowSize: 10, // Arrow size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Bidirectional Arrows\n\nAdd arrows to both ends of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // Start arrow\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // End arrow\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Arrow Style\n\nCustomize arrow color and type:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // Diamond arrow\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // Red arrow fill\n      endArrowStroke: '#722ED1', // Arrow stroke color\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Start Arrow Style Configuration\n\n| Property                | Description                                             | Type                                                                                 | Default                            | Required |\n| ----------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| startArrow              | Whether to show edge start arrow                        | boolean                                                                              | false                              |          |\n| startArrowCursor        | Edge start arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| startArrowFill          | Edge start arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| startArrowFillOpacity   | Edge start arrow fill opacity                           | number                                                                               | 1                                  |          |\n| startArrowOffset        | Edge start arrow offset                                 | number                                                                               | 0                                  |          |\n| startArrowSize          | Edge start arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| startArrowStroke        | Edge start arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| startArrowStrokeOpacity | Edge start arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| startArrowType          | Edge start arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n#### End Arrow Style Configuration\n\n| Property              | Description                                           | Type                                                                                 | Default                            | Required |\n| --------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| endArrow              | Whether to show edge end arrow                        | boolean                                                                              | false                              |          |\n| endArrowCursor        | Edge end arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| endArrowFill          | Edge end arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| endArrowFillOpacity   | Edge end arrow fill opacity                           | number                                                                               | 1                                  |          |\n| endArrowOffset        | Edge end arrow offset                                 | number                                                                               | 0                                  |          |\n| endArrowSize          | Edge end arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| endArrowStroke        | Edge end arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| endArrowStrokeOpacity | Edge end arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| endArrowType          | Edge end arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n### Loop Edge Styles\n\nLoop edges are special edges where the start and end nodes are the same node.\n\n#### Basic Loop Edge\n\nCreate a basic loop edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // Loop position\n      loopDist: 30, // Loop size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Loop Edges\n\nCreate multiple loop edges at different positions for the same node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete loop edge style configuration:\n\n| Property      | Description                                                         | Type                                                                                                                                                                   | Default                  | Required |\n| ------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- |\n| loop          | Whether to enable loop edges                                        | boolean                                                                                                                                                                | true                     |          |\n| loopClockwise | Whether to draw the loop clockwise                                  | boolean                                                                                                                                                                | true                     |          |\n| loopDist      | Distance from node edge to loop top, used to specify loop curvature | number                                                                                                                                                                 | Default to max node size |          |\n| loopPlacement | Loop edge position                                                  | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                    |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select an edge or hovering to activate an edge, it's simply marking certain states on that element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of that graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. Additionally, it supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\nFor example, when an edge is in the `focus` state, you can add a halo with a width of 6 and orange color.\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefine edge animation effects. Supports the following two configuration methods:\n\n1. Disable all edge animations\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to the animation effects when edges enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when edge enters the canvas\n- `update`: Animation when edge updates\n- `exit`: Animation when edge leaves the canvas\n- `show`: Animation when edge shows from hidden state\n- `hide`: Animation when edge hides\n- `collapse`: Animation when edge collapses\n- `expand`: Animation when edge expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#动画范式) to use animation syntax to configure edges, such as:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // Only animate stroke property during update\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"path-in\", // Use path animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable specific stage animations:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // Disable edge entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefine the edge palette, which is a predefined edge color pool that is allocated according to rules and maps colors to the `stroke` property.\n\n> For palette definitions, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to using id as grouping field                  | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                     | `group` \\| `value`            | `group` |\n\nFor example, to assign edge colors to a group of data by the `direction` field, making edges of the same category have the same color:\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau is the palette name, colors assigned by ID by default\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/BaseEdge.zh.md":"---\ntitle: 边通用配置项\norder: 1\n---\n\n本文介绍内置边通用属性配置。\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // 边类型\n    style: {}, // 边样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                   | 类型                    | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](#type)           | `line` |      |\n| style     | 边样式配置，包括颜色、粗细等           | [Style](#style)         | -      |      |\n| state     | 不同状态下的样式配置                   | [State](#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](#animation) | -      |      |\n\n## Type\n\n指定边类型，内置边类型名称或自定义边的名称。默认为 `line`（直线边）。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据边数据动态选择边类型：\n\n```js\nconst graph = new Graph({\n  edge: {\n    // 静态配置\n    type: 'line',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `line`：[直线边](/manual/element/edge/line)\n- `polyline`：[折线边](/manual/element/edge/polyline)\n- `cubic`：[三次贝塞尔曲线边](/manual/element/edge/cubic)\n- `cubic-horizontal`：[水平三次贝塞尔曲线边](/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`：[垂直三次贝塞尔曲线边](/manual/element/edge/cubic-vertical)\n- `quadratic`：[二次贝塞尔曲线边](/manual/element/edge/quadratic)\n\n## Style\n\n定义边的样式，包括颜色、粗细等。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据边数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // 静态配置\n      stroke: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineDash: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `边: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\n其中 `datum` 参数为边数据对象 (`EdgeData`)，包含边的所有数据信息。\n\n一个完整的边由以下几部分构成：\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要路径，例如直线、曲线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `badge` ：边上的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `startArrow` ：边起始端的箭头；\n- `endArrow` ：边结束端的箭头。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是边的核心部分，定义了边的基本路径和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置边的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // 蓝色边\n      lineWidth: 2, // 边宽度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线样式\n\n创建带虚线样式的边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // 虚线样式\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 阴影效果\n\n为边添加阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                  | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | --------------------- | --------- | ---- |\n| cursor                          | 边鼠标移入样式，[配置项](#cursor)                                                         | string                | `default` |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                | 0         |      |\n| lineDash                        | 边虚线样式                                                                                | number[]              | -         |      |\n| lineDashOffset                  | 边虚线偏移量                                                                              | number                | 0         |      |\n| lineWidth                       | 边宽度                                                                                    | number                | 1         |      |\n| opacity                         | 边透明度                                                                                  | number \\| string      | 1         |      |\n| pointerEvents                   | 边如何响应指针事件，[配置项](#pointerevents)                                              | string                | `auto`    |      |\n| shadowBlur                      | 边阴影模糊度                                                                              | number                | -         |      |\n| shadowColor                     | 边阴影颜色                                                                                | string                | -         |      |\n| shadowOffsetX                   | 边阴影在 x 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowOffsetY                   | 边阴影在 y 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowType                      | 边阴影类型                                                                                | `inner` \\| `outer`    | `outer`   |      |\n| sourcePort                      | 边起始连接的连接桩                                                                        | string                | -         |      |\n| stroke                          | 边颜色                                                                                    | string                | `#000`    |      |\n| strokeOpacity                   | 边颜色透明度                                                                              | number \\| string      | 1         |      |\n| targetPort                      | 边终点连接的连接桩                                                                        | string                | -         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定边                                          | string                | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                | -         |      |\n| visibility                      | 边是否可见                                                                                | `visible` \\| `hidden` | `visible` |      |\n| zIndex                          | 边渲染层级                                                                                | number                | 1         |      |\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的描边区域就会响应事件，不会受 `stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // 边不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示边的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '边标签',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '这是一个很长的边标签需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '重要连接',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自动旋转标签\n\n标签可以自动旋转以保持与边方向一致：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '自动旋转',\n      labelAutoRotate: true, // 自动旋转\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                             | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 边标签是否显示                                                                   | boolean                                                                     | true      |      |\n| labelAutoRotate          | 边标签是否自动旋转，保持与边的方向一致                                           | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入边标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 边标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 边标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 边标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 边标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 边标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 边标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                           | number                                                                      | 0         |      |\n| labelLetterSpacing       | 边标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 边标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 边标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 边标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 边标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 边标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 边标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 边标签相对于边的位置，[配置项](#labelplacement)                                  | string \\| number                                                            | `center`  |      |\n| labelText                | 边标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 边标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 边标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 边标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 边标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 边标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 边标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 边标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 边标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 边标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n边标签相对于边的位置，可以设置为：\n\n- `start`：标签位于边的起始位置\n- `center`：标签位于边的中心位置（默认）\n- `end`：标签位于边的结束位置\n- `number`：取值范围为 0-1，表示标签在边上的具体位置比例，0 为起始位置，1 为结束位置\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于边长度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过边长度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示边标签的背景：\n\n| 属性                          | 描述                                                                                                         | 类型                                     | 默认值    |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | --------- |\n| labelBackground               | 边标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 边标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 边标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 边标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 边标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 边标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 边标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 边标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 边标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 边标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 边标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 边标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 边标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 边标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 边标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 边标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 边标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕边主图形显示的效果，通常用于高亮显示或表示边的特殊状态。\n\n#### 基础光晕效果\n\n为边添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                 | 类型                   | 默认值                         | 必选 |\n| ----------------- | ---------------------------------------------------- | ---------------------- | ------------------------------ | ---- |\n| halo              | 边光晕是否显示                                       | boolean                | false                          |      |\n| haloCursor        | 边光晕鼠标移入样式，[配置项](#cursor)                | string                 | `default`                      |      |\n| haloDraggable     | 边光晕是否允许拖拽                                   | boolean                | true                           |      |\n| haloDroppable     | 边光晕是否允许接收被拖拽的元素                       | boolean                | true                           |      |\n| haloFillRule      | 边光晕填充规则                                       | `nonzero` \\| `evenodd` | -                              |      |\n| haloFilter        | 边光晕滤镜                                           | string                 | -                              |      |\n| haloLineWidth     | 边光晕描边宽度                                       | number                 | 3                              |      |\n| haloPointerEvents | 边光晕效果是否响应指针事件，[配置项](#pointerevents) | string                 | `none`                         |      |\n| haloStroke        | 边光晕描边色，**此属性用于设置边周围光晕的颜色**     | string                 | 与主图形的描边色 `stroke` 一致 |      |\n| haloStrokeOpacity | 边光晕描边色透明度                                   | number                 | 0.25                           |      |\n| haloVisibility    | 边光晕可见性                                         | `visible` \\| `hidden`  | `visible`                      |      |\n| haloZIndex        | 边光晕渲染层级                                       | number                 | -1                             |      |\n\n### 箭头样式\n\n边支持在起始端和结束端添加箭头，用于表示边的方向性。\n\n#### 基础箭头\n\n为边的结束端添加基本箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'vee', // 箭头类型\n      endArrowSize: 10, // 箭头大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 双向箭头\n\n为边的两端都添加箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // 起始端箭头\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义箭头样式\n\n自定义箭头的颜色和类型：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // 菱形箭头\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // 红色箭头填充\n      endArrowStroke: '#722ED1', // 箭头描边颜色\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 起始箭头样式配置\n\n| 属性                    | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| ----------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| startArrow              | 边起始箭头是否显示                        | boolean                                                                              | false              |      |\n| startArrowCursor        | 边起始箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| startArrowFill          | 边起始箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowFillOpacity   | 边起始箭头填充透明度                      | number                                                                               | 1                  |      |\n| startArrowOffset        | 边起始箭头的偏移量                        | number                                                                               | 0                  |      |\n| startArrowSize          | 边起始箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| startArrowStroke        | 边起始箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowStrokeOpacity | 边起始箭头描边透明度                      | number                                                                               | 1                  |      |\n| startArrowType          | 边起始箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n#### 结束箭头样式配置\n\n| 属性                  | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| --------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| endArrow              | 边结束箭头是否显示                        | boolean                                                                              | false              |      |\n| endArrowCursor        | 边结束箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| endArrowFill          | 边结束箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowFillOpacity   | 边结束箭头填充透明度                      | number                                                                               | 1                  |      |\n| endArrowOffset        | 边结束箭头的偏移量                        | number                                                                               | 0                  |      |\n| endArrowSize          | 边结束箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| endArrowStroke        | 边结束箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowStrokeOpacity | 边结束箭头描边透明度                      | number                                                                               | 1                  |      |\n| endArrowType          | 边结束箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n### 自环边样式\n\n自环边是指起始节点和结束节点为同一个节点的特殊边。\n\n#### 基础自环边\n\n创建基本的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // 自环位置\n      loopDist: 30, // 自环大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个自环边\n\n为同一节点创建多个不同位置的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的自环边样式配置：\n\n| 属性          | 描述                                           | 类型                                                                                                                                                                   | 默认值                 | 必选 |\n| ------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| loop          | 是否启用自环边                                 | boolean                                                                                                                                                                | true                   |      |\n| loopClockwise | 指定是否顺时针绘制环                           | boolean                                                                                                                                                                | true                   |      |\n| loopDist      | 从节点边缘到自环顶部的距离，用于指定自环的曲率 | number                                                                                                                                                                 | 默认为节点尺寸的最大值 |      |\n| loopPlacement | 自环边的位置                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                  |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个边或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\n例如，当边处于 `focus` 状态时，可以为其添加一个宽度为 6 且颜色为橙色的光晕。\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义边的动画效果，支持下列两种配置方式：\n\n1. 关闭边全部动画\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指边在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 边进入画布时的动画\n- `update`: 边更新时的动画\n- `exit`: 边离开画布时的动画\n- `show`: 边从隐藏状态显示时的动画\n- `hide`: 边隐藏时的动画\n- `collapse`: 边收起时的动画\n- `expand`: 边展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置边，如：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // 更新时只对 stroke 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ]\n    }\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"path-in\", // 使用路径动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // 关闭边入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义边的色板，即预定义边颜色池，并根据规则进行分配，将颜色映射到 `stroke` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `direction` 字段分配边颜色，使得同类别的边颜色相同：\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Cubic.en.md":"---\ntitle: Cubic Bezier Curve Edge\norder: 2\n---\n\n## Overview\n\nA cubic Bezier curve is a versatile smooth curve with control points that can be freely distributed, suitable for connecting nodes in any direction.\n\nUse cases:\n\n- Suitable for graphs with any layout, such as network graphs and relationship graphs.\n\n- Use when smooth node connections are needed without specific directional requirements.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type                               | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [[Point](#point), [Point](#point)] | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number &#124; number[]             | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number &#124; number[]             | 20      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Cubic.zh.md":"---\ntitle: 三次贝塞尔曲线边 Cubic\norder: 2\n---\n\n## 概述\n\n三次贝塞尔曲线是一种通用的平滑曲线，其控制点可以自由分布，适合连接任意方向的节点。\n\n使用场景：\n\n- 适用于任意布局的图，如网络图、关系图。\n\n- 当需要平滑连接节点且无特定方向要求时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型                               | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [[Point](#point), [Point](#point)] | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number &#124; number[]             | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number &#124; number[]             | 20     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicHorizontal.en.md":"---\ntitle: CubicHorizontal Bezier Curve Edge\norder: 3\n---\n\n## Overview\n\nThe horizontal cubic Bezier curve is a smooth curve with control points primarily distributed along the horizontal direction, suitable for connecting nodes horizontally.\n\nUse cases:\n\n- Suitable for horizontally laid-out graphs, such as flowcharts and hierarchical diagrams.\n\n- Use when emphasizing horizontal connections is needed.\n\n> Note: When calculating control points, the distance on the x-axis is primarily considered, ignoring changes on the y-axis.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Horizontal Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicHorizontal.zh.md":"---\ntitle: 水平三次贝塞尔曲线边 CubicHorizontal\norder: 3\n---\n\n## 概述\n\n水平三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿水平方向分布，适合在水平方向上连接节点。\n\n使用场景：\n\n- 适用于水平布局的图，如流程图、层次结构图。\n\n- 当需要强调水平方向的连接关系时使用。\n\n> 特别注意，计算控制点时主要考虑 x 轴上的距离，忽略 y 轴的变化\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置水平三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicVertical.en.md":"---\ntitle: CubicVertical Bezier Curve Edge\norder: 4\n---\n\n## Overview\n\nThe vertical cubic Bezier curve is a smooth curve with control points primarily distributed along the vertical direction, suitable for connecting nodes vertically.\n\nUse cases:\n\n- Suitable for vertically laid-out graphs, such as organizational charts and tree diagrams.\n\n- Use when emphasizing vertical connections is needed.\n\n**Note: When calculating control points, the distance on the y-axis is primarily considered, ignoring changes on the x-axis.**\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Vertical Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicVertical.zh.md":"---\ntitle: 垂直三次贝塞尔曲线边 CubicVertical\norder: 4\n---\n\n## 概述\n\n垂直三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿垂直方向分布，适合在垂直方向上连接节点。\n\n使用场景：\n\n- 适用于垂直布局的图，如组织结构图、树状图。\n\n- 当需要强调垂直方向的连接关系时使用。\n\n**特别注意，计算控制点时主要考虑 y 轴上的距离，忽略 x 轴的变化**\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置垂直三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Line.en.md":"---\ntitle: Line Edge\norder: 5\n---\n\n## Overview\n\nA line is the simplest type of edge, directly connecting two nodes without any curvature.\n\nUse cases:\n\n- Suitable for simple graphs, such as topology diagrams and flowcharts.\n\n- Use when quick drawing is needed without complex visual effects.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n## Example\n\n### Built-in Line Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Line.zh.md":"---\ntitle: 直线边 Line\norder: 5\n---\n\n## 概述\n\n直线是最简单的边类型，直接连接两个节点，没有任何弯曲。\n\n使用场景：\n\n- 适用于简单的图，如拓扑图、流程图。\n\n- 当需要快速绘制且无需复杂视觉效果时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n## 示例\n\n### 内置直线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Polyline.en.md":"---\ntitle: Polyline Edge\norder: 6\n---\n\n## Overview\n\nA polyline is an edge composed of multiple straight line segments, suitable for connecting nodes by bypassing obstacles in complex layouts.\n\nUse cases:\n\n- Suitable for graphs with complex layouts, such as circuit diagrams and pipeline diagrams.\n\n- Use when you need to bypass other nodes or obstacles.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                | Type                                                                                    | Default | Required |\n| ------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the turning points of the polyline. | [Point](#point)[]                                                                       | []      |          |\n| radius        | Corner radius of the turning points.                                       | number                                                                                  | 0       |          |\n| router        | Whether to enable routing.                                                 | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false   |          |\n\n### OrthRouter\n\n| Attribute | Description                                                                                              | Type                | Default |\n| --------- | -------------------------------------------------------------------------------------------------------- | ------------------- | ------- |\n| type      | Orthogonal routing, adding extra control points on the path to keep each segment horizontal or vertical. | `'orth'`            | -       |\n| padding   | Minimum distance between the node connection point and the corner.                                       | [Padding](#padding) | `0`     |\n\n### ShortestPathRouter\n\n| Attribute                 | Description                                                                                                                                                                                                                                                                          | Type                                                                   | Default |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------- |\n| type                      | Shortest path routing, an intelligent version of orthogonal routing `'orth'`. This routing consists of horizontal or vertical orthogonal segments. It uses the A\\* algorithm to calculate the shortest path and supports automatic avoidance of other nodes (obstacles) on the path. | `'shortest-path'`                                                      | -       |\n| offset                    | Minimum distance between the node anchor point and the corner.                                                                                                                                                                                                                       | [Padding](#padding)                                                    | 0       |\n| gridSize                  | Grid cell size.                                                                                                                                                                                                                                                                      | number                                                                 | 0       |\n| maxAllowedDirectionChange | Maximum allowed rotation angle (radians).                                                                                                                                                                                                                                            | number                                                                 | 0       |\n| startDirections           | Possible starting directions of the node.                                                                                                                                                                                                                                            | [Direction](#direction)[]                                              | 0       |\n| endDirections             | Possible ending directions of the node.                                                                                                                                                                                                                                              | [Direction](#direction)[]                                              | 0       |\n| directionMap              | Specifies the movable directions.                                                                                                                                                                                                                                                    | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0       |\n| penalties                 | Represents additional costs for certain paths during path searching. The key is the radian value, and the value is the cost.                                                                                                                                                         | { [key: string]: number }                                              | 0       |\n| distFunc                  | Specifies the function to calculate the distance between two points.                                                                                                                                                                                                                 | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0       |\n| maximumLoops              | Maximum number of iterations.                                                                                                                                                                                                                                                        | number                                                                 | 0       |\n| enableObstacleAvoidance   | Whether to enable obstacle avoidance.                                                                                                                                                                                                                                                | boolean                                                                | false   |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## Example\n\n### Built-in Polyline Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Polyline.zh.md":"---\ntitle: 折线边 Polyline\norder: 6\n---\n\n## 概述\n\n折线是由多条直线段组成的边，适合在复杂布局中绕过障碍物连接节点。\n\n使用场景：\n\n- 适用于复杂布局的图，如电路图、管道图。\n\n- 当需要绕过其他节点或障碍物时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                             | 类型                                                                                    | 默认值 | 必选 |\n| ------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义折线的转折点 | [Point](#point)[]                                                                       | []     |      |\n| radius        | 转折点圆角半径                   | number                                                                                  | 0      |      |\n| router        | 是否启用路由                     | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false  |      |\n\n### OrthRouter\n\n| 属性    | 描述                                                                   | 类型                | 默认值 |\n| ------- | ---------------------------------------------------------------------- | ------------------- | ------ |\n| type    | 正交路由，通过在路径上添加额外的控制点，使得边的每一段都保持水平或垂直 | `'orth'`            | -      |\n| padding | 节点连接点与转角的最小距离                                             | [Padding](#padding) | `0`    |\n\n### ShortestPathRouter\n\n| 属性                      | 描述                                                                                                                                              | 类型                                                                   | 默认值 |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------ |\n| type                      | 最短路径路由，是正交路由 `'orth'` 的智能版本。该路由由水平或垂直的正交线段组成。采用 A\\* 算法计算最短路径，并支持自动避开路径上的其他节点（障碍） | `'shortest-path'`                                                      | -      |\n| offset                    | 节点锚点与转角的最小距离                                                                                                                          | [Padding](#padding)                                                    | 0      |\n| gridSize                  | grid 格子大小                                                                                                                                     | number                                                                 | 0      |\n| maxAllowedDirectionChange | 支持的最大旋转角度（弧度）                                                                                                                        | number                                                                 | 0      |\n| startDirections           | 节点的可能起始方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| endDirections             | 节点的可能结束方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| directionMap              | 指定可移动的方向                                                                                                                                  | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0      |\n| penalties                 | 表示在路径搜索过程中某些路径的额外代价。key 为弧度值，value 为代价                                                                                | { [key: string]: number }                                              | 0      |\n| distFunc                  | 指定计算两点之间距离的函数                                                                                                                        | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0      |\n| maximumLoops              | 最大迭代次数                                                                                                                                      | number                                                                 | 0      |\n| enableObstacleAvoidance   | 是否开启避障                                                                                                                                      | boolean                                                                | false  |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## 示例\n\n### 内置折线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Quadratic.en.md":"---\ntitle: Quadratic Bezier Curve Edge\norder: 6\n---\n\n## Overview\n\nA quadratic Bezier curve is a smooth curve whose shape is determined by a start point, an end point, and a control point.\n\nUse cases:\n\n- Suitable for moderately complex graphs, such as relationship graphs and network graphs.\n\n- Use when smooth node connections are needed with limited computational resources.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type            | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [Point](#point) | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number          | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number          | 30      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Quadratic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Quadratic.zh.md":"---\ntitle: 二次贝塞尔曲线边 Quadratic\norder: 6\n---\n\n## 概述\n\n二次贝塞尔曲线是一种平滑的曲线，其形状由起点、终点和一个控制点决定。\n\n使用场景：\n\n- 适用于中等复杂度的图，如关系图、网络图。\n\n- 当需要平滑连接节点且计算资源有限时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型            | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | --------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [Point](#point) | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number          | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number          | 30     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置二次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/custom-edge.en.md":"---\ntitle: Custom Edge\norder: 7\n---\n\nG6 provides multiple [built-in edge](/en/manual/element/edge/base-edge) types, including [line](/en/manual/element/edge/line), [polyline](/en/manual/element/edge/polyline), [quadratic (quadratic Bézier curve edge)](/en/manual/element/edge/quadratic), [cubic (cubic Bézier curve edge)](/en/manual/element/edge/cubic), [cubic-horizontal](/en/manual/element/edge/cubic-horizontal), [cubic-vertical](/en/manual/element/edge/cubic-vertical), and more. These built-in edges can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter requirements that these basic edges cannot satisfy. In such cases, you need to create custom edges. Don't worry, it's simpler than you think!\n\n## Before Starting: Understanding the Basic Components of an Edge\n\nIn G6, a complete edge typically consists of the following parts:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the primary shape of the edge, such as straight lines, polylines, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `arrow`: Arrow, used to indicate the direction of the edge\n- `halo`: Graphic displaying halo effects around the main graphic\n\n## Ways to Create Custom Edges <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are two main ways to create custom edges:\n\n### 1. Inherit from Existing Edge Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach. You can choose to inherit from one of the following types:\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - The most basic edge class, providing core edge functionality\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - Straight line edge\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - Polyline edge\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - Quadratic Bézier curve edge\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - Cubic Bézier curve edge\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - Vertical cubic Bézier curve edge\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - Horizontal cubic Bézier curve edge\n\n**Why choose this approach?**\n\n- 📌 **Less code**: Reuse existing edge properties and methods, only focus on new functionality\n- 📌 **Fast development**: Suitable for most project requirements, quickly achieve business goals\n- 📌 **Easy maintenance**: Clear code structure, clear inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing edge types (recommended), you can jump directly to [Create Your First Custom Edge in Three Steps](#create-your-first-custom-edge-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing edge types don't meet your requirements, you can create edges from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum freedom**: Complete control over every detail of the edge, achieving any complex effects\n- 📌 **Special requirements**: Highly customized scenarios that existing edge types cannot satisfy\n- 📌 **Performance optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom edges built from scratch need to handle all details by themselves, including graphic rendering, event response, state changes, etc., which is more challenging to develop. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) for implementation.\n:::\n\n## Create Your First Custom Edge in Three Steps\n\nLet's start with the most basic `BaseEdge` to implement a custom straight line edge:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Edge Class\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // Define edge style, can add or override default styles\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // Call parent class method to get basic style, then add custom styles\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // Implement abstract method: define edge path\n  // This is an abstract method of BaseEdge, all subclasses must implement it\n  protected getKeyPath(attributes) {\n    // Get source node and target node\n    const { sourceNode, targetNode } = this;\n\n    // Get node position coordinates\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // Return SVG path array, defining a straight line from start to end\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=Key Method Analysis}\n\n- `getKeyStyle`: Defines the basic style of the edge, such as line width, color, etc.\n- `getKeyPath`: An abstract method in `BaseEdge` that **must be implemented**, it defines the path shape of the edge\n  :::\n\n### Step 2: Register Custom Edge\n\nUse the `register` method to register the edge type so that G6 can recognize your custom edge:\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.EDGE` indicates this is an edge type\n- Type name: `my-line-edge` is the name we give to this custom edge, which will be used in configuration later\n- Class definition: `MyLineEdge` is the edge class we just created\n\n### Step 3: Apply Custom Edge\n\nIn the graph configuration, use our custom edge by setting `edge.type`:\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom edge.\n\n## Going Further: Understanding the Principles of Edge Rendering\n\n### Atomic Graphics\n\nG6 nodes are drawn using atomic graphic units provided by the [G graphics system](https://g.antv.antgroup.com/). Here are common graphic elements and their uses:\n\n| Graphic Element | Type       | Description                                                                                                                                                                                                                                                                 |\n| --------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Circle          | `circle`   | Suitable for representing states, avatars, circular buttons, etc. Refer to SVG's [\\<circle\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/circle) element                                                                                            |\n| Ellipse         | `ellipse`  | Similar to circle, but supports scenarios with different horizontal and vertical axes. Refer to SVG's [\\<ellipse\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/ellipse) element                                                                     |\n| Image           | `image`    | Used to display icons, user avatars, LOGOs, etc. Refer to SVG's [\\<image\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image) element                                                                                                                         |\n| Line            | `line`     | Used for decoration, auxiliary connections, etc. Refer to SVG's [\\<line\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) element                                                                                                                           |\n| Path            | `path`     | Supports complex graphics such as arrows, arcs, curves, Bézier paths, etc. The path contains a set of commands and parameters with different semantics, [specific usage](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths)                                   |\n| Polygon         | `polygon`  | Supports custom graphics such as pentagrams, arrows. Refer to SVG's [\\<polygon\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon) element                                                                                                                 |\n| Polyline        | `polyline` | Multi-point polyline, suitable for complex connection structures. Refer to SVG's [\\<polyline\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline) element                                                                                                  |\n| Rectangle       | `rect`     | Most commonly used graphic, suitable as containers, cards, buttons, and other basic structures. Refer to SVG's [\\<rect\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect) element                                                                            |\n| Text            | `text`     | Displays names, descriptions, labels, and other content. Provides simple single-line/multi-line text layout capabilities, single-line supports horizontal alignment, character spacing; multi-line supports explicit line breaks and automatic wrapping, vertical alignment |\n\n> For more atomic graphics and detailed properties, please refer to [Element - Shape (Optional)](/en/manual/element/shape/overview)\n\nAll these graphics can be dynamically created or updated through `upsert()`, automatically managing graphic state and lifecycle.\n\n### Element Base Class\n\nBefore starting to customize elements, you need to understand some important properties and methods in G6 element base classes:\n\n#### Properties\n\n| Property   | Type                          | Description                                           |\n| ---------- | ----------------------------- | ----------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom elements, you will frequently use the `upsert` method. It's short for \"update or insert\", responsible for adding or updating graphics in elements:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                       |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | The key of the graphic, i.e., the corresponding key in `shapeMap`. Built-in keys include `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> The key should not use special symbols, it will be converted to camelCase to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                     |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                     |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                    |\n\nFor example, inserting a purple circle at a fixed position:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics through `container.appendChild()`? Because:\n\n1. **Better performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and rebuilding, greatly improving rendering performance\n2. **Simpler code**: No need to manually check if elements exist\n3. **Easy management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, you can easily get them through `this.getShape(key)`\n\n#### `render(attributes, container)`: Main Entry Point for Rendering Edges\n\nEvery custom edge class must implement the `render(attributes, container)` method, which defines how the edge is \"drawn\". You can use various atomic graphics here to compose the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation, or make sub-graphics interact with each other. In this case, the `getShape` method can help you get any graphic previously created through `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, you must ensure A is created first\n\n### Element Conventions\n\n- **Use Conventional Properties**\n\nCurrently conventional element properties include:\n\n- Get element size through `this.getSize()`\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` (simple mode - doesn't consider node shape, directly returns node center or nearest port center position)\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` (optimized mode - default is true, considers node shape, returns connection points on node boundary)\n\n- **Use Paired `getXxxStyle` and `drawXxxShape` Methods for Graphic Drawing**\n\n`getXxxStyle` is used to get graphic styles, `drawXxxShape` is used to draw graphics. Graphics created this way support automatic animation execution.\n\n> Where `Xxx` is the camelCase form of the key passed when calling the [upsert](#methods) method.\n\n- **Access Graph Context through `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, which you can override in custom edges to execute specific logic at key moments:\n\n| Hook Function | Trigger Time                                            | Typical Usage                                                                    |\n| ------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------- |\n| `onCreate`    | When edge creation is completed with entrance animation | Bind interaction events, initialize edge state, add external listeners           |\n| `onUpdate`    | When edge update is completed with update animation     | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | When edge completes exit animation and is destroyed     | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"rendering logic\"**.\n\nYou can define styles for each state in edge configuration:\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\nThis state will be passed to the `render()` method's `attributes`, and the merged result by the internal system will be automatically applied to the graphics.\n\nYou can also customize rendering logic based on state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## From Simple to Complex\n\n### Custom Path Polyline Edge\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Additional Labels\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/custom-edge.zh.md":"---\ntitle: 自定义边\norder: 7\n---\n\nG6 提供了多种[内置边](/manual/element/edge/base-edge)类型，包含 [line（直线边）](/manual/element/edge/line)、[polyline（折线边）](/manual/element/edge/polyline)、[quadratic（二次贝塞尔曲线边）](/manual/element/edge/quadratic)、[cubic（三次贝塞尔曲线边）](/manual/element/edge/cubic)、[cubic-horizontal（水平三次贝塞尔曲线边）](/manual/element/edge/cubic-horizontal)、[cubic-vertical（垂直三次贝塞尔曲线边）](/manual/element/edge/cubic-vertical) 等。这些内置边能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础边无法满足的需求。这时，你需要创建自定义边。别担心，这比你想象的要简单！\n\n## 开始之前：了解边的基本构成\n\n在 G6 中，一条完整的边通常由以下几个部分组成：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要形状，例如直线、折线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `arrow` ：箭头，用于表示边的方向；\n- `halo` ：主图形周围展示的光晕效果的图形。\n\n## 自定义边的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义边的方式主要有两种途径：\n\n### 1. 继承现有边类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - 最基础的边类，提供边的核心功能\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - 直线边\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - 折线边\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - 二次贝塞尔曲线边\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - 三次贝塞尔曲线边\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - 垂直三次贝塞尔曲线边\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - 水平三次贝塞尔曲线边\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有边的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有边类型（推荐），可以直接跳到 [三步创建你的第一个自定义边](#三步创建你的第一个自定义边) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有边类型都不满足需求，你可以基于 G 的底层图形系统从零创建边。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制边的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有边类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义边需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义边\n\n让我们从最基础的 `BaseEdge` 开始，实现一个自定义直线边：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义边类\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // 定义边的样式，可以添加或覆盖默认样式\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // 调用父类方法获取基础样式，然后添加自定义样式\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // 实现抽象方法：定义边的路径\n  // 这是 BaseEdge 的抽象方法，所有子类必须实现\n  protected getKeyPath(attributes) {\n    // 获取源节点和目标节点\n    const { sourceNode, targetNode } = this;\n\n    // 获取节点的位置坐标\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // 返回SVG路径数组，定义从起点到终点的直线\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=关键方法解析}\n\n- `getKeyStyle`: 定义边的基本样式，如线宽、颜色等\n- `getKeyPath`: 是 `BaseEdge` 中的抽象方法，**必须实现**，它定义了边的路径形状\n  :::\n\n### 第二步：注册自定义边\n\n使用 `register` 方法注册边类型，这样 G6 才能识别你的自定义边：\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.EDGE` 表示这是一个边类型\n- 类型名称：`my-line-edge` 是我们给这个自定义边起的名字，后续会在配置中使用\n- 类定义：`MyLineEdge` 是我们刚刚创建的边类\n\n### 第三步：应用自定义边\n\n在图的配置中，通过设置 `edge.type` 来使用我们的自定义边：\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义边。\n\n## 更进一步：理解边绘制的原理\n\n### 原子图形\n\nG6 的节点是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。以下是常见图形元素及其用途：\n\n| 图形元素 | 类型       | 描述                                                                                                                                                                        |\n| -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 圆形     | `circle`   | 适合表示状态、头像、圆形按钮等。可以参考 SVG 的 [\\<circle\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/circle) 元素                                |\n| 椭圆     | `ellipse`  | 与 circle 类似，但支持横纵轴不同的场景。可以参考 SVG 的 [\\<ellipse\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/ellipse) 元素                      |\n| 图片     | `image`    | 用于展示图标、用户头像、LOGO 等。可以参考 SVG 的 [\\<image\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/image) 元素                                           |\n| 直线     | `line`     | 用于装饰、辅助连接等。可以参考 SVG 的 [\\<line\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/line) 元素                                                        |\n| 路径     | `path`     | 支持复杂图形，如箭头、圆弧、曲线、贝塞尔路径等。路径中包含一组命令与参数，这些命令有不同的语义，[具体用法](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths) |\n| 多边形   | `polygon`  | 支持自定义图形，如五角星、箭头。可以参考 SVG 的 [\\<polygon\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polygon) 元素                                        |\n| 折线     | `polyline` | 多点折线，适合复杂的连线结构。可以参考 SVG 的 [\\<polyline\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polyline) 元素                                        |\n| 矩形     | `rect`     | 最常用图形，适合作为容器、卡片、按钮等基础结构。可以参考 SVG 的 [\\<rect\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/rect) 元素                              |\n| 文本     | `text`     | 显示名称、描述、标签等内容。提供简单的单行/多行文本排版能力，单行支持水平对齐、字符间距；多行支持显式换行符以及自动换行，垂直对齐                                           |\n\n> 更多原子图形和详细的属性请参考 [元素 - 图形（可选）](/manual/element/shape/overview)\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义元素之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义元素时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                   |\n| --------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见[元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                 |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                               |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                         |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染边的主入口\n\n每个自定义边类都必须实现 `render(attributes, container)` 方法，它定义了该边如何被“绘制”出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n目前约定的元素属性包括：\n\n- 通过 `this.getSize()` 获取元素的尺寸\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` 获取边的起点和终点（简单模式 - 不考虑节点形状，直接返回节点中心点或最近连接桩中心˝位置）\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` 获取边的起点和终点（优化模式 - 默认为 true，考虑节点形状，返回节点边界上的连接点）\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义边中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                 | 典型用途                                   |\n| ----------- | ------------------------ | ------------------------------------------ |\n| `onCreate`  | 当边创建后完成入场动画时 | 绑定交互事件、初始化边状态、添加外部监听器 |\n| `onUpdate`  | 当边更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果   |\n| `onDestroy` | 当边完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知     |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **“状态响应”** 与 **“绘制逻辑”** 分离。\n\n你可以在边配置中定义每种状态下的样式：\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## 从简单到复杂\n\n### 自定义路径的折线边\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 额外标签\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/overview.en.md":"---\ntitle: Edge Overview\norder: 0\n---\n\n## What is an Edge\n\nAn edge is one of the basic elements in a graph, used to connect two nodes or combos, representing the relationship between them. In G6, edges are directional, pointing from `source` to `target`, but you can configure them to hide the arrow to represent undirected connections.\n\nYou can create edges between any two nodes, combos, or between a node and a combo, and you can express different types of relationships by creating multiple edges.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 provides the following built-in edges:\n\n- `line` Straight line edge\n- `polyline` Polyline edge\n- `quadratic` Quadratic Bezier curve edge\n- `cubic` Cubic Bezier curve edge\n- `cubicVertical` Vertical cubic Bezier curve edge\n- `cubicHorizontal` Horizontal cubic Bezier curve edge\n\n### Data Structure\n\nWhen defining an edge, you need to add an `edges` field to the graph's data object. Each edge is an object with the following structure:\n\n| Attribute | Description                                                                                                   | Type     | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source    | ID of the starting node of the edge                                                                           | string   | -       | ✓        |\n| target    | ID of the target node of the edge                                                                             | string   | -       | ✓        |\n| id        | Unique identifier of the edge                                                                                 | string   | -       |          |\n| type      | Type of edge, name of built-in edge type or custom edge, such as `line` or `polyline`                         | string   | -       |          |\n| data      | Edge data, used to store custom data of the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style     | Edge style, including visual attributes like line color, width, arrow, etc.                                   | object   | -       |          |\n| states    | Initial states of the edge                                                                                    | string[] | -       |          |\n\nAn example of a data item in the `edges` array:\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Configuration Methods\n\nThere are three ways to configure edges, listed in order of priority from high to low:\n\n- Use `graph.setEdge()` for dynamic configuration\n- Global configuration when instantiating the graph\n- Dynamic attributes in data\n\nThese configuration methods can be used simultaneously. When there are the same configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setEdge()`\n\nYou can dynamically set the style mapping logic of edges using `graph.setEdge()` after the graph instance is created.\n\nThis method needs to be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration When Instantiating the Graph\n\nYou can configure edge style mapping globally when instantiating the graph, and this configuration will take effect on all edges.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different edges, you can write the configuration into the edge data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## Custom Edges\n\nWhen built-in edges cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend built-in edges\n- Create entirely new edge types\n\nUnlike combos, custom edges need to be registered before use. For detailed tutorials, please refer to the [Custom Edge](/manual/element/edge/custom-edge) documentation.\n","packages/site/docs/manual/element/edge/overview.zh.md":"---\ntitle: 边总览\norder: 0\n---\n\n## 什么是边\n\n边（Edge）是图中的基本元素之一，用于连接两个节点或组合，表示它们之间的关系。在 G6 中，边具有方向性，从 `source` 指向 `target`，也可以通过配置隐藏箭头以表示无方向连接。\n\n你可以在任意两个节点、组合，或节点与组合之间创建边，还可以通过创建多条边来表达不同的关系类型。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 提供了以下内置边：\n\n- `line` 直线边\n- `polyline` 折线边\n- `quadratic` 二次贝塞尔曲线边\n- `cubic` 三次贝塞尔曲线边\n- `cubicVertical` 垂直三次贝塞尔曲线边\n- `cubicHorizontal` 水平三次贝塞尔曲线边\n\n### 数据结构\n\n定义边时，需要在图的数据对象中添加 `edges` 字段。每条边是一个对象，结构如下：\n\n| 属性   | 描述                                                                  | 类型     | 默认值 | 必选 |\n| ------ | --------------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                         | string   | -      | ✓    |\n| target | 边目标节点 ID                                                         | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                        | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称，比如 `line` 或者 `polyline` | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取      | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                            | object   | -      |      |\n| states | 边初始状态                                                            | string[] | -      |      |\n\n`edges` 数组中一个数据项的示例：\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 配置方法\n\n配置边的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setEdge()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setEdge()`\n\n可在图实例创建后，使用 `graph.setEdge()` 动态设置边的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `edge` 配置边样式映射，这里的配置是全局的配置，将会在所有边上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同边进行不同的配置，可以将配置写入到边数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## 自定义边\n\n当内置边无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置边进行扩展\n- 创建全新的边类型\n\n与组合不同，自定义边需要先注册后使用。详细教程请参考 [自定义边](/manual/element/edge/custom-edge) 文档。\n","packages/site/docs/manual/element/node/BaseNode.en.md":"---\ntitle: Common Node Configuration\norder: 1\n---\n\nThis document introduces the common configuration properties for built-in nodes.\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {}, // Node style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default  | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name         | [Type](#type)           | `circle` |          |\n| style     | Node style configuration, including color, size, etc.          | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                       | [State](#state)         | -        |          |\n| palette   | Define node palette for mapping colors based on different data | [Palette](#palette)     | -        |          |\n| animation | Define animation effects for nodes                             | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the node type, built-in node type name or custom node name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: The `type` property also supports dynamic configuration, allowing you to dynamically select node types based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Node](/en/manual/element/node/circle)\n- `diamond`: [Diamond Node](/en/manual/element/node/diamond)\n- `donut`: [Donut Node](/en/manual/element/node/donut)\n- `ellipse`: [Ellipse Node](/en/manual/element/node/ellipse)\n- `hexagon`: [Hexagon Node](/en/manual/element/node/hexagon)\n- `html`: [HTML Node](/en/manual/element/node/html)\n- `image`: [Image Node](/en/manual/element/node/image)\n- `rect`: [Rectangle Node](/en/manual/element/node/rect)\n- `star`: [Star Node](/en/manual/element/node/star)\n- `triangle`: [Triangle Node](/en/manual/element/node/triangle)\n\n## Style\n\nDefines the style of nodes, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Node: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the node data object (`NodeData`), containing all data information of the node.\n\nA complete node consists of the following parts:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the node, representing the primary shape of the node, such as rectangle, circle, etc.\n- `label`: Text label, usually used to display the name or description of the node\n- `icon`: Icon graphic, usually used to display node icons, can be images or text icons\n- `badge`: Badge, by default located at the top-right corner of the node\n- `halo`: Graphic showing halo effect around the main graphic\n- `port`: Connection points on the node, used to connect edges\n\nThe following style configurations are explained in order by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the node, defining the basic shape and appearance of the node. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSetting the basic appearance of nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdding transparency and shadow effects to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreating nodes with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete main graphic style configuration is as follows:\n\n| Property                        | Description                                                                                                                                      | Type                          | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current node/combo is collapsed                                                                                                      | boolean                       | false     |          |\n| cursor                          | Node mouse hover style, [options](#cursor)                                                                                                       | string                        | default   |          |\n| fill                            | Node fill color                                                                                                                                  | string                        | `#1783FF` |          |\n| fillOpacity                     | Node fill color transparency                                                                                                                     | number \\| string              | 1         |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick up | number                        | 0         |          |\n| lineCap                         | Node stroke end style                                                                                                                            | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Node stroke dash style                                                                                                                           | number[]                      | -         |          |\n| lineDashOffset                  | Node stroke dash offset                                                                                                                          | number                        | -         |          |\n| lineJoin                        | Node stroke join style                                                                                                                           | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Node stroke width                                                                                                                                | number                        | 1         |          |\n| opacity                         | Node transparency                                                                                                                                | number \\| string              | 1         |          |\n| pointerEvents                   | How the node responds to pointer events, [options](#pointerevents)                                                                               | string                        | `auto`    |          |\n| shadowBlur                      | Node shadow blur                                                                                                                                 | number                        | -         |          |\n| shadowColor                     | Node shadow color                                                                                                                                | string                        | -         |          |\n| shadowOffsetX                   | Node shadow offset in x-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowOffsetY                   | Node shadow offset in y-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowType                      | Node shadow type                                                                                                                                 | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Node size, quick setting for node width and height, [options](#size)                                                                             | number \\| number[]            | 32        |          |\n| stroke                          | Node stroke color                                                                                                                                | string                        | `#000`    |          |\n| strokeOpacity                   | Node stroke color transparency                                                                                                                   | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given node                                                                 | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                                   | string                        | -         |          |\n| visibility                      | Whether the node is visible                                                                                                                      | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Node x coordinate                                                                                                                                | number                        | 0         |          |\n| y                               | Node y coordinate                                                                                                                                | number                        | 0         |          |\n| z                               | Node z coordinate                                                                                                                                | number                        | 0         |          |\n| zIndex                          | Node rendering level                                                                                                                             | number                        | 0         |          |\n\n#### Size\n\nNode size, quick setting for node width and height, supports three configuration methods:\n\n- number: Indicates that the node width and height are the same as the specified value\n- [number, number]: Indicates that the node width and height are represented by array elements indicating the node's width and height respectively\n- [number, number, number]: Indicates that the node width, height, and depth are represented by array elements\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. You can refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be a target for responding to events\n- **`visiblepainted`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n- **`visiblestroke`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n- **`visible`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by the values of `fill` and `stroke`\n- **`painted`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by the value of `visibility`\n- **`fill`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n  - Not affected by the value of `visibility`\n- **`stroke`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n  - Not affected by the value of `visibility`\n- **`all`**: Will respond to events as long as entering the fill and stroke areas of the graphic, not affected by the values of `fill`, `stroke`, and `visibility`\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely unresponsive to events\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // Node does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Style\n\nLabels are used to display text information of nodes, supporting various style configurations and layout methods. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Node Name',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'This is a very long node name that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdding background to labels to improve readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Important Node',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete label style configuration is as follows:\n\n| Property                 | Description                                                                                                                        | Type                                                                        | Default   | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to display node label                                                                                                      | boolean                                                                     | true      |          |\n| labelCursor              | Style displayed when mouse hovers over node label, [options](#cursor)                                                              | string                                                                      | `default` |          |\n| labelFill                | Node label text color                                                                                                              | string                                                                      | -         |          |\n| labelFontFamily          | Node label font family                                                                                                             | string                                                                      | -         |          |\n| labelFontSize            | Node label font size                                                                                                               | number                                                                      | 12        |          |\n| labelFontStyle           | Node label font style                                                                                                              | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Node label font variant                                                                                                            | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Node label font weight                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                                       | number                                                                      | 0         |          |\n| labelLetterSpacing       | Node label letter spacing                                                                                                          | number \\| string                                                            | -         |          |\n| labelLineHeight          | Node label line height                                                                                                             | number \\| string                                                            | -         |          |\n| labelMaxLines            | Maximum number of lines for node label                                                                                             | number                                                                      | 1         |          |\n| labelMaxWidth            | Maximum width of node label, [options](#labelmaxwidth)                                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Node label offset in x-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelOffsetY             | Node label offset in y-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelPadding             | Node label padding                                                                                                                 | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Position of node label relative to node main graphic, [options](#labelplacement)                                                   | string                                                                      | `bottom`  |          |\n| labelText                | Node label text content                                                                                                            | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Node label text horizontal alignment                                                                                               | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Node label text baseline                                                                                                           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Node label text decoration line color                                                                                              | string                                                                      | -         |          |\n| labelTextDecorationLine  | Node label text decoration line                                                                                                    | string                                                                      | -         |          |\n| labelTextDecorationStyle | Node label text decoration line style                                                                                              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Node label text overflow handling                                                                                                  | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Node label text path                                                                                                               | Path                                                                        | -         |          |\n| labelWordWrap            | Whether node label enables automatic line wrapping. After enabling labelWordWrap, parts exceeding labelMaxWidth wrap automatically | boolean                                                                     | false     |          |\n| labelZIndex              | Node label rendering level                                                                                                         | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nAvailable values: `left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text wraps when exceeding this width:\n\n- string: Defines maximum width as a percentage relative to node width. For example, `50%` means label width does not exceed half of the node width\n- number: Defines maximum width in pixels. For example, 100 means the maximum width of the label is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background is used to display the background of node labels:\n\n| Property                      | Description                                                                                                                                                                         | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to display node label background                                                                                                                                            | boolean                                  | false     |\n| labelBackgroundCursor         | Node label background mouse hover style, [options](#cursor)                                                                                                                         | string                                   | `default` |\n| labelBackgroundFill           | Node label background fill color                                                                                                                                                    | string                                   | -         |\n| labelBackgroundFillOpacity    | Node label background transparency                                                                                                                                                  | number                                   | 1         |\n| labelBackgroundHeight         | Node label background height                                                                                                                                                        | string \\| number                         | -         |\n| labelBackgroundLineDash       | Node label background dash configuration                                                                                                                                            | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Node label background dash offset                                                                                                                                                   | number                                   | -         |\n| labelBackgroundLineWidth      | Node label background stroke line width                                                                                                                                             | number                                   | -         |\n| labelBackgroundRadius         | Node label background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Node label background shadow blur degree                                                                                                                                            | number                                   | -         |\n| labelBackgroundShadowColor    | Node label background shadow color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Node label background shadow X direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Node label background shadow Y direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundStroke         | Node label background stroke color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Node label background stroke transparency                                                                                                                                           | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Whether node label background is visible                                                                                                                                            | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Node label background rendering level                                                                                                                                               | number                                   | 1         |\n\n### Halo Style\n\nHalo is an effect displayed around the node's main graphic, usually used for highlighting or indicating special states of nodes.\n\n#### Basic Halo Effect\n\nAdding basic halo effect to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete halo style configuration is as follows:\n\n| Property          | Description                                                                                                                   | Type                   | Default                                 | Required |\n| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------------------------------------- | -------- |\n| halo              | Whether to display node halo                                                                                                  | boolean                | false                                   |          |\n| haloCursor        | Node halo mouse hover style, [options](#cursor)                                                                               | string                 | `default`                               |          |\n| haloDraggable     | Whether node halo allows dragging                                                                                             | boolean                | true                                    |          |\n| haloDroppable     | Whether node halo allows receiving dragged elements                                                                           | boolean                | true                                    |          |\n| haloFillRule      | Node halo fill rule                                                                                                           | `nonzero` \\| `evenodd` | -                                       |          |\n| haloFilter        | Node halo filter                                                                                                              | string                 | -                                       |          |\n| haloLineWidth     | Node halo stroke width                                                                                                        | number                 | 3                                       |          |\n| haloPointerEvents | Whether node halo effect responds to pointer events, [options](#pointerevents)                                                | string                 | `none`                                  |          |\n| haloStroke        | Node halo stroke color, **this property is used to set the color of the halo around the node, helping to highlight the node** | string                 | Consistent with main graphic fill color |          |\n| haloStrokeOpacity | Node halo stroke color transparency                                                                                           | number                 | 0.25                                    |          |\n| haloVisibility    | Node halo visibility                                                                                                          | `visible` \\| `hidden`  | `visible`                               |          |\n| haloZIndex        | Node halo rendering level                                                                                                     | number                 | -1                                      |          |\n\n### Icon Style\n\nNode icons support three common usage methods: text icons, image icons, and IconFont icons. The configurations for these three methods are shown below:\n\n#### 1. Text Icons\n\nUsing text directly as icons, suitable for simple identifiers:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // Icon text content\n      iconFill: '#C41D7F', // Deep pink icon\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. Image Icons\n\nUsing images as icons, supporting various image formats:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont Icons\n\nUsing IconFont font icons, you need to import the corresponding font files first:\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // Light blue background\n      stroke: '#1890FF', // Blue border\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete icon style configuration is as follows:\n\n| Property                | Description                                          | Type                                                                        | Default                     |\n| ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to display node icon                         | boolean                                                                     | true                        |\n| iconFill                | Node icon text color                                 | string                                                                      | -                           |\n| iconFontFamily          | Node icon font family                                | string                                                                      | -                           |\n| iconFontSize            | Node icon font size                                  | number                                                                      | 16                          |\n| iconFontStyle           | Node icon font style                                 | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Node icon font variant                               | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Node icon font weight                                | number \\| string                                                            | `normal`                    |\n| iconHeight              | Node icon height                                     | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Node icon text letter spacing                        | number \\| string                                                            | -                           |\n| iconLineHeight          | Node icon text line height                           | number \\| string                                                            | -                           |\n| iconMaxLines            | Maximum lines for node icon text                     | number                                                                      | 1                           |\n| iconRadius              | Node icon border radius                              | number                                                                      | 0                           |\n| iconSrc                 | Node image source. Has higher priority than iconText | string                                                                      | -                           |\n| iconText                | Node icon text                                       | string                                                                      | -                           |\n| iconTextAlign           | Node icon text horizontal alignment                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`                      |\n| iconTextBaseline        | Node icon text baseline                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`                |\n| iconTextDecorationColor | Node icon text decoration line color                 | string                                                                      | -                           |\n| iconTextDecorationLine  | Node icon text decoration line                       | string                                                                      | -                           |\n| iconTextDecorationStyle | Node icon text decoration line style                 | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Node icon text overflow handling                     | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconWidth               | Node icon width                                      | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether node icon text automatically wraps           | boolean                                                                     | -                           |\n\n### Badge Style\n\nBadges are small markers displayed on nodes, usually used to show status, quantity, or other auxiliary information. Supports displaying multiple badges simultaneously with customizable positions.\n\n#### Single Badge\n\nAdding a simple badge to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Default display at the top\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdding multiple badges at different positions to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // Whether to display badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background color palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nCompletely customizing badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete badge style configuration is as follows:\n\n| Property     | Description                      | Type                                  | Default                           |\n| ------------ | -------------------------------- | ------------------------------------- | --------------------------------- |\n| badge        | Whether the node displays badges | boolean                               | true                              |\n| badgePalette | Badge background color palette   | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Node badge settings              | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                                         | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether node badge displays background                                                                                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Node badge background mouse hover style, [options](#cursor)                                                                                                                                                                                                                                                         | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Node badge background fill color. If not specified, badgePalette is considered for allocation in order                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Node badge background fill transparency                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Node badge background filter                                                                                                                                                                                                                                                                                        | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Node badge background height                                                                                                                                                                                                                                                                                        | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Node badge background dash configuration                                                                                                                                                                                                                                                                            | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Node badge background dash offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Node badge background stroke line width                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Node badge background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, separated by spaces | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Node badge background shadow blur degree                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Node badge background shadow color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Node badge background shadow X direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Node badge background shadow Y direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Node badge background stroke color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Node badge background stroke transparency                                                                                                                                                                                                                                                                           | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether node badge background is visible                                                                                                                                                                                                                                                                            | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | Node badge background rendering level                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| fill                     | Node badge text color                                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| fontFamily               | Node badge font family                                                                                                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| fontSize                 | Node badge font size                                                                                                                                                                                                                                                                                                | number                                                                                                                                                                 | 8            |\n| fontStyle                | Node badge font style                                                                                                                                                                                                                                                                                               | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Node badge font variant                                                                                                                                                                                                                                                                                             | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Node badge font weight                                                                                                                                                                                                                                                                                              | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Node badge line height                                                                                                                                                                                                                                                                                              | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Node badge line width                                                                                                                                                                                                                                                                                               | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Maximum lines for node badge text                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 1            |\n| offsetX                  | Node badge offset in x-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| offsetY                  | Node badge offset in y-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| padding                  | Node badge padding                                                                                                                                                                                                                                                                                                  | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Position of node badge relative to node main graphic. If not specified, defaults to clockwise arrangement starting from top-right corner                                                                                                                                                                            | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Node badge text content                                                                                                                                                                                                                                                                                             | string                                                                                                                                                                 | -            |\n| textAlign                | Node badge text horizontal alignment                                                                                                                                                                                                                                                                                | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Node badge text baseline                                                                                                                                                                                                                                                                                            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Node badge text decoration line color                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Node badge text decoration line                                                                                                                                                                                                                                                                                     | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Node badge text decoration line style                                                                                                                                                                                                                                                                               | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Node badge text overflow handling                                                                                                                                                                                                                                                                                   | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether node badge is visible                                                                                                                                                                                                                                                                                       | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether node badge text automatically wraps                                                                                                                                                                                                                                                                         | boolean                                                                                                                                                                | -            |\n| zIndex                   | Node badge rendering level                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                 | 3            |\n\n### Port Style\n\nPorts are connection points on nodes, used to connect edges. Supports adding multiple ports at different positions on nodes with customizable styles.\n\n#### Basic Ports\n\nAdding four basic directional ports to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Position Ports\n\nUsing percentages or absolute coordinates to precisely position ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // Relative position: 20% from top-left\n        { key: 'custom2', placement: [0.8, 0] }, // Relative position: 80% from top-right\n        { key: 'custom3', placement: [1, 0.5] }, // Relative position: right center\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Differentiated Port Styles\n\nSetting different styles for different ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // Green input port\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // Red output port\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // Unified stroke color\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete port style configuration is as follows:\n\n| Property | Description                                                  | Type                                | Default | Required |\n| -------- | ------------------------------------------------------------ | ----------------------------------- | ------- | -------- |\n| port     | Whether the node displays ports                              | boolean                             | true    |          |\n| ports    | Node port configuration, supports configuring multiple ports | [PortStyleProps](#portstyleprops)[] | -       |          |\n\n#### PortStyleProps\n\n| Property          | Description                                                                                                                                                                                                                                                  | Type                                                                                                                                                                                                   | Default   | Required |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- |\n| key               | Key value of node port, defaults to the index of the node port                                                                                                                                                                                               | string                                                                                                                                                                                                 | -         |          |\n| placement         | Position of node port relative to node main graphic                                                                                                                                                                                                          | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓        |\n| r                 | Node port radius <br> - If set to undefined, the port is treated as a point, not displayed on canvas but exists, edges will preferentially connect to the nearest port <br> - If set to a number, the port is treated as a circle with radius specified here | number                                                                                                                                                                                                 | -         |          |\n| linkToCenter      | Whether edges connect to the center of the node port <br> - If true, edges connect to the center of the node port <br> - If false, edges connect to the edge of the node port                                                                                | boolean                                                                                                                                                                                                | false     |          |\n| cursor            | Node port mouse hover style, [options](#cursor)                                                                                                                                                                                                              | string                                                                                                                                                                                                 | `default` |          |\n| fill              | Node port fill color                                                                                                                                                                                                                                         | string                                                                                                                                                                                                 | -         |          |\n| fillOpacity       | Node port fill transparency                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | 1         |          |\n| isBillboard       | Whether node port has Billboard effect                                                                                                                                                                                                                       | boolean                                                                                                                                                                                                | -         |          |\n| isSizeAttenuation | Whether node port enables size attenuation                                                                                                                                                                                                                   | boolean                                                                                                                                                                                                | -         |          |\n| lineDash          | Node port stroke dash configuration                                                                                                                                                                                                                          | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |          |\n| lineDashOffset    | Node port stroke dash offset                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| lineWidth         | Node port stroke line width                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | -         |          |\n| shadowBlur        | Node port shadow blur degree                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| shadowColor       | Node port shadow color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| shadowOffsetX     | Node port shadow X direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| shadowOffsetY     | Node port shadow Y direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| stroke            | Node port stroke color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| strokeOpacity     | Node port stroke transparency                                                                                                                                                                                                                                | number \\| string                                                                                                                                                                                       | 1         |          |\n| visibility        | Whether node port is visible                                                                                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |          |\n| zIndex            | Node port rendering level                                                                                                                                                                                                                                    | number                                                                                                                                                                                                 | 2         |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select a node or hovering to activate an edge, only certain state identifications are made on the element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of the graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\nFor example, when a node is in the `focus` state, you can add a stroke with width 3 and orange color.\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefines animation effects for nodes, supporting the following two configuration methods:\n\n1. Disable all node animations\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when nodes enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when nodes enter the canvas\n- `update`: Animation when nodes are updated\n- `exit`: Animation when nodes leave the canvas\n- `show`: Animation when nodes are shown from hidden state\n- `hide`: Animation when nodes are hidden\n- `collapse`: Animation when nodes are collapsed\n- `expand`: Animation when nodes are expanded\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure nodes, such as:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // Only animate x and y properties during updates\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable animations for specific stages:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // Disable node entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefines the color palette for nodes, i.e., predefined node color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For the definition of palettes, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to id as the grouping field                    | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify the current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                 | `group` \\| `value`            | `group` |\n\nFor example, assigning node colors to a group of data by `category` field, so that nodes of the same category have the same color:\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau is the palette name, defaults to assigning colors based on ID\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/BaseNode.zh.md":"---\ntitle: 节点通用配置项\norder: 1\n---\n\n本文介绍内置节点通用属性配置。\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {}, // 节点样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](#type)           | `circle` |      |\n| style     | 节点样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定节点类型，内置节点类型名称或自定义节点的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据节点数据动态选择节点类型：\n\n```js\nconst graph = new Graph({\n  node: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形节点](/manual/element/node/circle)\n- `diamond`：[菱形节点](/manual/element/node/diamond)\n- `donut`：[甜甜圈节点](/manual/element/node/donut)\n- `ellipse`：[椭圆节点](/manual/element/node/ellipse)\n- `hexagon`：[六边形节点](/manual/element/node/hexagon)\n- `html`：[HTML 节点](/manual/element/node/html)\n- `image`：[图片节点](/manual/element/node/image)\n- `rect`：[矩形节点](/manual/element/node/rect)\n- `star`：[星形节点](/manual/element/node/star)\n- `triangle`：[三角形节点](/manual/element/node/triangle)\n\n## Style\n\n定义节点的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据节点数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `节点: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为节点数据对象 (`NodeData`)，包含节点的所有数据信息。\n\n一个完整的节点由以下几部分构成：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：节点的主图形，表示节点的主要形状，例如矩形、圆形等；\n- `label` ：文本标签，通常用于展示节点的名称或描述；\n- `icon` ：图标图形，通常用于展示节点的图标，可以是图片或者文本图标；\n- `badge` ：默认位于节点右上角的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `port` ：节点上的连接点，用于连接边。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是节点的核心部分，定义了节点的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置节点的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为节点添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的节点：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前节点/组合是否折叠                                                                     | boolean                       | false     |      |\n| cursor                          | 节点鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 节点填充色                                                                                | string                        | `#1783FF` |      |\n| fillOpacity                     | 节点填充色透明度                                                                          | number \\| string              | 1         |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 节点描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 节点描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 节点描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 节点描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 节点描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 节点透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 节点如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 节点阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 节点阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 节点阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 节点阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 节点阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 节点大小，快捷设置节点宽高，[配置项](#size)                                               | number \\| number[]            | 32        |      |\n| stroke                          | 节点描边色                                                                                | string                        | `#000`    |      |\n| strokeOpacity                   | 节点描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定节点                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 节点是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 节点 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 节点 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 节点 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 节点渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n节点大小，快捷设置节点宽高，支持三种配置方式：\n\n- number：表示节点宽高相同为指定值\n- [number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度\n- [number, number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // 节点不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示节点的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '节点名称',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '这是一个很长的节点名称需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '重要节点',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                               | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示节点标签                                                                   | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入节点标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 节点标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 节点标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 节点标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 节点标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 节点标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 节点标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                             | number                                                                      | 0         |      |\n| labelLetterSpacing       | 节点标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 节点标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 节点标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 节点标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 节点标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 节点标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 节点标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 节点标签相对于节点主图形的位置，[配置项](#labelplacement)                          | string                                                                      | `bottom`  |      |\n| labelText                | 节点标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 节点标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 节点标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 节点标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 节点标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 节点标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 节点标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 节点标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 节点标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 节点标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n可选值有：`left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于节点宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过节点宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示节点标签的背景：\n\n| 属性                          | 描述                                                                                                           | 类型                                     | 默认值    |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | 节点标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 节点标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 节点标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 节点标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 节点标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 节点标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 节点标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 节点标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 节点标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 节点标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 节点标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 节点标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 节点标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 节点标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 节点标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 节点标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 节点标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕节点主图形显示的效果，通常用于高亮显示或表示节点的特殊状态。\n\n#### 基础光晕效果\n\n为节点添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                                   | 类型                   | 默认值                       | 必选 |\n| ----------------- | ---------------------------------------------------------------------- | ---------------------- | ---------------------------- | ---- |\n| halo              | 节点光晕是否显示                                                       | boolean                | false                        |      |\n| haloCursor        | 节点光晕鼠标移入样式，[配置项](#cursor)                                | strig                  | `default`                    |      |\n| haloDraggable     | 节点光晕是否允许拖拽                                                   | boolean                | true                         |      |\n| haloDroppable     | 节点光晕是否允许接收被拖拽的元素                                       | boolean                | true                         |      |\n| haloFillRule      | 节点光晕填充规则                                                       | `nonzero` \\| `evenodd` | -                            |      |\n| haloFilter        | 节点光晕滤镜                                                           | string                 | -                            |      |\n| haloLineWidth     | 节点光晕描边宽度                                                       | number                 | 3                            |      |\n| haloPointerEvents | 节点光晕效果是否响应指针事件，[配置项](#pointerevents)                 | string                 | `none`                       |      |\n| haloStroke        | 节点光晕描边色，**此属性用于设置节点周围光晕的颜色，帮助突出显示节点** | string                 | 与主图形的填充色 `fill` 一致 |      |\n| haloStrokeOpacity | 节点光晕描边色透明度                                                   | number                 | 0.25                         |      |\n| haloVisibility    | 节点光晕可见性                                                         | `visible` \\| `hidden`  | `visible`                    |      |\n| haloZIndex        | 节点光晕渲染层级                                                       | number                 | -1                           |      |\n\n### 图标样式\n\n节点图标支持三种常见的使用方式：文字图标、图片图标和 IconFont 图标。下面分别展示这三种方式的配置：\n\n#### 1. 文字图标\n\n直接使用文字作为图标，适合简单的标识：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // 图标文字内容\n      iconFill: '#C41D7F', // 深粉色图标\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. 图片图标\n\n使用图片作为图标，支持各种图片格式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont 图标\n\n使用 IconFont 字体图标，需要先引入相应的字体文件：\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // 淡蓝色背景\n      stroke: '#1890FF', // 蓝色边框\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                | 类型                                                                        | 默认值           |\n| ----------------------- | ----------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示节点图标                    | boolean                                                                     | true             |\n| iconFill                | 节点图标文字颜色                    | string                                                                      | -                |\n| iconFontFamily          | 节点图标字体族                      | string                                                                      | -                |\n| iconFontSize            | 节点图标字体大小                    | number                                                                      | 16               |\n| iconFontStyle           | 节点图标字体样式                    | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 节点图标字体变种                    | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 节点图标字体粗细                    | number \\| string                                                            | `normal`         |\n| iconHeight              | 节点图标高度                        | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 节点图标文本字间距                  | number \\| string                                                            | -                |\n| iconLineHeight          | 节点图标文本行高                    | number \\| string                                                            | -                |\n| iconMaxLines            | 节点图标文本最大行数                | number                                                                      | 1                |\n| iconRadius              | 节点图标圆角半径                    | number                                                                      | 0                |\n| iconSrc                 | 节点图片来源。其优先级高于 iconText | string \\| ((datum) => string)                                                | -                |\n| iconText                | 节点图标文字                        | string \\| ((datum) => string)                                               | -                |\n| iconTextAlign           | 节点图标文本水平对齐方式            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`           |\n| iconTextBaseline        | 节点图标文本基线                    | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`     |\n| iconTextDecorationColor | 节点图标文本装饰线颜色              | string                                                                      | -                |\n| iconTextDecorationLine  | 节点图标文本装饰线                  | string                                                                      | -                |\n| iconTextDecorationStyle | 节点图标文本装饰线样式              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 节点图标文本溢出处理方式            | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconWidth               | 节点图标宽度                        | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 节点图标文本是否自动换行            | boolean                                                                     | -                |\n\n### 徽标样式\n\n徽标是节点上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为节点添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为节点添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 节点是否显示徽标   | boolean                               | true                              |\n| badgePalette | 节点徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 节点徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 节点徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 节点徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 节点徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 节点徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 节点徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 节点徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 节点徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 节点徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 节点徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 节点徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 节点徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 节点徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 节点徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 节点徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 节点徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 节点徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 节点徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | 节点徽标背景渲染层级                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| fill                     | 节点徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 节点徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 节点徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 节点徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 节点徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 节点徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 节点徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 节点徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 节点徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 节点徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 节点徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 节点徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 节点徽标相对于节点主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 节点徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 节点徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 节点徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 节点徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 节点徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 节点徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 节点徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 节点徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 节点徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 节点徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 连接桩样式\n\n连接桩是节点上的连接点，用于连接边。支持在节点的不同位置添加多个连接桩，并可自定义样式。\n\n#### 基础连接桩\n\n为节点添加四个基本方向的连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义位置连接桩\n\n使用百分比或绝对坐标精确定位连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // 相对位置：左上角20%处\n        { key: 'custom2', placement: [0.8, 0] }, // 相对位置：右上角80%处\n        { key: 'custom3', placement: [1, 0.5] }, // 相对位置：右边中央\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 差异化连接桩样式\n\n为不同的连接桩设置不同的样式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // 绿色输入桩\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // 红色输出桩\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // 统一的描边颜色\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的连接桩样式配置：\n\n| 属性  | 描述                                 | 类型                                | 默认值 | 必选 |\n| ----- | ------------------------------------ | ----------------------------------- | ------ | ---- |\n| port  | 节点是否显示连接桩                   | boolean                             | true   |      |\n| ports | 节点连接桩配置项，支持配置多个连接桩 | [PortStyleProps](#portstyleprops)[] |        |      |\n\n#### PortStyleProps\n\n| 属性              | 描述                                                                                                                                                                               | 类型                                                                                                                                                                                                   | 默认值    | 必选 |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ---- |\n| key               | 节点连接桩的键值，默认为节点连接桩的索引                                                                                                                                           | string                                                                                                                                                                                                 | -         |      |\n| placement         | 节点连接桩相对于节点主图形的位置                                                                                                                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓    |\n| r                 | 节点连接桩半径 <br> - 如果设置为 undefined，则连接桩被视为一个点，不在画布上显示但存在，边会优先连接到最近的连接桩 <br> - 如果设置为数字，则连接桩被视为一个圆，圆的半径由此处指定 | number                                                                                                                                                                                                 | -         |      |\n| linkToCenter      | 边是否连接到节点连接桩的中心 <br> - 若为 true，则边连接到节点连接桩的中心 <br> - 若为 false，则边连接到节点连接桩的边缘                                                            | boolean                                                                                                                                                                                                | false     |      |\n| cursor            | 节点连接桩鼠标移入样式，[配置项](#cursor)                                                                                                                                          | string                                                                                                                                                                                                 | `default` |      |\n| fill              | 节点连接桩填充颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| fillOpacity       | 节点连接桩填充透明度                                                                                                                                                               | number                                                                                                                                                                                                 | 1         |      |\n| isBillboard       | 节点连接桩是否为Billboard 效果                                                                                                                                                     | boolean                                                                                                                                                                                                | -         |      |\n| isSizeAttenuation | 节点连接桩是否启用大小衰减                                                                                                                                                         | boolean                                                                                                                                                                                                | -         |      |\n| lineDash          | 节点连接桩描边虚线配置                                                                                                                                                             | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |      |\n| lineDashOffset    | 节点连接桩描边虚线偏移量                                                                                                                                                           | number                                                                                                                                                                                                 | -         |      |\n| lineWidth         | 节点连接桩描边线宽                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |      |\n| shadowBlur        | 节点连接桩阴影模糊程度                                                                                                                                                             | number                                                                                                                                                                                                 | -         |      |\n| shadowColor       | 节点连接桩阴影颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| shadowOffsetX     | 节点连接桩阴影 X 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| shadowOffsetY     | 节点连接桩阴影 Y 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| stroke            | 节点连接桩描边颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| strokeOpacity     | 节点连接桩描边透明度                                                                                                                                                               | number \\| string                                                                                                                                                                                       | 1         |      |\n| visibility        | 节点连接桩是否可见                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |      |\n| zIndex            | 节点连接桩渲染层级                                                                                                                                                                 | number                                                                                                                                                                                                 | 2         |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个节点或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\n例如，当节点处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义节点的动画效果，支持下列两种配置方式：\n\n1. 关闭节点全部动画\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指节点在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 节点进入画布时的动画\n- `update`: 节点更新时的动画\n- `exit`: 节点离开画布时的动画\n- `show`: 节点从隐藏状态显示时的动画\n- `hide`: 节点隐藏时的动画\n- `collapse`: 节点收起时的动画\n- `expand`: 节点展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置节点，如：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // 关闭节点入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义节点的色板，即预定义节点颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `category` 字段分配节点颜色，使得同类别的节点颜色相同：\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Circle.en.md":"---\ntitle: Circle Node\norder: 2\n---\n\n## Overview\n\nA circle is a symmetrical geometric shape with a uniform radius.\n\nApplicable scenarios:\n\n- Used to represent the size or weight of a node (controlled by radius).\n- Suitable for representing non-directional relationships, such as user nodes in social networks.\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node))\n\n## Example\n\n### Built-in Circle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Circle.zh.md":"---\ntitle: 圆形节点 Circle\norder: 2\n---\n\n## 概述\n\n圆形是一个对称的几何形状，具有均匀的半径。\n\n适用场景：\n\n- 用于表示节点的大小或权重（通过半径控制）。\n- 适合表示无方向性的关系，如社交网络中的用户节点。\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见[BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Diamond.en.md":"---\ntitle: Diamond Node\norder: 3\n---\n\n## Overview\n\nA diamond is a geometric shape with four equal sides and diagonal symmetry.\n\nApplicable scenarios:\n\n- Used to represent decision nodes, conditional judgments, or critical paths.\n\n- Suitable for representing decision nodes or key steps in flowcharts.\n\n- Commonly used in flowcharts, decision trees, network diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Diamond Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Diamond.zh.md":"---\ntitle: 菱形节点 Diamond\norder: 3\n---\n\n## 概述\n\n菱形是一个四边相等的几何形状，具有对角线对称性。\n\n适用场景：\n\n- 用于表示决策节点、条件判断或关键路径。\n\n- 适合表示流程图中的判断节点或关键步骤。\n\n- 常用于流程图、决策树、网络图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置菱形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Donut.en.md":"---\ntitle: Donut Node\norder: 4\n---\n\n## Overview\n\nThe donut node is a ring-shaped geometric figure composed of two concentric circles.\n\nApplicable scenarios:\n\n- Used to represent proportional data, such as completion progress and ratio analysis.\n\n- Suitable for representing multi-layered data, such as nested ring charts.\n\n- Commonly used in data visualization, dashboards, progress charts, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute           | Description                         | Type                                    | Default   | Required |\n| ------------------- | ----------------------------------- | --------------------------------------- | --------- | -------- |\n| donutFill           | Fill color                          | string                                  | `#1783FF` |          |\n| donutFillOpacity    | Fill color opacity                  | number \\| string                        | 1         |          |\n| donutLineCap        | Stroke end style                    | `round` \\| `square` \\| `butt`           | `butt`    |          |\n| donutLineDash       | Stroke dash style                   | number[]                                | -         |          |\n| donutLineDashOffset | Stroke dash offset                  | number                                  | -         |          |\n| donutLineJoin       | Stroke join style                   | `round` \\| `bevel` \\| `miter`           | `miter`   |          |\n| donutLineWidth      | Stroke width                        | number                                  | 1         |          |\n| donutOpacity        | Opacity                             | number \\| string                        | 1         |          |\n| donutPalette        | Color or palette name               | string \\| string[]                      | `tableau` |          |\n| donuts              | Donut data                          | number[] \\| [DonutRound](#donutround)[] | -         |          |\n| donutShadowBlur     | Shadow blur                         | number                                  | -         |          |\n| donutShadowColor    | Shadow color                        | string                                  | -         |          |\n| donutShadowOffsetX  | Shadow offset in x-axis direction   | number \\| string                        | -         |          |\n| donutShadowOffsetY  | Shadow offset in y-axis direction   | number \\| string                        | -         |          |\n| donutShadowType     | Shadow type                         | `inner` \\| `outer`                      | `outer`   |          |\n| donutStroke         | Stroke color                        | string                                  | `#000`    |          |\n| donutStrokeOpacity  | Stroke color opacity                | number \\| string                        | 1         |          |\n| donutVisibility     | Visibility of the shape             | `visible` \\| `hidden`                   | `visible` |          |\n| innerR              | Inner ring radius, percentage or px | string \\| number                        | 50%       |          |\n\n### DonutRound\n\n| Attribute      | Description                       | Type                          | Default   | Required |\n| -------------- | --------------------------------- | ----------------------------- | --------- | -------- |\n| color          | Color                             | string                        | -         |          |\n| fill           | Fill color                        | string                        | `#1783FF` |          |\n| fillOpacity    | Fill color opacity                | number \\| string              | 1         |          |\n| lineCap        | Stroke end style                  | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash       | Stroke dash style                 | number[]                      | -         |          |\n| lineDashOffset | Stroke dash offset                | number                        | -         |          |\n| lineJoin       | Stroke join style                 | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth      | Stroke width                      | number                        | 1         |          |\n| opacity        | Opacity                           | number \\| string              | 1         |          |\n| shadowBlur     | Shadow blur                       | number                        | -         |          |\n| shadowColor    | Shadow color                      | string                        | -         |          |\n| shadowOffsetX  | Shadow offset in x-axis direction | number \\| string              | -         |          |\n| shadowOffsetY  | Shadow offset in y-axis direction | number \\| string              | -         |          |\n| shadowType     | Shadow type                       | `inner` \\| `outer`            | `outer`   |          |\n| stroke         | Stroke color                      | string                        | `#000`    |          |\n| strokeOpacity  | Stroke color opacity              | number \\| string              | 1         |          |\n| value          | Value for ratio calculation       | number                        | -         | ✓        |\n| visibility     | Visibility of the shape           | `visible` \\| `hidden`         | `visible` |          |\n\n## Example\n\n### Built-in Donut Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Donut.zh.md":"---\ntitle: 甜甜圈节点 Donut\norder: 4\n---\n\n## 概述\n\n甜甜圈节点是一个环形几何形状，由内外两个同心圆组成。\n\n适用场景：\n\n- 用于表示比例数据，如完成进度、占比分析。\n\n- 适合表示多层数据，如嵌套的环形图。\n\n- 常用于数据可视化、仪表盘、进度图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性                | 描述                           | 类型                                        | 默认值    | 必选 |\n| ------------------- | ------------------------------ | ------------------------------------------- | --------- | ---- |\n| donutFill           | 填充色                         | string                                      | `#1783FF` |      |\n| donutFillOpacity    | 填充色透明度                   | number \\| string                            | 1         |      |\n| donutLineCap        | 描边端点样式                   | `round` \\| `square` \\| `butt`               | `butt`    |      |\n| donutLineDash       | 描边虚线样式                   | number[]                                    | -         |      |\n| donutLineDashOffset | 描边虚线偏移量                 | number                                      | -         |      |\n| donutLineJoin       | 描边连接处样式                 | `round` \\| `bevel` \\| `miter`               | `miter`   |      |\n| donutLineWidth      | 描边宽度                       | number                                      | 1         |      |\n| donutOpacity        | 透明度                         | number \\| string                            | 1         |      |\n| donutPalette        | 颜色或者色板名                 | string &#124; string[]                      | `tableau` |      |\n| donuts              | 圆环数据                       | number[] &#124; [DonutRound](#donutround)[] | -         |      |\n| donutShadowBlur     | 阴影模糊度                     | number                                      | -         |      |\n| donutShadowColor    | 阴影颜色                       | string                                      | -         |      |\n| donutShadowOffsetX  | 阴影在 x 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowOffsetY  | 阴影在 y 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowType     | 阴影类型                       | `inner` \\| `outer`                          | `outer`   |      |\n| donutStroke         | 描边色                         | string                                      | `#000`    |      |\n| donutStrokeOpacity  | 描边色透明度                   | number \\| string                            | 1         |      |\n| donutVisibility     | 图形是否可见                   | `visible` \\| `hidden`                       | `visible` |      |\n| innerR              | 内环半径，使用百分比或者像素值 | string &#124; number                        | 50%       |      |\n\n### DonutRound\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| color          | 颜色                      | string                        | -         |      |\n| fill           | 填充色                    | string                        | `#1783FF` |      |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |      |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash       | 描边虚线样式              | number[]                      | -         |      |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |      |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth      | 描边宽度                  | number                        | 1         |      |\n| opacity        | 透明度                    | number \\| string              | 1         |      |\n| shadowBlur     | 阴影模糊度                | number                        | -         |      |\n| shadowColor    | 阴影颜色                  | string                        | -         |      |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |      |\n| stroke         | 描边色                    | string                        | `#000`    |      |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |      |\n| value          | 数值，用于计算比例        | number                        | -         | ✓    |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |      |\n\n## 示例\n\n### 内置甜甜圈节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Ellipse.en.md":"---\ntitle: Ellipse Node\norder: 5\n---\n\n## Overview\n\nAn ellipse is a geometric shape with asymmetrical major and minor axes.\n\nApplicable scenarios:\n\n- Used to represent dynamic nodes, asymmetric relationships, or special shapes.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Ellipse Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Ellipse.zh.md":"---\ntitle: 椭圆形节点 Ellipse\norder: 5\n---\n\n## 概述\n\n椭圆是一个长轴和短轴不对称的几何形状。\n\n适用场景：\n\n- 用于表示动态节点、非对称关系或特殊形状。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置椭圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Hexagon.en.md":"---\ntitle: Hexagon Node\norder: 6\n---\n\n## Overview\n\nA hexagon is a geometric shape with six equal sides, featuring a honeycomb structure.\n\nApplicable scenarios:\n\n- Used to represent honeycomb networks, molecular structures, or tightly packed nodes.\n\n- Suitable for representing network topology, molecular diagrams, or game maps.\n\n- Commonly used in network diagrams, topology diagrams, game design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                        | Type   | Default                                 | Required |\n| --------- | ------------------------------------------------------------------ | ------ | --------------------------------------- | -------- |\n| outerR    | Outer radius, the distance from the hexagon's center to any vertex | number | Half of the minimum of width and height |          |\n\n## Example\n\n### Built-in Hexagon Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Hexagon.zh.md":"---\ntitle: 六边形节点 Hexagon\norder: 6\n---\n\n## 概述\n\n六边形是一个六边相等的几何形状，具有蜂窝状结构。\n\n适用场景：\n\n- 用于表示蜂窝网络、分子结构或紧密排列的节点。\n\n- 适合表示网络拓扑、分子图或游戏地图。\n\n- 常用于网络图、拓扑图、游戏设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                     | 类型   | 默认值                   | 必选 |\n| ------ | ---------------------------------------- | ------ | ------------------------ | ---- |\n| outerR | 外半径，是指从六边形中心到任意顶点的距离 | number | 默认为宽高的最小值的一半 |      |\n\n## 示例\n\n### 内置六边形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Html.en.md":"---\ntitle: HTML Node\norder: 7\n---\n\n## Overview\n\nHTML node is a custom rectangular area used to display HTML content. It allows you to embed arbitrary HTML elements within graph nodes, providing great flexibility for creating complex custom nodes.\n\nUse Cases:\n\n- Used to represent complex custom nodes such as tables, charts, or rich text\n- Suitable for representing custom visual elements or interactive components\n- Commonly used in custom charts, UI design, dashboards, and other scenarios\n- When you need to embed interactive elements like forms and buttons in nodes\n\n## Framework Support\n\n> **💡 Tips**：\n>\n> - **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node) for better component-based development experience\n> - **Vue Projects**: Vue Node is not currently supported, community contributions are welcome\n> - **Native HTML**: The HTML node introduced in this document is suitable for native HTML development\n\n## Online Demo\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific properties, we will list them below. For all common style properties, see [BaseNode](/en/manual/element/node/base-node)\n\n| Property  | Description                                                                                           | Type                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------------- | --------------------------- | ------- | -------- |\n| dx        | Horizontal offset. HTML container defaults to top-left corner as origin, use dx for horizontal offset | number                      | 0       |          |\n| dy        | Vertical offset. HTML container defaults to top-left corner as origin, use dy for vertical offset     | number                      | 0       |          |\n| innerHTML | HTML content, can be string or `HTMLElement`                                                          | string &#124; `HTMLElement` | -       | ✓        |\n\n## Examples\n\n### Basic HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### HTML Node with Interactive Buttons\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >Restart</button>\n    <button \n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >Monitor</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle button clicks\nwindow.handleRestart = (nodeId) => {\n  console.log(`Restarting server: ${nodeId}`);\n  alert(`Restarting server ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`Opening monitoring panel: ${nodeId}`);\n  alert(`Opening monitoring panel for server ${nodeId}`);\n};\n\ngraph.render();\n```\n\n### Form Input HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: 'User Information', type: 'user-form' } },\n      { id: 'form-2', data: { title: 'Configuration Panel', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Name</label>\n    <input \n      type=\"text\" \n      placeholder=\"Enter name\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Email</label>\n    <input \n      type=\"email\" \n      placeholder=\"Enter email\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Role</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>Administrator</option>\n      <option>User</option>\n      <option>Guest</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Save</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Cancel</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle form operations\nwindow.handleSave = (nodeId) => {\n  console.log(`Saving form: ${nodeId}`);\n  alert(`Form ${nodeId} saved`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`Canceling form: ${nodeId}`);\n  alert(`Form ${nodeId} operation canceled`);\n};\n\ngraph.render();\n```\n\n## Usage Notes\n\n### 1. Performance Optimization\n\n- HTML nodes have higher rendering costs compared to regular graphic nodes, recommend using when node count is small\n- Complex HTML structures will affect performance, recommend keeping structure simple\n- Avoid using too many animation effects in HTML\n\n### 2. Event Handling\n\n- Event handling in HTML nodes needs to be implemented through global functions or event delegation\n- Recommend mounting event handling functions to the `window` object to ensure accessibility in HTML strings\n- Be careful to prevent event bubbling from affecting graph interaction behavior\n\n### 3. Style Isolation\n\n- HTML node styles may be affected by global page styles\n- Recommend using inline styles or ensuring sufficient style specificity\n- Consider using CSS-in-JS or style namespaces to avoid style conflicts\n\n### 4. Responsive Design\n\n- HTML node dimensions are fixed and do not automatically adapt to content\n- Need to dynamically calculate node dimensions based on content or use responsive layouts\n- Consider display effects at different zoom levels\n\n### 5. Framework Integration Recommendations\n\n- **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node), which allows direct use of React components as node content\n- **Vue Projects**: Vue Node is not currently supported, community contributions are welcome if needed\n- **Native Projects**: HTML nodes are the best choice, providing maximum flexibility\n","packages/site/docs/manual/element/node/Html.zh.md":"---\ntitle: HTML节点 Html\norder: 7\n---\n\n## 概述\n\nHTML 节点是一个自定义的矩形区域，用于显示 HTML 内容。它允许您在图形节点中嵌入任意的 HTML 元素，提供了极大的灵活性来创建复杂的自定义节点。\n\n适用场景：\n\n- 用于表示复杂的自定义节点，如表格、图表或富文本\n- 适合表示自定义的可视化元素或交互组件\n- 常用于自定义图表、UI 设计、仪表板等场景\n- 需要在节点中嵌入表单、按钮等交互元素时\n\n## 框架支持说明\n\n> **💡 提示**：\n>\n> - **React 项目**：推荐使用 [React Node](/manual/element/node/react-node) 来实现更好的组件化开发体验\n> - **Vue 项目**：目前暂不支持 Vue Node，欢迎社区共建贡献\n> - **原生 HTML**：本文档介绍的 HTML 节点适用于原生 HTML 开发\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述                                                            | 类型                        | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------- | --------------------------- | ------ | ---- |\n| dx        | 横行偏移量。HTML 容器默认以左上角为原点，通过 dx 来进行横向偏移 | number                      | 0      |      |\n| dy        | 纵向偏移量。HTML 容器默认以左上角为原点，通过 dy 来进行纵向偏移 | number                      | 0      |      |\n| innerHTML | HTML 内容，可以为字符串或者 `HTMLElement`                       | string &#124; `HTMLElement` | -      | ✓    |\n\n## 示例\n\n### 基础HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 带交互按钮的HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%;\n  height: 100%;\n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"display: flex; gap: 8px;\">\n    <button\n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >重启</button>\n    <button\n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >监控</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理按钮点击\nwindow.handleRestart = (nodeId) => {\n  console.log(`重启服务器: ${nodeId}`);\n  alert(`正在重启服务器 ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`打开监控面板: ${nodeId}`);\n  alert(`打开服务器 ${nodeId} 的监控面板`);\n};\n\ngraph.render();\n```\n\n### 表单输入HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: '用户信息', type: 'user-form' } },\n      { id: 'form-2', data: { title: '配置面板', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">姓名</label>\n    <input \n      type=\"text\" \n      placeholder=\"请输入姓名\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">邮箱</label>\n    <input \n      type=\"email\" \n      placeholder=\"请输入邮箱\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">角色</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>管理员</option>\n      <option>用户</option>\n      <option>访客</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >保存</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >取消</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理表单操作\nwindow.handleSave = (nodeId) => {\n  console.log(`保存表单: ${nodeId}`);\n  alert(`表单 ${nodeId} 已保存`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`取消表单: ${nodeId}`);\n  alert(`取消表单 ${nodeId} 操作`);\n};\n\ngraph.render();\n```\n\n## 使用注意事项\n\n### 1. 性能优化\n\n- HTML 节点相比普通图形节点有更高的渲染成本，建议在节点数量较少时使用\n- 复杂的 HTML 结构会影响性能，建议保持结构简洁\n- 避免在 HTML 中使用过多的动画效果\n\n### 2. 事件处理\n\n- HTML 节点中的事件处理需要通过全局函数或事件委托来实现\n- 建议将事件处理函数挂载到 `window` 对象上，确保在 HTML 字符串中可以访问\n- 注意防止事件冒泡影响图的交互行为\n\n### 3. 样式隔离\n\n- HTML 节点的样式可能会受到页面全局样式的影响\n- 建议使用内联样式或确保样式的特异性足够高\n- 考虑使用 CSS-in-JS 或样式命名空间来避免样式冲突\n\n### 4. 响应式设计\n\n- HTML 节点的尺寸是固定的，不会自动适应内容\n- 需要根据内容动态计算节点尺寸，或使用响应式布局\n- 考虑在不同缩放级别下的显示效果\n\n### 5. 框架集成建议\n\n- **React 项目**：推荐使用 [React Node](/manual/element/node/react-node)，可以直接使用 React 组件作为节点内容\n- **Vue 项目**：目前暂不支持 Vue Node，如有需求欢迎社区贡献\n- **原生项目**：HTML 节点是最佳选择，提供了最大的灵活性\n","packages/site/docs/manual/element/node/Image.en.md":"---\ntitle: Image Node\norder: 8\n---\n\n## Overview\n\nThe image node is a rectangular area used to display images.\n\nApplicable scenarios:\n\n- Used to represent user avatars, product images, or icons.\n\n- Suitable for representing social networks, product catalogs, or icon collections.\n\n- Commonly used in social network graphs, product images, UI design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                          | Type   | Default | Required |\n| --------- | ------------------------------------ | ------ | ------- | -------- |\n| img       | Alias for the img attribute          | string | -       |          |\n| src       | Image source, i.e., image URL string | string | -       | ✓        |\n\n## Example\n\n### Built-in Image Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Image.zh.md":"---\ntitle: 图片节点 Image\norder: 8\n---\n\n## 概述\n\n图片节点是一个矩形区域，用于显示图像。\n\n适用场景：\n\n- 用于表示用户头像、产品图片或图标。\n\n- 适合表示社交网络、产品目录或图标集合。\n\n- 常用于社交网络图、产品图、UI 设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性 | 描述                       | 类型   | 默认值 | 必选 |\n| ---- | -------------------------- | ------ | ------ | ---- |\n| img  | 该属性为 img 的别名        | string | -      |      |\n| src  | 图片来源，即图片地址字符串 | string | -      | ✓    |\n\n## 示例\n\n### 内置图片节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Rect.en.md":"---\ntitle: Rect Node\norder: 9\n---\n\n## Overview\n\nA rectangle is a geometric shape with four equal sides and defined boundaries.\n\nApplicable scenarios:\n\n- Used to represent modules, components, or containers.\n\n- Suitable for representing hierarchies, such as organizational charts, file directory trees.\n\n- Commonly used in flowcharts, architecture diagrams, UML diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Rect Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Rect.zh.md":"---\ntitle: 矩形节点 Rect\norder: 9\n---\n\n## 概述\n\n矩形是一个四边相等的几何形状，具有明确的边界。\n\n适用场景：\n\n- 用于表示模块、组件或容器。\n\n- 适合表示层次结构，如组织结构图、文件目录树。\n\n- 常用于流程图、架构图、UML 图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置矩形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Star.en.md":"---\ntitle: Star Node\norder: 10\n---\n\n## Overview\n\nA star is a polygonal geometric shape with prominent points.\n\nApplicable scenarios:\n\n- Used to represent important nodes, special markers, or decorative elements.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                           | Type   | Default                            | Required |\n| --------- | --------------------------------------------------------------------- | ------ | ---------------------------------- | -------- |\n| innerR    | Inner radius, the distance from the star's center to the inner vertex | number | Default is 3/8 of the outer radius |\n\nStructure Description:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## Example\n\n### Built-in Star Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Star.zh.md":"---\ntitle: 五角形节点 Star\norder: 10\n---\n\n## 概述\n\n星形是一个多角几何形状，具有突出的角。\n\n适用场景：\n\n- 用于表示重要节点、特殊标记或装饰性元素。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                 | 类型   | 默认值             | 必选 |\n| ------ | ------------------------------------ | ------ | ------------------ | ---- |\n| innerR | 内半径，是指从星形中心到内顶点的距离 | number | 默认为外半径的 3/8 |\n\n结构说明：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## 示例\n\n### 内置五角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Triangle.en.md":"---\ntitle: Triangle Node\norder: 11\n---\n\n## Overview\n\nA triangle is a geometric shape with three sides, having a clear directionality.\n\nApplicable scenarios:\n\n- Used to represent directional nodes, warnings, or prompts.\n\n- Suitable for indicating direction or hierarchy in flowcharts.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description               | Type                                | Default | Required |\n| --------- | ------------------------- | ----------------------------------- | ------- | -------- |\n| direction | Direction of the triangle | `up` \\| `left` \\| `right` \\| `down` | `up`    |\n\n## Example\n\n### Built-in Triangle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Triangle.zh.md":"---\ntitle: 三角形节点 Triangle\norder: 11\n---\n\n## 概述\n\n三角形是一个三边几何形状，具有明确的方向性。\n\n适用场景：\n\n- 用于表示方向性节点、警告或提示。\n\n- 适合表示流程图中的方向指示或层级关系。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述         | 类型                                | 默认值 | 必选 |\n| --------- | ------------ | ----------------------------------- | ------ | ---- |\n| direction | 三角形的方向 | `up` \\| `left` \\| `right` \\| `down` | `up`   |\n\n## 示例\n\n### 内置三角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/custom-node.en.md":"---\ntitle: Custom Node\norder: 12\n---\n\nG6 provides a series of [built-in nodes](/en/manual/element/node/base-node), including [circle (Circle Node)](/en/manual/element/node/circle), [diamond (Diamond Node)](/en/manual/element/node/diamond), [donut (Donut Node)](/en/manual/element/node/donut), [ellipse (Ellipse Node)](/en/manual/element/node/ellipse), [hexagon (Hexagon Node)](/en/manual/element/node/hexagon), [html (HTML Node)](/en/manual/element/node/html), [image (Image Node)](/en/manual/element/node/image), [rect (Rectangle Node)](/en/manual/element/node/rect), [star (Star Node)](/en/manual/element/node/star), and [triangle (Triangle Node)](/en/manual/element/node/triangle). These built-in nodes can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter needs that these basic nodes cannot satisfy. In such cases, you need to create custom nodes. Don't worry, this is simpler than you might think!\n\n## Ways to Create Custom Nodes <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are mainly two approaches to creating custom nodes:\n\n### 1. Inherit from Existing Node Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach, where you can choose to inherit from one of the following types:\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - The most basic node class, providing core node functionality\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - Circle node\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - Rectangle node\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - Ellipse node\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - Diamond node\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - Triangle node\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - Star node\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - Image node\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - Donut node\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - Hexagon node\n\n**Why choose this approach?**\n\n- 📌 **Less Code**: Reuse properties and methods of existing nodes, only focus on new features\n- 📌 **Rapid Development**: Suitable for most project needs, quickly achieve business goals\n- 📌 **Easy Maintenance**: Clear code structure with well-defined inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing node types (recommended), you can jump directly to [Create Your First Custom Node in Three Steps](#create-your-first-custom-node-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing node types don't meet your requirements, you can create nodes from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum Freedom**: Complete control over every detail of the node, achieving any complex effects\n- 📌 **Special Requirements**: Highly customized scenarios that existing node types cannot satisfy\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom nodes built from scratch require handling all details yourself, including graphics rendering, event response, state changes, etc., with higher development difficulty. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) for implementation.\n:::\n\n## Create Your First Custom Node in Three Steps\n\nLet's start with a simple example - creating a **rectangle node with main and subtitle**:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// Step 1: Create custom node class\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// Step 2: Register custom node\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// Step 3: Use custom node\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Node Class\n\nInherit from G6's `Rect` (rectangle node) and add a subtitle:\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// Create custom node, inheriting from Rect\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### Step 2: Register Custom Node\n\nUse the `register` method to register the node type so that G6 can recognize your custom node:\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `dual-label-node` is the name we give to this custom node, which will be used in configuration later\n- Class definition: `DualLabelNode` is the node class we just created\n\n### Step 3: Apply Custom Node\n\nUse the custom node in graph configuration:\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom node. It looks simple, but this process contains the core concept of custom nodes: **inherit from a basic node type**, then **override the `render` method** to add custom content.\n\n## Understanding Data Flow: How to Access Data in Custom Nodes\n\nBefore creating complex custom nodes, understanding how data flows into custom nodes is very important. G6 provides multiple ways to access data for custom nodes:\n\n### Method 1: Through `attributes` Parameter (Recommended)\n\nThe first parameter `attributes` of the `render` method contains processed style attributes, including data-driven styles:\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes contains all style attributes, including data-driven styles\n    console.log('All properties of current node:', attributes);\n\n    // If customData: (d) => d.data.someValue is defined in style\n    // Then you can access it through attributes.customData\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Method 2: Through `this.context.graph` to Access Raw Data\n\nWhen you need to access the node's raw data, you can get it through the graph instance:\n\n```js\nclass CustomNode extends Rect {\n  // Convenient data access method\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Get complete node data\n    const nodeData = this.nodeData;\n    console.log('Complete node data:', nodeData);\n\n    // Get business data from data field\n    const businessData = this.data;\n    console.log('Business data:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Complete Data Flow Process\n\nLet's understand how data flows from graph data to custom nodes through a specific example:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // Method 2: Get raw data through graph\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Method 1: Get processed styles from attributes\n    console.log('Get from attributes:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // Method 2: Get from raw data\n    console.log('Get from raw data:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Use data to render custom content\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // This is the node's business data\n        data: {\n          name: 'Zhang San',\n          role: 'Developer',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // Map data from data field to style attributes\n      iconUrl: (d) => d.data.icon, // This becomes attributes.iconUrl\n      userName: (d) => d.data.name, // This becomes attributes.userName\n      // Main title uses role information\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=Data Flow Summary}\n\n1. **Graph Data Definition**: Define business data in `data.nodes[].data`\n2. **Style Mapping**: Use functions in `node.style` to map data to style attributes\n3. **Node Access**: Access data in custom nodes through `attributes` or `this.context.graph`\n4. **Rendering Usage**: Use the obtained data to render custom graphics\n   :::\n\n## From Simple to Complex: Gradually Building Feature-Rich Nodes\n\nLet's gradually increase the complexity and functionality of nodes through practical examples.\n\n### Example 1: User Card Node with Icon and Badge\n\nThis example shows how to create a user card node containing avatar, name, and status badge:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // Avatar style\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // Circular avatar\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // Status badge style\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // Username style\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // Role label style\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Add various components\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: 'Zhang Xiaoming',\n          role: 'Frontend Engineer',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // Data mapping\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 2: Node with Clickable Action Button\n\nAdd a blue button to the node that triggers events (prints logs or executes callbacks) when clicked.\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // Mouse pointer becomes hand\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // Add click event to button\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // Prevent event bubbling to avoid triggering node click event\n        e.stopPropagation();\n\n        // Execute business logic\n        console.log('Button clicked on node:', this.id);\n\n        // If there's a callback function in data, call it\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // Mark as bound to avoid duplicate binding\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // Add a button\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // Specify using our custom node\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 3: Node Responding to State Changes (Click to Change Color)\n\nCommon interactions require nodes and edges to provide feedback through style changes, such as when the mouse moves over a node, clicking to select nodes/edges, or activating interactions on edges through interaction. All these require changing the styles of nodes and edges. There are two ways to achieve this effect:\n\n1. Get the current state from `data.states` and handle state changes in the custom node class;\n2. Separate interaction state from raw data and node drawing logic, only update the node.\n\nWe recommend users use the second approach to implement node state adjustments, which can be achieved through the following steps:\n\n1. Implement custom node;\n2. Configure node state styles in graph configuration;\n3. Set node state through the `graph.setElementState()` method.\n\nBased on rect, extend a hole shape with default white fill color that turns orange when clicked. The sample code to achieve this effect is as follows:\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. Define node class\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. Register node\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. Create graph instance\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // Mouse selected state\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. Add node interaction\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/custom-node.zh.md":"---\ntitle: 自定义节点\norder: 12\n---\n\nG6 提供了一系列 [内置节点](/manual/element/node/base-node)，包含 [circle（圆形节点）](/manual/element/node/circle)、[diamond（菱形节点）](/manual/element/node/diamond)、[donut（甜甜圈节点）](/manual/element/node/donut)、[ellipse（椭圆节点）](/manual/element/node/ellipse)、[hexagon（六边形节点）](/manual/element/node/hexagon)、[html（HTML节点）](/manual/element/node/html)、[image（图片节点）](/manual/element/node/image)、[rect（矩形节点）](/manual/element/node/rect)、[star（星形节点）](/manual/element/node/star) 和 [triangle（三角形节点）](/manual/element/node/triangle)。这些内置节点能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础节点无法满足的需求。这时，你需要创建自定义节点。别担心，这比你想象的要简单！\n\n## 自定义节点的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义节点的方式主要有两种途径：\n\n### 1. 继承现有节点类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - 最基础的节点类，提供节点的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - 圆形节点\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - 矩形节点\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - 椭圆节点\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - 菱形节点\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - 三角形节点\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - 星形节点\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - 图片节点\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - 甜甜圈节点\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - 六边形节点\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有节点的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有节点类型（推荐），可以直接跳到 [三步创建你的第一个自定义节点](#三步创建你的第一个自定义节点) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有节点类型都不满足需求，你可以基于 G 的底层图形系统从零创建节点。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制节点的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有节点类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义节点需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义节点\n\n让我们从一个简单的例子开始 - 创建一个 **带有主副标题的矩形节点**：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// 第一步：创建自定义节点类\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// 第二步：注册自定义节点\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// 第三步：使用自定义节点\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义节点类\n\n继承 G6 的 `Rect`（矩形节点），并添加一个副标题：\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 创建自定义节点，继承自 Rect\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### 第二步：注册自定义节点\n\n使用 `register` 方法注册节点类型，这样 G6 才能识别你的自定义节点：\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`dual-label-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：`DualLabelNode` 是我们刚刚创建的节点类\n\n### 第三步：应用自定义节点\n\n在图配置中使用自定义节点：\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义节点。它看起来很简单，但这个过程包含了自定义节点的核心思想：**继承一个基础节点类型**，然后 **重写 `render` 方法** 来添加自定义内容。\n\n## 理解数据流：如何在自定义节点中获取数据\n\n在创建复杂的自定义节点之前，理解数据如何流入自定义节点是非常重要的。G6 为自定义节点提供了多种数据获取方式：\n\n### 方式一：通过 `attributes` 参数（推荐）\n\n`render` 方法的第一个参数 `attributes` 包含了经过处理的样式属性，包括数据驱动的样式：\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes 包含了所有样式属性，包括数据驱动的样式\n    console.log('当前节点的所有属性:', attributes);\n\n    // 如果在 style 中定义了 customData: (d) => d.data.someValue\n    // 那么可以通过 attributes.customData 获取\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 方式二：通过 `this.context.graph` 获取原始数据\n\n当你需要访问节点的原始数据时，可以通过图实例获取：\n\n```js\nclass CustomNode extends Rect {\n  // 便捷的数据获取方法\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 获取节点的完整数据\n    const nodeData = this.nodeData;\n    console.log('节点完整数据:', nodeData);\n\n    // 获取 data 字段中的业务数据\n    const businessData = this.data;\n    console.log('业务数据:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 数据传递的完整流程\n\n让我们通过一个具体例子来理解数据是如何从图数据传递到自定义节点的：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // 方式二：通过 graph 获取原始数据\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 方式一：从 attributes 获取处理后的样式\n    console.log('从 attributes 获取:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // 方式二：从原始数据获取\n    console.log('从原始数据获取:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 使用数据渲染自定义内容\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // 这里是节点的业务数据\n        data: {\n          name: '张三',\n          role: '开发者',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // 将 data 中的数据映射到样式属性\n      iconUrl: (d) => d.data.icon, // 这会变成 attributes.iconUrl\n      userName: (d) => d.data.name, // 这会变成 attributes.userName\n      // 主标题使用角色信息\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=数据流总结}\n\n1. **图数据定义**：在 `data.nodes[].data` 中定义业务数据\n2. **样式映射**：在 `node.style` 中使用函数将数据映射到样式属性\n3. **节点获取**：在自定义节点中通过 `attributes` 或 `this.context.graph` 获取数据\n4. **渲染使用**：使用获取到的数据渲染自定义图形\n   :::\n\n## 从简单到复杂：逐步构建功能丰富的节点\n\n让我们通过实际例子，逐步增加节点的复杂度和功能。\n\n### 示例一：带图标和徽章的用户卡片节点\n\n这个例子展示如何创建一个包含头像、姓名、状态徽章的用户卡片节点：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // 头像样式\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // 圆形头像\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // 状态徽章样式\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // 用户名样式\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // 角色标签样式\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 添加各个组件\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: '张小明',\n          role: '前端工程师',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // 数据映射\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例二：可点击操作按钮的节点\n\n给节点加一个蓝色按钮，点击后触发事件（打印日志或执行回调）。\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // 鼠标指针变为手型\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // 为按钮添加点击事件\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // 阻止事件冒泡，避免触发节点的点击事件\n        e.stopPropagation();\n\n        // 执行业务逻辑\n        console.log('Button clicked on node:', this.id);\n\n        // 如果数据中有回调函数，则调用\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // 标记已绑定事件，避免重复绑定\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // 添加一个按钮\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // 指定使用我们的自定义节点\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例三：响应状态变化的节点（点击变色）\n\n常见的交互都需要节点和边通过样式变化做出反馈，例如鼠标移动到节点上、点击选中节点/边、通过交互激活边上的交互等，都需要改变节点和边的样式，有两种方式来实现这种效果：\n\n1. 从 `data.states` 获取当前状态，在自定义节点类中处理状态变化；\n2. 将交互状态同原始数据和绘制节点的逻辑分开，仅更新节点。\n\n我们推荐用户使用第二种方式来实现节点的状态调整，可以通过以下方式来实现：\n\n1. 实现自定义节点；\n2. 在图配置项中配置节点状态样式；\n3. 通过 `graph.setElementState()` 方法来设置节点状态。\n\n基于 rect 扩展出一个 hole 图形，默认填充色为白色，当鼠标点击时变成橙色，实现这一效果的示例代码如下：\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. 定义节点类\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. 注册节点\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. 创建图实例\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // 鼠标选中状态\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. 添加节点交互\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/overview.en.md":"---\ntitle: Node Overview\norder: 0\n---\n\n## What is a Node\n\nA node is one of the basic elements in a graph, representing an entity or an abstract concept, such as a person, a place, an organization, etc. Nodes can contain attributes like ID, name, type, etc. In G6, nodes can have various shapes and styles, and support rich interactions and customization.\n\nYou can create any number of nodes in a graph and connect them with edges to represent relationships.\n\n## Node System\n\nThe G6 node system includes three main categories: built-in nodes, extended nodes, and custom nodes. **In most cases, built-in nodes are sufficient.**\n\n### Built-in Nodes\n\nG6 provides a variety of built-in node types, **which can be used directly without registration**:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| Node Type      | Registration Name | Description                                     |\n| -------------- | ----------------- | ----------------------------------------------- |\n| Circle Node    | `circle`          | Commonly used for entities                      |\n| Rectangle Node | `rect`            | Suitable for more text and details              |\n| Ellipse Node   | `ellipse`         | A variant of the circle                         |\n| Diamond Node   | `diamond`         | Often used for decision points or special nodes |\n| Triangle Node  | `triangle`        | Can indicate direction or special marks         |\n| Hexagon Node   | `hexagon`         | Suitable for grid layouts and honeycomb charts  |\n| Star Node      | `star`            | Highlights important nodes                      |\n| Donut Node     | `donut`           | Can display proportions or progress             |\n| Image Node     | `image`           | Uses an image as the node body                  |\n| HTML Node      | `html`            | Supports custom HTML content                    |\n\n### 3D Nodes\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` provides 3D nodes:\n\n- `Capsule` - Capsule-shaped node\n- `Cone` - Cone-shaped node\n- `Cube` - Cube-shaped node\n- `Cylinder` - Cylinder-shaped node\n- `Plane` - Plane node\n- `Sphere` - Sphere node\n- `Torus` - Torus node\n\n### React Nodes\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` provides React nodes, supporting the use of React components as the node body. For detailed tutorials, please refer to the [Using React to Define Nodes](/en/manual/element/node/react-node) document.\n\n### Custom Nodes\n\nWhen built-in and extended nodes cannot meet the requirements, G6 offers powerful customization capabilities:\n\n- Extend built-in nodes\n- Create entirely new node types\n\nUnlike built-in nodes, **custom nodes need to be registered before use**. For detailed tutorials, please refer to the [Custom Nodes](/en/manual/element/node/custom-node) document.\n\n## Data Structure\n\nWhen defining nodes, you need to add a `nodes` field to the graph's data object. Each node is an object with the following structure:\n\n| Property | Description                                                                                                                             | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                     | string         | -       | ✓        |\n| type     | Node type, either a built-in node type name or a custom node name                                                                       | string         | -       |          |\n| data     | Node data, used to store custom data such as the node's name, description, etc. Can be accessed via callback functions in style mapping | object         | -       |          |\n| style    | Node style, including visual attributes like position, size, color, etc.                                                                | object         | -       |          |\n| states   | Initial states of the node, such as selected, active, hover, etc.                                                                       | string[]       | -       |          |\n| combo    | The ID of the combo to which the node belongs, used to organize hierarchical relationships. If none, it is null                         | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                         | string[]       | -       |          |\n\nAn example of a data item in the `nodes` array:\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure nodes, listed in order of priority from high to low:\n\n- Use `graph.setNode()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setNode()`\n\nAfter creating the graph instance, you can use `graph.setNode()` to dynamically set the node's style mapping logic.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nWhen instantiating the graph, you can configure node style mapping through `node`, which is a global configuration and will apply to all nodes.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different nodes, you can write the configuration into the node data. This configuration method can be directly written into the data in the following form:\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can do so as follows:\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### Dynamically Updating Nodes\n\nG6 supports dynamically updating the style and state of nodes at runtime:\n\n```typescript\n// Update the style of a single node\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// Set node state\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=Note}\nWhen updating nodes, only the specified attributes will be updated, and unspecified attributes will remain unchanged.\n:::\n\nFor more node-related APIs, please refer to [API - Element Operations](/en/api/element).\n\n## Node States\n\nNodes can have different states, such as selected, highlighted, disabled, etc. You can define the display effect of nodes in different states by configuring state styles:\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // Default style\n      fill: '#C6E5FF',\n    },\n    // State styles\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\nThe state system is the foundation for implementing node interaction effects. For more information on states, please refer to [Element States](/en/manual/element/state).\n","packages/site/docs/manual/element/node/overview.zh.md":"---\ntitle: 节点总览\norder: 0\n---\n\n## 什么是节点\n\n节点（Node）是图中的基本元素之一，表示图中的实体或者抽象概念，例如一个人、一个地点、一个组织等，节点可以包含一些属性，例如节点的 ID、名称、类型等。在 G6 中，节点可以具有多种形状和样式，并支持丰富的交互和自定义功能。\n\n你可以在图中创建任意数量的节点，并通过边连接它们以表示关系。\n\n## 节点体系\n\nG6 的节点体系包括三大类：内置节点、扩展节点和自定义节点。**大多数场景下，内置节点即可满足需求**。\n\n### 内置节点\n\nG6 提供了丰富的内置节点类型，**无需注册，直接配置即可使用**：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| 节点类型   | 注册名称   | 描述                     |\n| ---------- | ---------- | ------------------------ |\n| 圆形节点   | `circle`   | 常用于表示普通实体       |\n| 矩形节点   | `rect`     | 适合展示更多文本和细节   |\n| 椭圆节点   | `ellipse`  | 类似圆形的变体           |\n| 菱形节点   | `diamond`  | 常用于决策点或特殊节点   |\n| 三角形节点 | `triangle` | 可用于指示方向或特殊标记 |\n| 六边形节点 | `hexagon`  | 适合网格布局和蜂窝图     |\n| 星形节点   | `star`     | 突出显示重要节点         |\n| 甜甜圈节点 | `donut`    | 可展示比例或进度信息     |\n| 图片节点   | `image`    | 使用图片作为节点主体     |\n| HTML节点   | `html`     | 支持自定义HTML内容       |\n\n### 3D 节点\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` 提供了 3D 节点：\n\n- `Capsule` - 胶囊型节点\n- `Cone` - 圆锥型节点\n- `Cube` - 立方体节点\n- `Cylinder` - 圆柱型节点\n- `Plane` - 平面节点\n- `Sphere` - 球体节点\n- `Torus` - 圆环节点\n\n### React 节点\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` 提供了 React 节点，支持使用 React 组件作为节点的主体，详细教程请查看 [使用 React 定义节点](/manual/element/node/react-node) 文档。\n\n### 自定义节点\n\n当内置节点和扩展节点无法满足需求时，G6提供了强大的自定义能力：\n\n- 继承内置节点进行扩展\n- 创建全新的节点类型\n\n与内置节点不同，**自定义节点需要先注册后使用**。详细教程请参考 [自定义节点](/manual/element/node/custom-node) 文档。\n\n## 数据结构\n\n定义节点时，需要在图的数据对象中添加 `nodes` 字段。每个节点是一个对象，结构如下：\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n`nodes` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## 配置方法\n\n配置节点的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setNode()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setNode()`\n\n可在图实例创建后，使用 `graph.setNode()` 动态设置节点的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `node` 配置节点样式映射，这里的配置是全局的配置，将会在所有节点上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同节点进行不同的配置，可以将配置写入到节点数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### 动态更新节点\n\nG6 支持在运行时动态更新节点的样式和状态：\n\n```typescript\n// 更新单个节点样式\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// 设置节点状态\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=注意}\n更新节点时，只有指定的属性会被更新，未指定的属性保持不变。\n:::\n\n更多与节点相关的 API 请参考 [API - 元素操作](/api/element)。\n\n## 节点状态\n\n节点可以拥有不同的状态，例如选中、高亮、禁用等。可以通过配置状态样式来定义节点在不同状态下的显示效果：\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // 默认样式\n      fill: '#C6E5FF',\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n状态系统是实现节点交互效果的基础，更多状态的介绍，请参考 [元素状态](/manual/element/state)。\n","packages/site/docs/manual/element/node/react-node.en.md":"---\ntitle: Define Nodes with React\norder: 13\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the `@antv/g6-extension-react` ecosystem library, you can directly use React components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Ant Design\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing React design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a React project**: Ensure a React project is installed and created.\n- **React version requirement**: Ensure the React version used is >=16.8.0.\n\n### Install Dependencies\n\nTo use `@antv/g6-extension-react`, run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register React Node Type\n\nRegister the React node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `react-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: ReactNode is the implementation class exported by `@antv/g6-extension-react`\n\n#### 2. Define Business Component\n\nDefine a simple React component as the content of the node:\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. Use the Component\n\nUse the custom React node in the graph configuration. Specify the node type and style in the graph configuration to use the custom React component.\n\n- `type`: Specify the node type as `react-node` (use the name given during registration)\n- `style.component`: Define the React component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // Set border color based on selection state\n        cursor: 'pointer', // Add mouse pointer style\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","packages/site/docs/manual/element/node/react-node.zh.md":"---\ntitle: 使用 React 定义节点\norder: 13\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 `@antv/g6-extension-react` 一方生态库，可以直接使用 React 组件作为节点内容，提升开发效率与可维护性。\n\n## 自定义节点方案选择\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Ant Design 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 React 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 React 项目**：确保已安装并创建 React 项目。\n- **React 版本要求**：确保使用的 React 版本 >=16.8.0。\n\n### 安装依赖\n\n要使用 `@antv/g6-extension-react`，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 React 节点类型\n\n通过扩展机制注册 React 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`react-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：ReactNode 是 `@antv/g6-extension-react` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 React 组件作为节点的内容：\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 React 节点。通过在图配置中指定节点类型和样式，来使用自定义的 React 组件。\n\n- `type`：指定节点类型为 `react-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 React 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n        cursor: 'pointer', // 添加鼠标指针样式\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","packages/site/docs/manual/element/node/vue-node.en.md":"---\ntitle: Define Nodes with Vue\norder: 14\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) ecosystem library, you can directly use Vue components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Element Plus / Ant Design Vue\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing Vue design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a Vue project**: Ensure a Vue project is installed and created.\n- **Vue version requirement**: Ensure the Vue version used is >=2.6.0. (Vue 3 is recommended)\n\n### Install Dependencies\n\nTo use [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue), run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register Vue Node Type\n\nRegister the Vue node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `vue-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: VueNode is the implementation class exported by `g6-extension-vue`\n\n#### 2. Define Business Component\n\nDefine a simple Vue component as the content of the node:\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. Use the Component\n\nUse the custom Vue node in the graph configuration. Specify the node type and style in the graph configuration to use the custom Vue component.\n\n- `type`: Specify the node type as `vue-node` (use the name given during registration)\n- `style.component`: Define the Vue component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // Set border color based on selection state\n          cursor: 'pointer', // Add mouse pointer style\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","packages/site/docs/manual/element/node/vue-node.zh.md":"---\ntitle: 使用 Vue 定义节点\norder: 14\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) 社区生态库，可以直接使用 Vue 组件作为节点内容，提升开发效率与可维护性。\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Element Plus / Ant Design Vue 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 Vue 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 Vue 项目**：确保已安装并创建 Vue 项目。\n- **Vue 版本要求**：确保使用的 Vue 版本 >=2.6.0。(推荐使用 Vue 3)\n\n### 安装依赖\n\n要使用 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue)，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 Vue 节点类型\n\n通过扩展机制注册 Vue 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`vue-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：VueNode 是 `g6-extension-vue` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 Vue 组件作为节点的内容：\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 Vue 节点。通过在图配置中指定节点类型和样式，来使用自定义的 Vue 组件。\n\n- `type`：指定节点类型为 `vue-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 Vue 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n          cursor: 'pointer', // 添加鼠标指针样式\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","packages/site/docs/manual/element/overview.en.md":"---\ntitle: Element Overview\norder: 1\n---\n\n## Element System\n\nThe core of G6 charts is composed of three basic elements: **Node**, **Edge**, and **Combo**. These elements are the fundamental units for building complex graphical networks.\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### Node\n\n[Nodes](/en/manual/element/node/overview) represent entities or concepts in the graph, such as people, places, objects, etc. G6 provides a rich set of built-in node types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 also supports [defining nodes using React](/en/manual/element/node/react-node) or [custom nodes](/en/manual/element/node/custom-node) to meet specific needs.\n\n### Edge\n\n[Edges](/en/manual/element/edge/overview) represent the connections between nodes, such as friendships, transactions, etc. G6 has multiple built-in edge types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nWhen built-in edges do not meet the requirements, complex connection expressions can be achieved through [custom edges](/en/manual/element/edge/custom-edge).\n\n### Combo\n\n[Combos](/en/manual/element/combo/overview) are special elements that can contain nodes and other combos, used to represent collections, groups, or hierarchical relationships. G6 has two built-in combo types:\n\n- **Circle Combo**(`circle`): Suitable for compact grouping\n- **Rectangle Combo**(`rect`): Suitable for regular layout grouping\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nCombos support nesting, dragging, expanding/collapsing, and other interactions, and more complex container behaviors can be achieved through [custom combos](/en/manual/element/combo/custom-combo).\n\n## Element Composition Principle\n\nEach element is composed of one or more basic shapes. Shapes are the smallest graphical units in G6, including [rectangle](/en/manual/element/shape/properties#rectstyleprops), [circle](/en/manual/element/shape/properties#circlestyleprops), [text](/en/manual/element/shape/properties#textstyleprops), [path](/en/manual/element/shape/properties#pathstyleprops), etc.\n\nFor example:\n\n- A node may consist of a background shape (such as a circle) and a text label\n- An edge may consist of a path, arrow, and text label\n- A combo may consist of a container shape, title text, and expand/collapse button\n\nFor more information about shapes, see [Shape Overview](/en/manual/element/shape/overview) and [Shape Style Properties](/en/manual/element/shape/properties).\n\n## Element State\n\n[Element State](/en/manual/element/state) is a powerful mechanism for displaying visual changes of elements in different interactions or business scenarios. G6 provides a complete state management system:\n\n- **Preset States**: `selected`, `highlight`, `active`, etc.\n- **State Overlay**: Elements can have multiple states simultaneously, with styles overlaying according to priority\n- **Custom States**: Any state can be defined according to business needs\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Configure Elements\n\nG6 5.x adopts a flat configuration structure, where all element configurations are at the same level, making it easy to find and manage:\n\n```typescript\n{\n  node: {\n    // Default node style\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // Node styles in different states\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // Default edge style\n    style: {\n      stroke: '#aaa',\n    },\n    // Edge styles in different states\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // Default combo style\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\nThere are three configuration methods, in order of priority from high to low:\n\n1. **Dynamic configuration using instance methods**: such as `graph.setNode()`, `graph.setEdge()`, `graph.setCombo()`\n2. **Global configuration when instantiating the graph**: specify configuration items in `new Graph()`\n3. **Configuration in data**: set in the data objects of nodes, edges, and combos\n\nIn editors like VSCode, you can see all configurable properties of elements and search based on keywords:\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Extension Capabilities\n\nG6 provides powerful extension capabilities to meet various customization needs:\n\n- **Custom Nodes**: [Custom Node Guide](/en/manual/element/node/custom-node)\n- **Custom Edges**: [Custom Edge Guide](/en/manual/element/edge/custom-edge)\n- **Custom Combos**: [Custom Combo Guide](/en/manual/element/combo/custom-combo)\n- **React Nodes**: [Define Nodes Using React](/en/manual/element/node/react-node)\n- **3D Extension**: Use 3D nodes through `@antv/g6-extension-3d`\n\n## Built-in Element Reference\n\n### Node Types\n\n- [Built-in Node Library](/en/manual/element/node/base-node)\n\n### Edge Types\n\n- [Built-in Edge Library](/en/manual/element/edge/base-edge)\n\n### Combo Types\n\n- [Built-in Combo Library](/en/manual/element/combo/base-combo)\n","packages/site/docs/manual/element/overview.zh.md":"---\ntitle: 元素总览\norder: 1\n---\n\n## 元素体系\n\nG6 图表的核心是由三种基本元素构成：**节点(Node)**、**边(Edge)** 和 **组合(Combo)**。这些元素是构建复杂图形网络的基础单元。\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 节点 (Node)\n\n[节点](/manual/element/node/overview) 表示图中的实体或概念，如人物、地点、对象等。G6 提供了丰富的内置节点类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 还支持 [使用 React 定义节点](/manual/element/node/react-node) 或 [自定义节点](/manual/element/node/custom-node) 以满足特定需求。\n\n### 边 (Edge)\n\n[边](/manual/element/edge/overview)表示节点间的连接关系，如朋友关系、交易往来等。G6 内置多种边类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n当内置边不满足需求时，可以通过 [自定义边](/manual/element/edge/custom-edge) 来实现复杂的连接表现。\n\n### 组合 (Combo)\n\n[组合](/manual/element/combo/overview)是一种特殊元素，可以包含节点和其他组合，用于表示集合、分组或层级关系。G6 内置两种组合类型：\n\n- **圆形组合**(`circle`)：适合紧凑型分组\n- **矩形组合**(`rect`)：适合规则布局的分组\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n组合支持嵌套、拖拽、展开/收起等交互，可以通过 [自定义组合](/manual/element/combo/custom-combo) 来实现更复杂的容器行为。\n\n## 元素构成原理\n\n每个元素由一个或多个基础图形(Shape)组成。图形是 G6 中的最小图形单元，包括 [矩形](/manual/element/shape/properties#rectstyleprops)、[圆形](/manual/element/shape/properties#circlestyleprops)、[文本](/manual/element/shape/properties#textstyleprops)、[路径](/manual/element/shape/properties#pathstyleprops)等。\n\n例如：\n\n- 一个节点可能由背景图形(如圆形)和文本标签组成\n- 一条边可能由路径、箭头和文本标签组成\n- 一个组合可能由容器图形、标题文本和展开/收起按钮组成\n\n要了解更多关于图形的信息，请参阅 [图形 Shape 总览](/manual/element/shape/overview) 和 [Shape 样式属性](/manual/element/shape/properties)。\n\n## 元素状态\n\n[元素状态](/manual/element/state) 是一种强大的机制，用于展示元素在不同交互或业务场景下的视觉变化。G6 提供了一套完整的状态管理系统：\n\n- **预设状态**：`selected`(选中)、`highlight`(高亮)、`active`(激活)等\n- **状态叠加**：元素可同时拥有多个状态，样式按优先级叠加\n- **自定义状态**：可根据业务需求定义任意状态\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 配置元素\n\nG6 5.x 采用扁平化的配置结构，所有元素的配置都在同一层级，便于查找和管理：\n\n```typescript\n{\n  node: {\n    // 节点默认样式\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // 节点在不同状态下的样式\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // 边默认样式\n    style: {\n      stroke: '#aaa',\n    },\n    // 边在不同状态下的样式\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // 组合默认样式\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\n配置方式有三种，按优先级从高到低：\n\n1. **使用实例方法动态配置**：如 `graph.setNode()`、`graph.setEdge()`、`graph.setCombo()`\n2. **实例化图时全局配置**：在 `new Graph()` 时指定配置项\n3. **在数据中配置**：在节点、边、组合的数据对象中设置\n\n在 VSCode 等编辑器中，你可以看到元素的全部可配置属性，并基于关键字进行搜索：\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 扩展能力\n\nG6 提供了强大的扩展能力，满足各种自定义需求：\n\n- **自定义节点**：[自定义节点指南](/manual/element/node/custom-node)\n- **自定义边**：[自定义边指南](/manual/element/edge/custom-edge)\n- **自定义组合**：[自定义组合指南](/manual/element/combo/custom-combo)\n- **React 节点**：[使用 React 定义节点](/manual/element/node/react-node)\n- **3D 扩展**：通过 `@antv/g6-extension-3d` 使用 3D 节点\n\n## 内置元素参考\n\n### 节点类型\n\n- [内置节点库](/manual/element/node/base-node)\n\n### 边类型\n\n- [内置边库](/manual/element/edge/base-edge)\n\n### 组合类型\n\n- [内置组合库](/manual/element/combo/base-combo)\n","packages/site/docs/manual/element/shape/label-shape.en.md":"---\ntitle: Design and Implementation of Composite Shape\norder: 3\n---\n\nG6 provides a flexible Shape mechanism, allowing developers to customize various graphics and efficiently reuse them in elements such as nodes, edges, and combos. This article uses Label as an example to explain how to customize a Shape and how to apply it in elements.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 1. Customization and Encapsulation of Shape\n\n### 1. Base Class Design of Shape\n\nAll Shapes inherit from `BaseShape`, which centrally manages the lifecycle (creation, update, destruction), property parsing, animation, event binding, etc. You only need to focus on implementing the `render` method.\n\n**Core Abstraction:**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // Lifecycle management, property parsing, animation, etc...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. Hierarchical Structure of Composite Shape\n\nA node usually contains multiple child Shapes, for example:\n\n```\nNode\n├── keyShape (main shape)\n├── label (label, auxiliary information)\n│   ├── text\n│   └── rect\n├── icon\n│   ├── text\n│   └── image\n├── badge\n│   ├── text\n│   └── rect\n└── port\n│   ├── circle\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Implementation of Label Shape\n\nLabel is a typical composite Shape, consisting of text (Text) and an optional background (Rect). The implementation idea is as follows:\n\n- **Property Separation**: The style properties of Label are divided into text style and background style, which are passed to Text and Rect respectively.\n- **Smart Layout**: The background automatically adjusts its size and position based on the text content, padding, border radius, etc.\n- **Reuse upsert**: The `upsert` method is used to automatically manage the creation, update, and destruction of child Shapes.\n\n**Main code snippet of Label:**\n\n```js\nimport { Text, Rect } from '@antv/g'; // Import atomic graphics\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... Omitted style extraction methods\n}\n```\n\n- `getTextStyle` and `getBackgroundStyle` extract the style properties for text and background respectively to avoid interference.\n- The `upsert` method ensures automatic CRUD of Shapes, greatly improving reusability and robustness.\n\n### 4. Complete Custom Shape Example\n\nBelow is an example of customizing a label with special decoration, demonstrating the complete definition, registration, and usage of a Shape:\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // Main text\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // Background\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // Extra decoration: small dot on the left\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...implement getTextStyle/getBackgroundStyle\n}\n\n// Register custom Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// Define custom node\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// Register custom node\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 2. Prefix Separation of Style Properties\n\nIn G6, elements such as nodes, edges, and combos often contain multiple child Shapes (such as main shape, label, badge, port, etc.). To ensure that the style of each child Shape does not interfere with each other, G6 adopts a **prefix separation** design for style properties.\n\n### 1. Significance of Prefix Separation\n\n- **Decoupling**: Each child Shape only cares about its own style properties, avoiding style pollution.\n- **Easy Expansion**: Adding a new child Shape only requires defining a new prefix, without modifying the original logic.\n- **Intuitive Configuration**: When configuring nodes/edges/combos, users can clearly set the style of each part.\n\n### 2. Code Implementation\n\nTake Label as an example:\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` means all properties starting with `background` belong to the label background style.\n- During rendering, tools such as `subStyleProps` and `subObject` are used to automatically extract prefixed styles and pass them to the corresponding Shape.\n\n**Label background style extraction example**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...Omitted layout calculation\n  return backgroundStyle;\n}\n```\n\n**Style configuration example**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 3. Relationship between Label and keyShape\n\n- **keyShape** is the main shape of a node/edge/combo, determining interaction picking, bounding box, main style, etc.\n- **Label**, icon, badge, port, etc. usually exist as auxiliary Shapes and are not used as keyShape.\n- When customizing a node, you can specify the keyShape via `drawKeyShape` or similar methods. Label is only responsible for displaying text information and does not affect the main interaction control of the node.\n\n## 4. How to Apply Custom Shape in Elements\n\nTake nodes as an example. The node base class `BaseNode` has built-in support for multiple child Shapes (keyShape, label, icon, badge, port, halo, etc.). You only need to focus on drawing the keyShape, and other child Shapes can be automatically managed through configuration and style prefixing.\n\n### 1. Node Rendering Process\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. Draw keyShape (main shape)\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. Draw halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. Draw icon\n  this.drawIconShape(attributes, container);\n\n  // 4. Draw badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. Draw label\n  this.drawLabelShape(attributes, container);\n\n  // 6. Draw ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- The style of each child Shape is automatically extracted by prefix separation and passed to the corresponding Shape instance.\n- You can flexibly control the display and style of each child Shape through configuration options.\n\n### 2. Example of Applying Label\n\nSuppose you want to add a label with a background to a node, just configure the label-related properties in the node data:\n\n```js\n{\n  label: true,\n  labelText: 'I am a label',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`, `labelFill`, `labelFontSize`, etc. will be automatically extracted and passed to the text part of the Label.\n- `labelBackground`, `labelBackgroundFill`, `labelBackgroundRadius`, `labelPadding`, etc. will be automatically extracted and passed to the background part of the Label.\n\nYou do not need to manually manage the creation, update, or destruction of the Label. G6 will handle it automatically.\n\n## 5. Common Issues and Debugging Suggestions\n\n### 1. Why is the label style not effective?\n\n- Check whether the style property prefix is correct (such as `labelFill`, `labelBackgroundFill`).\n- Make sure the `label` configuration of the node/edge/combo is `true` and `labelText` is set.\n- Check if it is overridden by other styles.\n\n### 2. How to debug the rendering of custom Shape?\n\n- Use the browser console to view `shapeMap` and confirm whether each child Shape is created correctly.\n\n### 3. How to make Label respond to node states (such as hover, selected)?\n\n- Directly set node state styles in the graph configuration (recommended)\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- Or listen for state changes in the implementation of Label and dynamically adjust the style. You can get the current state value through data.\n\n---\n\nFor more details, it is recommended to read the source code [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts), [`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts).\n","packages/site/docs/manual/element/shape/label-shape.zh.md":"---\ntitle: 复合 Shape 的设计与实现\norder: 3\n---\n\nG6 提供了灵活的 Shape 机制，支持开发者自定义各种图形，并在节点、边、Combo 等元素中高效复用。本文将以 Label（标签）为例，讲解如何自定义 Shape、如何在元素中应用。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 一、Shape 的自定义与封装\n\n### 1. Shape 的基类设计\n\n所有 Shape 都继承自 `BaseShape`，它统一管理了 Shape 的生命周期（创建、更新、销毁）、属性解析、动画、事件绑定等。你只需关注如何实现 `render` 方法即可。\n\n**核心抽象：**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // 生命周期管理、属性解析、动画等...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. 复合 Shape 层级结构示意\n\n一个节点通常包含多个子 Shape，例如：\n\n```\n节点（Node）\n├── keyShape（主图形）\n├── label（标签，辅助信息）\n│   ├── text（文本）\n│   └── rect（背景）\n├── icon（图标）\n│   ├── text（文本）\n│   └── image（图片）\n├── badge（徽标）\n│   ├── text（文本）\n│   └── rect（背景）\n└── port（锚点）\n│   ├── circle（圆形）\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Label Shape 的实现\n\nLabel 是一个典型的复合 Shape，由文本（Text）和可选的背景（Rect）组成。其实现思路如下：\n\n- **属性分离**：Label 的样式属性分为文本样式和背景样式，分别传递给 Text 和 Rect。\n- **智能布局**：背景自动根据文本内容、内边距、圆角等动态调整尺寸和位置。\n- **复用 upsert**：通过 `upsert` 方法自动管理子 Shape 的创建、更新、销毁。\n\n**Label 主要代码片段：**\n\n```js\nimport { Text, Rect } from '@antv/g'; // 引入原子图形\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... 省略样式提取方法\n}\n```\n\n- `getTextStyle`、`getBackgroundStyle` 分别提取文本和背景的样式属性，避免相互干扰。\n- `upsert` 方法保证了 Shape 的自动增删改查，极大提升了复用性和健壮性。\n\n### 4. 完整自定义 Shape 示例\n\n下面以自定义一个带特殊装饰的标签为例，演示 Shape 的完整定义、注册与使用：\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // 主文本\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // 背景\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // 额外装饰：左侧小圆点\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...实现 getTextStyle/getBackgroundStyle\n}\n\n// 注册自定义 Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// 定义自定义节点\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// 注册自定义节点\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 二、样式属性的前缀分离\n\nG6 中节点、边、Combo 等元素往往包含多个子 Shape（如主图形、标签、徽标、锚点等）。为了让每个子 Shape 的样式互不干扰，G6 采用了**样式属性前缀分离**的设计。\n\n### 1. 前缀分离的意义\n\n- **解耦**：每个子 Shape 只关心属于自己的样式属性，避免样式污染。\n- **易扩展**：新增子 Shape 只需定义新的前缀，无需修改原有逻辑。\n- **配置直观**：用户在配置节点/边/Combo 时，可以一目了然地设置各部分样式。\n\n### 2. 代码实现\n\n以 Label 为例：\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` 表示所有以 `background` 开头的属性都属于标签背景样式。\n- 在实际渲染时，通过 `subStyleProps`、`subObject` 等工具函数，自动提取带前缀的样式，传递给对应的 Shape。\n\n**Label 背景样式提取示例**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...省略布局计算\n  return backgroundStyle;\n}\n```\n\n**样式配置示例**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 三、Label 与 keyShape 的关系\n\n- **keyShape** 是节点/边/Combo 的主图形，决定交互拾取、包围盒、主样式等。\n- **Label**、icon、badge、port 等通常作为辅助 Shape 存在，不会作为 keyShape。\n- 你可以在自定义节点时通过 `drawKeyShape` 或类似方法指定 keyShape，Label 只负责展示文本信息，不影响节点的交互主控。\n\n## 四、如何在元素中应用自定义 Shape\n\n以节点为例，节点基类 `BaseNode` 已经内置了对多种子 Shape 的支持（keyShape、label、icon、badge、port、halo 等）。你只需专注于 keyShape 的绘制，其他子 Shape 可以通过配置和样式前缀自动管理。\n\n### 1. 节点渲染流程\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. 绘制 keyShape（主图形）\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. 绘制 halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. 绘制 icon\n  this.drawIconShape(attributes, container);\n\n  // 4. 绘制 badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. 绘制 label\n  this.drawLabelShape(attributes, container);\n\n  // 6. 绘制 ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- 每个子 Shape 的样式都通过前缀分离自动提取，传递给对应的 Shape 实例。\n- 你可以通过配置项灵活控制每个子 Shape 的显示与样式。\n\n### 2. 应用 Label 的示例\n\n假设你要为节点添加带背景的标签，只需在节点数据中配置 label 相关属性：\n\n```js\n{\n  label: true,\n  labelText: '我是标签',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`、`labelFill`、`labelFontSize` 等会被自动提取并传递给 Label 的文本部分。\n- `labelBackground`、`labelBackgroundFill`、`labelBackgroundRadius`、`labelPadding` 等会被自动提取并传递给 Label 的背景部分。\n\n你无需手动管理 Label 的创建、更新、销毁，G6 会自动完成。\n\n## 五、常见问题与调试建议\n\n### 1. 为什么 label 样式没有生效？\n\n- 检查样式属性前缀是否正确（如 `labelFill`、`labelBackgroundFill`）。\n- 确认节点/边/Combo 的 `label` 配置为 `true`，且 `labelText` 已设置。\n- 检查是否被其他样式覆盖。\n\n### 2. 如何调试自定义 Shape 的渲染？\n\n- 使用浏览器控制台查看 `shapeMap`，确认各子 Shape 是否被正确创建。\n\n### 3. 如何让 Label 响应节点状态（如 hover、selected）？\n\n- 直接在图配置中设置节点状态样式（推荐）\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- 或者在 Label 的实现中监听状态变化，动态调整样式。可以通过 data 获取到当前的状态值\n\n---\n\n如需更深入了解，建议阅读源码 [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts)、[`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts)。\n","packages/site/docs/manual/element/shape/overview.en.md":"---\ntitle: Shape and KeyShape\norder: 1\n---\n\n## Shape\n\nA Shape in G6 refers to a graphical element, such as a circle, rectangle, or path. Shapes are generally associated with nodes, edges, or combos in G6. **💡 Every node/edge/combo in G6 is composed of one or more shapes. The style configuration of nodes, edges, and combos is reflected on their corresponding shapes.**\n\nFor example, in the images below: the node on the left contains a single circular shape; the node in the middle contains a circle and a text shape; the node on the right contains five circles (the blue-green main circle and four anchor points at the top, bottom, left, and right) and a text shape. Each node/edge/combo has its unique key shape (keyShape). In the examples below, the keyShape for all three nodes is the blue-green circle. The keyShape is mainly used for interaction detection and automatic style updates with [element states](/en/manual/element/state), see [keyShape](#keyshape).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> (Left) A node with only one circular shape, whose keyShape is the circle. (Middle) A node with a circle and a text shape, whose keyShape is the circle. (Right) A node with a main circle, text, and four small circles at the top, bottom, left, and right, whose keyShape is the main circle.\n\nG6 uses different combinations of shapes to design various built-in nodes/edges/combos. Built-in nodes include 'circle', 'rect', 'ellipse', ... (see [Built-in Nodes](/en/manual/element/node/base-node)); built-in edges include 'line', 'polyline', 'cubic', ... (see [Built-in Edges](/en/manual/element/edge/base-edge)); built-in combos include 'circle', 'rect', ... (see [Built-in Combos](/en/manual/element/combo/base-combo)).\n\nIn addition to using built-in nodes/edges/combos, G6 also allows users to customize nodes/edges/combos by combining shapes as needed. See [Custom Node](/en/manual/element/node/custom-node), [Custom Edge](/en/manual/element/edge/custom-edge), and [Custom Combo](/en/manual/element/combo/custom-combo) for details.\n\n## KeyShape\n\nIn G6, each node, edge, or combo consists of one or more shapes, but one of them is called the keyShape, which is the \"key graphical element\" of the item:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> The key graphical element of the node is the colored area in the image above.\n\n### Bounding Box Determination\n\n**Determines the bounding box of a node/combo**, which is used to calculate the connection point of related edges (the intersection with the edge). If the keyShape is different, the intersection calculation between the node and the edge will also differ.\n\n#### Example\n\nIn this example, a node consists of a rect shape and a circle shape with a gray stroke and transparent fill.\n\n- When the node's keyShape is the circle:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- When the node's keyShape is the rect:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape Lifecycle\n\n> If you need to [customize nodes](/en/manual/element/node/custom-node), [customize edges](/en/manual/element/edge/custom-edge), or [customize combos](/en/manual/element/combo/custom-combo), you need to understand the lifecycle of shapes. If you use built-in nodes/edges/combos, you can skip this section.\n\nThe shape lifecycle includes:\n\n- **Initial Rendering**: Draws the shape for the first time based on data and style configuration.\n- **Update**: Automatically updates the appearance of the shape when data or style changes.\n- **Operation**: Responds to interaction states (such as selected, active, hover, etc.) and dynamically adjusts the style.\n- **Destruction**: Cleans up when the shape is removed (usually managed automatically by the Graph, so users don't need to worry).\n\nWhen customizing shapes, the most common requirement is \"how to efficiently manage the creation, update, and destruction of shapes.\" For this, G6 provides a very useful method in BaseShape:\n\n### Principle and Advantages of upsert\n\nupsert is a combination of \"update\" and \"insert\", meaning \"update if exists, insert if not\". Its function can be simply understood as:\n\n- **Automatic Judgment**: You only need to describe the desired appearance of the shape. `upsert` will automatically determine whether the shape already exists. If not, it will create it; if it exists, it will update it; if it needs to be deleted, it will remove it automatically.\n- **Simplified Logic**: Developers do not need to manually manage the CRUD of shapes, avoiding duplicate code and state confusion.\n- **Improved Robustness**: Whether it's the initial rendering, data changes, or state switching, upsert ensures that the shape always stays in sync with the data and configuration.\n\n**Type Definition:**\n\n```js\n/**\n * Create, update, or delete a shape\n * @param className Shape name\n * @param Ctor Shape type\n * @param style Shape style. Pass false to delete the shape\n * @param container Container\n * @param hooks Hooks\n * @returns Shape instance\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\nYou only need to describe \"what kind of shape you want now\" without worrying about whether it is being created, updated, or deleted. upsert will handle it for you. This makes customizing and managing complex composite shapes very simple and safe.\n","packages/site/docs/manual/element/shape/overview.zh.md":"---\ntitle: 图形 Shape 与 KeyShape\norder: 1\n---\n\n## 图形 Shape\n\nShape 指 G6 中的图形、形状，可以是圆形、矩形、路径等。它一般与 G6 中的节点、边、Combo 相关。**💡 G6 中的每一种节点/边/Combo 都是由一个或多个 Shape 组合而成。节点、边、Combo 的样式配置都会被体现到对应的图形上。**\n\n例如下图（左）的节点包含了一个圆形图形；下图（中）的节点含有一个圆形和一个文本图形；下图（右）的节点中含有 5 个圆形（蓝绿色的圆和上下左右四个锚点）、一个文本图形。但每种节点/边/Combo 都会有自己的唯一关键图形 keyShape，下图中三个节点的 keyShape 都是蓝绿色的圆，keyShape 主要用于交互检测、样式随 [元素状态](/manual/element/state) 自动更新等，见 [keyShape](#keyshape)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> （左）只含有一个圆形图形的节点，keyShape 是该圆形。（中）含有圆形和文本图形的节点，keyShape 是圆形。（右）含有主要圆形、文本、上下左右四个小圆形的节点，keyShape 是圆形。\n\nG6 使用不同的 shape 组合，设计了多种内置的节点/边/ Combo 。G6 内置节点的有 'circle'， 'rect'，'ellipse'，...（详见 [内置节点](/manual/element/node/base-node)）；内置边的有 'line'，'polyline'，'cubic'，...（详见 [内置边](/manual/element/edge/base-edge)）；内置 Combo 有 'circle'，'rect'，（详见 [内置 Combo](/manual/element/combo/base-combo)）。\n\n除了使用内置的节点/边/ Combo 外，G6 还允许用户通过自己搭配和组合 shape 进行节点/边/ Combo 的自定义，详见 [自定义节点](/manual/element/node/custom-node)，[自定义边](/manual/element/edge/custom-edge)，[自定义 Combo](/manual/element/combo/custom-combo)。\n\n## KeyShape\n\n在 G6 中，每个节点、边、Combo 都由一个或多个 Shape 组成，但其中有一个 Shape 被称为 keyShape，它是该元素的“关键图形”：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> 节点的关键图形就是上图的颜色区域\n\n### 包围盒确定\n\n**确定节点 / Combo 的包围盒（Bounding Box）** ，从而计算相关边的连入点（与相关边的交点）。若 keyShape 不同，节点与边的交点计算结果不同。\n\n#### 示例  \n\n本例中的一个节点由一个 rect 图形和一个带灰色描边、填充透明的 circle 图形构成。\n\n- 当节点的 keyShape 为 circle 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- 当节点的 keyShape 为 rect 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape 的生命周期\n\n> 当用户需要 [自定义节点](/manual/element/node/custom-node)、[自定义边](/manual/element/edge/custom-edge)、[自定义 Combo](/manual/element/combo/custom-combo) 时，需要了解 Shape 的生命周期。使用内置节点/边/Combo 则可以跳过这一部分内容。\n\n从整体来看，Shape 的生命周期分为：\n\n- **初始化渲染**：首次根据数据和样式配置绘制出 Shape。\n- **更新**：当数据或样式发生变化时，自动更新 Shape 的表现。\n- **操作**：响应交互状态（如 selected、active、hover 等），动态调整样式。\n- **销毁**：Shape 被移除时的清理（通常由 Graph 自动管理，用户无需关心）。\n\n在自定义 Shape 时，最常见的需求就是“如何高效地管理 Shape 的创建、更新和销毁”。G6 为此在 BaseShape 中设计了一个非常实用的方法：\n\n### upsert 的原理与优势\n\nupsert 是“update” 和 “insert” 的合成词，意思是“有则更新，无则创建”。它的作用可以简单理解为：\n\n- **自动判断**：你只需描述希望 Shape 呈现的样子，`upsert` 会自动判断当前 Shape 是否已存在。如果不存在则创建，如果已存在则更新，如果需要删除则自动移除。\n- **简化逻辑**：开发者无需手动管理 Shape 的增删改查，避免了重复代码和状态混乱。\n- **提升健壮性**：无论是初次渲染、数据变更还是状态切换，upsert 都能保证 Shape 始终与数据和配置保持同步。\n\n**类型定义：**\n\n```js\n/**\n * 创建、更新或删除图形\n * @param className 图形名称\n * @param Ctor 图形类型\n * @param style 图形样式。若要删除图形，传入 false\n * @param container 容器\n * @param hooks 钩子函数\n * @returns 图形实例\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\n你只需要描述“我现在想要什么样的图形”，不用关心它是新建、更新还是删除，upsert 都会帮你处理好。这让自定义和管理复杂的复合 Shape 变得非常简单和安全。\n","packages/site/docs/manual/element/shape/properties.en.md":"---\ntitle: Atomic Shapes and Their Properties\norder: 2\n---\n\nElements (nodes/edges) in G6 are composed of **one or more [shapes](/en/manual/element/shape/overview)**, mainly added via `upsert` in the `render` method when customizing nodes or edges. G6 supports the following shapes:\n\n1. [Circle](#circlestyleprops)\n2. [Ellipse](#ellipsestyleprops)\n3. [Rect](#rectstyleprops)\n4. [HTML Element](#htmlstyleprops)\n5. [Image](#imagestyleprops)\n6. [Line](#linestyleprops)\n7. [Path](#pathstyleprops)\n8. [Polygon](#polygonstyleprops)\n9. [Polyline](#polylinestyleprops)\n10. [Text](#textstyleprops)\n\n## Common Properties of All Shapes\n\n### BaseShapeStyle\n\n| Property       | Description                                                                                      | Type                                     | Required |\n| -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------- | -------- |\n| x              | x coordinate                                                                                     | number                                   | ✓        |\n| y              | y coordinate                                                                                     | number                                   | ✓        |\n| width          | Width                                                                                            | number                                   | ✓        |\n| height         | Height                                                                                           | number                                   | ✓        |\n| fill           | Fill color                                                                                       | string \\| Pattern \\| null                |          |\n| stroke         | Stroke color                                                                                     | string \\| Pattern \\| null                |          |\n| opacity        | Overall opacity                                                                                  | number \\| string                         |          |\n| fillOpacity    | Fill opacity                                                                                     | number \\| string                         |          |\n| strokeOpacity  | Stroke opacity                                                                                   | number \\| string                         |          |\n| lineWidth      | Line width                                                                                       | number \\| string                         |          |\n| lineCap        | Line cap style                                                                                   | `butt` \\| `round` \\| `square`            |          |\n| lineJoin       | Line join style                                                                                  | `miter` \\| `round` \\| `bevel`            |          |\n| lineDash       | Dash array                                                                                       | number \\| string \\| (string \\| number)[] |          |\n| lineDashOffset | Dash offset                                                                                      | number                                   |          |\n| shadowBlur     | Shadow blur                                                                                      | number                                   |          |\n| shadowColor    | Shadow color                                                                                     | string                                   |          |\n| shadowOffsetX  | Shadow X offset                                                                                  | number                                   |          |\n| shadowOffsetY  | Shadow Y offset                                                                                  | number                                   |          |\n| cursor         | Mouse cursor, supports all [CSS cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) | string                                   |          |\n| zIndex         | Render z-index                                                                                   | number                                   |          |\n| visibility     | Visibility                                                                                       | `visible` \\| `hidden`                    |          |\n\n**Example:**\n\n```js\nconst shape = BaseShape.upsert(\n  // Specify the shape key, which must be unique within the same custom element type\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Common Methods of All Shapes\n\n### attr()\n\nSet or get the drawing attributes of the instance.\n\n### attr(name)\n\nGet the value of an attribute.\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\nUpdate a single drawing attribute.\n\n### attr({...})\n\nBatch update drawing attributes.\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## Circle Shape\n\n### CircleStyleProps\n\n| Property          | Description                               | Type             | Required |\n| ----------------- | ----------------------------------------- | ---------------- | -------- |\n| cx                | Center x coordinate                       | number \\| string | ✓        |\n| cy                | Center y coordinate                       | number \\| string | ✓        |\n| cz                | Center z coordinate                       | number \\| string |          |\n| r                 | Radius                                    | number \\| string | ✓        |\n| isBillboard       | Billboard mode (always faces camera)      | boolean          |          |\n| isSizeAttenuation | Size attenuation (size changes with view) | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Rect Shape\n\n### RectStyleProps\n\n| Property          | Description       | Type                         | Required |\n| ----------------- | ----------------- | ---------------------------- | -------- |\n| x                 | Rect x coordinate | number \\| string             |          |\n| y                 | Rect y coordinate | number \\| string             |          |\n| z                 | Rect z coordinate | number                       |          |\n| width             | Rect width        | number \\| string             | ✓        |\n| height            | Rect height       | number \\| string             | ✓        |\n| isBillboard       | Billboard mode    | boolean                      |          |\n| isSizeAttenuation | Size attenuation  | boolean                      |          |\n| radius            | Border radius     | number \\| string \\| number[] |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Ellipse Shape\n\n### EllipseStyleProps\n\n| Property          | Description         | Type             | Required |\n| ----------------- | ------------------- | ---------------- | -------- |\n| cx                | Center x coordinate | number \\| string | ✓        |\n| cy                | Center y coordinate | number \\| string | ✓        |\n| cz                | Center z coordinate | number \\| string |          |\n| rx                | X-axis radius       | number \\| string | ✓        |\n| ry                | Y-axis radius       | number \\| string | ✓        |\n| isBillboard       | Billboard mode      | boolean          |          |\n| isSizeAttenuation | Size attenuation    | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| Property  | Description       | Type                  | Required |\n| --------- | ----------------- | --------------------- | -------- |\n| x         | HTML x coordinate | number \\| string      |          |\n| y         | HTML y coordinate | number \\| string      |          |\n| innerHTML | HTML content      | string \\| HTMLElement | ✓        |\n| width     | HTML width        | number \\| string      |          |\n| height    | HTML height       | number \\| string      |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## Image Shape\n\n### ImageStyleProps\n\n| Property          | Description                      | Type                       | Required |\n| ----------------- | -------------------------------- | -------------------------- | -------- |\n| x                 | Image x coordinate               | number \\| string           |          |\n| y                 | Image y coordinate               | number \\| string           |          |\n| z                 | Image z coordinate               | number                     |          |\n| src               | Image source or HTMLImageElement | string \\| HTMLImageElement | ✓        |\n| width             | Image width                      | number \\| string           |          |\n| height            | Image height                     | number \\| string           |          |\n| isBillboard       | Billboard mode                   | boolean                    |          |\n| isSizeAttenuation | Size attenuation                 | boolean                    |          |\n| billboardRotation | Billboard rotation angle         | number                     |          |\n| keepAspectRatio   | Keep original aspect ratio       | boolean                    |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## Line Shape\n\n### LineStyleProps\n\n| Property          | Description         | Type                  | Required |\n| ----------------- | ------------------- | --------------------- | -------- |\n| x1                | Start x coordinate  | number                | ✓        |\n| y1                | Start y coordinate  | number                | ✓        |\n| x2                | End x coordinate    | number                | ✓        |\n| y2                | End y coordinate    | number                | ✓        |\n| z1                | Start z coordinate  | number                |          |\n| z2                | End z coordinate    | number                |          |\n| isBillboard       | Billboard mode      | boolean               |          |\n| isSizeAttenuation | Size attenuation    | boolean               |          |\n| markerStart       | Marker at start     | DisplayObject \\| null |          |\n| markerEnd         | Marker at end       | DisplayObject \\| null |          |\n| markerStartOffset | Start marker offset | number                |          |\n| markerEndOffset   | End marker offset   | number                |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Path Shape\n\n### PathStyleProps\n\n| Property          | Description          | Type                   | Required |\n| ----------------- | -------------------- | ---------------------- | -------- |\n| d                 | Path string or array | string \\| PathArray    | ✓        |\n| markerStart       | Marker at start      | DisplayObject \\| null  |          |\n| markerEnd         | Marker at end        | DisplayObject \\| null  |          |\n| markerMid         | Marker at middle     | DisplayObject \\| null  |          |\n| markerStartOffset | Start marker offset  | number                 |          |\n| markerEndOffset   | End marker offset    | number                 |          |\n| isBillboard       | Billboard mode       | boolean                |          |\n| isSizeAttenuation | Size attenuation     | boolean                |          |\n| fillRule          | Fill rule            | `nonzero` \\| `evenodd` |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Polygon Shape\n\n### PolygonStyleProps\n\n| Property          | Description             | Type                                             | Required |\n| ----------------- | ----------------------- | ------------------------------------------------ | -------- |\n| points            | Array of polygon points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start         | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end           | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle        | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset     | number                                           |          |\n| markerEndOffset   | End marker offset       | number                                           |          |\n| isClosed          | Is polygon closed       | boolean                                          |          |\n| isBillboard       | Billboard mode          | boolean                                          |          |\n| isSizeAttenuation | Size attenuation        | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Polyline Shape\n\n### PolylineStyleProps\n\n| Property          | Description              | Type                                             | Required |\n| ----------------- | ------------------------ | ------------------------------------------------ | -------- |\n| points            | Array of polyline points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start          | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end            | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle         | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset      | number                                           |          |\n| markerEndOffset   | End marker offset        | number                                           |          |\n| isBillboard       | Billboard mode           | boolean                                          |          |\n| isSizeAttenuation | Size attenuation         | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Text\n\n### TextStyleProps\n\n| Property            | Description              | Type                                                                        | Required |\n| ------------------- | ------------------------ | --------------------------------------------------------------------------- | -------- |\n| x                   | Text x coordinate        | number \\| string                                                            |          |\n| y                   | Text y coordinate        | number \\| string                                                            |          |\n| z                   | Text z coordinate        | number \\| string                                                            |          |\n| text                | Text content             | number \\| string                                                            | ✓        |\n| fontSize            | Font size                | number \\| string                                                            |          |\n| fontFamily          | Font family              | string                                                                      |          |\n| fontStyle           | Font style               | `normal` \\| `italic` \\| `oblique`                                           |          |\n| fontWeight          | Font weight              | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |          |\n| fontVariant         | Font variant             | `normal` \\| `small-caps` \\| string                                          |          |\n| textAlign           | Text horizontal align    | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |          |\n| textBaseline        | Text baseline            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |          |\n| textOverflow        | Text overflow            | `clip` \\| `ellipsis` \\| string                                              |          |\n| lineHeight          | Line height              | number \\| string                                                            |          |\n| letterSpacing       | Letter spacing           | number \\| string                                                            |          |\n| maxLines            | Max lines                | number                                                                      |          |\n| textPath            | Text path                | Path                                                                        |          |\n| textPathSide        | Text path side           | `left` \\| `right`                                                           |          |\n| textPathStartOffset | Text path start offset   | number \\| string                                                            |          |\n| textDecorationLine  | Text decoration line     | string                                                                      |          |\n| textDecorationColor | Text decoration color    | string                                                                      |          |\n| textDecorationStyle | Text decoration style    | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |          |\n| isBillboard         | Billboard mode           | boolean                                                                     |          |\n| billboardRotation   | Billboard rotation angle | number                                                                      |          |\n| isSizeAttenuation   | Size attenuation         | boolean                                                                     |          |\n| wordWrap            | Word wrap                | boolean                                                                     |          |\n| wordWrapWidth       | Word wrap width          | number                                                                      |          |\n| dx                  | X offset                 | number \\| string                                                            |          |\n| dy                  | Y offset                 | number \\| string                                                            |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n**Display in multiply line:**\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","packages/site/docs/manual/element/shape/properties.zh.md":"---\ntitle: 原子 Shape 以及其属性\norder: 2\n---\n\nG6 中的元素（节点/边）是由**一个或多个 [图形 Shape](/manual/element/shape/overview)** 组成，主要通过自定义节点或自定义边时在 `render` 方法中使用 `upsert` 添加，G6 中支持以下的图形 Shape：\n\n1. [Circle - 圆形](#circlestyleprops)\n2. [Ellipse - 椭圆](#ellipsestyleprops)\n3. [Rect - 矩形](#rectstyleprops)\n4. [HTML - HTML元素](#htmlstyleprops)\n5. [Image - 图片](#imagestyleprops)\n6. [Line - 线](#linestyleprops)\n7. [Path - 路径](#pathstyleprops)\n8. [Polygon - 多边形](#polygonstyleprops)\n9. [Polyline - 折线](#polylinestyleprops)\n10. [Text - 文本](#textstyleprops)\n\n## 各图形 Shape 的通用属性\n\n### BaseShapeStyle\n\n| 属性           | 描述                                                                                          | 类型                                     | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------- | ---- |\n| x              | x 坐标                                                                                        | number                                   | ✓    |\n| y              | y 坐标                                                                                        | number                                   | ✓    |\n| width          | 宽度                                                                                          | number                                   | ✓    |\n| height         | 高度                                                                                          | number                                   | ✓    |\n| fill           | 填充颜色                                                                                      | string \\| Pattern \\| null                |      |\n| stroke         | 描边颜色                                                                                      | string \\| Pattern \\| null                |      |\n| opacity        | 整体透明度                                                                                    | number \\| string                         |      |\n| fillOpacity    | 填充透明度                                                                                    | number \\| string                         |      |\n| strokeOpacity  | 描边透明度                                                                                    | number \\| string                         |      |\n| lineWidth      | 线宽度                                                                                        | number \\| string                         |      |\n| lineCap        | 线段端点样式                                                                                  | `butt` \\| `round` \\| `square`            |      |\n| lineJoin       | 线段连接处样式                                                                                | `miter` \\| `round` \\| `bevel`            |      |\n| lineDash       | 虚线配置                                                                                      | number \\| string \\| (string \\| number)[] |      |\n| lineDashOffset | 虚线偏移量                                                                                    | number                                   |      |\n| shadowBlur     | 阴影模糊程度                                                                                  | number                                   |      |\n| shadowColor    | 阴影颜色                                                                                      | string                                   |      |\n| shadowOffsetX  | 阴影 X 方向偏移                                                                               | number                                   |      |\n| shadowOffsetY  | 阴影 Y 方向偏移                                                                               | number                                   |      |\n| cursor         | 鼠标样式，[CSS 的 cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) 选项都支持 | string                                   |      |\n| zIndex         | 渲染层级                                                                                      | number                                   |      |\n| visibility     | 可见性                                                                                        | `visible` \\| `hidden`                    |      |\n\n**示例：**\n\n```js\nconst shape = BaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 各图形 Shape 的通用方法\n\n### attr()\n\n设置或获取实例的绘图属性。\n\n### attr(name)\n\n获取实例的属性值。\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\n更新实例的单个绘图属性。\n\n### attr({...})\n\n批量更新实例绘图属性。\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## 圆图形 Circle\n\n### CircleStyleProps\n\n| 属性              | 描述                               | 类型             | 必选 |\n| ----------------- | ---------------------------------- | ---------------- | ---- |\n| cx                | 圆心 x 坐标                        | number \\| string | ✓    |\n| cy                | 圆心 y 坐标                        | number \\| string | ✓    |\n| cz                | 圆心 z 坐标                        | number \\| string |      |\n| r                 | 圆的半径                           | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式（始终面向相机） | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减（随视距变化大小） | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 矩形图形 Rect\n\n### RectStyleProps\n\n| 属性              | 描述               | 类型                         | 必选 |\n| ----------------- | ------------------ | ---------------------------- | ---- |\n| x                 | 矩形 x 坐标        | number \\| string             |      |\n| y                 | 矩形 y 坐标        | number \\| string             |      |\n| z                 | 矩形 z 坐标        | number                       |      |\n| width             | 矩形宽度           | number \\| string             | ✓    |\n| height            | 矩形高度           | number \\| string             | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean                      |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                      |      |\n| radius            | 矩形圆角半径       | number \\| string \\| number[] |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 椭圆图形 Ellipse\n\n### EllipseStyleProps\n\n| 属性              | 描述               | 类型             | 必选 |\n| ----------------- | ------------------ | ---------------- | ---- |\n| cx                | 椭圆中心 x 坐标    | number \\| string | ✓    |\n| cy                | 椭圆中心 y 坐标    | number \\| string | ✓    |\n| cz                | 椭圆中心 z 坐标    | number \\| string |      |\n| rx                | 椭圆 x 轴半径      | number \\| string | ✓    |\n| ry                | 椭圆 y 轴半径      | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| 属性      | 描述             | 类型                  | 必选 |\n| --------- | ---------------- | --------------------- | ---- |\n| x         | HTML 元素 x 坐标 | number \\| string      |      |\n| y         | HTML 元素 y 坐标 | number \\| string      |      |\n| innerHTML | HTML 内容        | string \\| HTMLElement | ✓    |\n| width     | HTML 元素宽度    | number \\| string      |      |\n| height    | HTML 元素高度    | number \\| string      |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## 图片图形 Image\n\n### ImageStyleProps\n\n| 属性              | 描述                         | 类型                       | 必选 |\n| ----------------- | ---------------------------- | -------------------------- | ---- |\n| x                 | 图片 x 坐标                  | number \\| string           |      |\n| y                 | 图片 y 坐标                  | number \\| string           |      |\n| z                 | 图片 z 坐标                  | number                     |      |\n| src               | 图片资源路径或 HTML 图片元素 | string \\| HTMLImageElement | ✓    |\n| width             | 图片宽度                     | number \\| string           |      |\n| height            | 图片高度                     | number \\| string           |      |\n| isBillboard       | 是否启用公告牌模式           | boolean                    |      |\n| isSizeAttenuation | 是否启用大小衰减             | boolean                    |      |\n| billboardRotation | 公告牌模式下的旋转角度       | number                     |      |\n| keepAspectRatio   | 是否保持图片原有宽高比       | boolean                    |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## 直线 Line\n\n### LineStyleProps\n\n| 属性              | 描述               | 类型                  | 必选 |\n| ----------------- | ------------------ | --------------------- | ---- |\n| x1                | 线段起点 x 坐标    | number                | ✓    |\n| y1                | 线段起点 y 坐标    | number                | ✓    |\n| x2                | 线段终点 x 坐标    | number                | ✓    |\n| y2                | 线段终点 y 坐标    | number                | ✓    |\n| z1                | 线段起点 z 坐标    | number                |      |\n| z2                | 线段终点 z 坐标    | number                |      |\n| isBillboard       | 是否启用公告牌模式 | boolean               |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean               |      |\n| markerStart       | 线段起点的标记     | DisplayObject \\| null |      |\n| markerEnd         | 线段终点的标记     | DisplayObject \\| null |      |\n| markerStartOffset | 起点标记的偏移量   | number                |      |\n| markerEndOffset   | 终点标记的偏移量   | number                |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 路径 Path\n\n### PathStyleProps\n\n| 属性              | 描述                 | 类型                   | 必选 |\n| ----------------- | -------------------- | ---------------------- | ---- |\n| d                 | 路径定义字符串或数组 | string \\| PathArray    | ✓    |\n| markerStart       | 路径起点的标记       | DisplayObject \\| null  |      |\n| markerEnd         | 路径终点的标记       | DisplayObject \\| null  |      |\n| markerMid         | 路径中间点的标记     | DisplayObject \\| null  |      |\n| markerStartOffset | 起点标记的偏移量     | number                 |      |\n| markerEndOffset   | 终点标记的偏移量     | number                 |      |\n| isBillboard       | 是否启用公告牌模式   | boolean                |      |\n| isSizeAttenuation | 是否启用大小衰减     | boolean                |      |\n| fillRule          | 填充规则             | `nonzero` \\| `evenodd` |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 多边形图形 Polygon\n\n### PolygonStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 多边形的顶点数组   | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 多边形起点的标记   | DisplayObject \\| null                            |      |\n| markerEnd         | 多边形终点的标记   | DisplayObject \\| null                            |      |\n| markerMid         | 多边形中间点的标记 | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isClosed          | 是否闭合多边形     | boolean                                          |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 折线 Polyline\n\n### PolylineStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 折线的顶点数组     | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 折线起点的标记     | DisplayObject \\| null                            |      |\n| markerEnd         | 折线终点的标记     | DisplayObject \\| null                            |      |\n| markerMid         | 折线中间点的标记   | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 文字 Text\n\n### TextStyleProps\n\n| 属性                | 描述               | 类型                                                                        | 必选 |\n| ------------------- | ------------------ | --------------------------------------------------------------------------- | ---- |\n| x                   | 文本 x 坐标        | number \\| string                                                            |      |\n| y                   | 文本 y 坐标        | number \\| string                                                            |      |\n| z                   | 文本 z 坐标        | number \\| string                                                            |      |\n| text                | 文本内容           | number \\| string                                                            | ✓    |\n| fontSize            | 字体大小           | number \\| string                                                            |      |\n| fontFamily          | 字体族             | string                                                                      |      |\n| fontStyle           | 字体样式           | `normal` \\| `italic` \\| `oblique`                                           |      |\n| fontWeight          | 字体粗细           | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |      |\n| fontVariant         | 字体变种           | `normal` \\| `small-caps` \\| string                                          |      |\n| textAlign           | 文本水平对齐方式   | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |      |\n| textBaseline        | 文本基线           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |      |\n| textOverflow        | 文本溢出处理方式   | `clip` \\| `ellipsis` \\| string                                              |      |\n| lineHeight          | 行高               | number \\| string                                                            |      |\n| letterSpacing       | 字间距             | number \\| string                                                            |      |\n| maxLines            | 最大行数           | number                                                                      |      |\n| textPath            | 文本路径           | Path                                                                        |      |\n| textPathSide        | 文本路径侧边       | `left` \\| `right`                                                           |      |\n| textPathStartOffset | 文本路径起始偏移   | number \\| string                                                            |      |\n| textDecorationLine  | 文本装饰线         | string                                                                      |      |\n| textDecorationColor | 文本装饰线颜色     | string                                                                      |      |\n| textDecorationStyle | 文本装饰线样式     | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |      |\n| isBillboard         | 是否启用公告牌模式 | boolean                                                                     |      |\n| billboardRotation   | 公告牌旋转角度     | number                                                                      |      |\n| isSizeAttenuation   | 是否启用大小衰减   | boolean                                                                     |      |\n| wordWrap            | 是否自动换行       | boolean                                                                     |      |\n| wordWrapWidth       | 自动换行宽度       | number                                                                      |      |\n| dx                  | X 方向偏移         | number \\| string                                                            |      |\n| dy                  | Y 方向偏移         | number \\| string                                                            |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n多行文字显示：\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","packages/site/docs/manual/element/state.en.md":"---\ntitle: Element State\norder: 2\n---\n\n## What is Element State\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\nElement State refers to the visual representation of elements (nodes, edges, combos) in a graph under different interaction scenarios. For example, when a user clicks on a node, the node might enter a \"selected\" state and change color; when the mouse hovers over an edge, the edge might enter a \"highlight\" state and become bold.\n\n**Simply put, states allow elements to dynamically change their appearance based on user operations or business logic.**\n\n### Characteristics of States\n\n- **Multiple State Coexistence**: An element can have multiple states simultaneously, such as being both \"selected\" and \"highlighted\"\n- **Style Stacking**: Styles from multiple states are stacked together, with later-set state styles having higher priority\n- **Complete Customization**: Besides built-in states, you can create any custom states that meet your business requirements\n\n## Built-in State Types\n\nG6 provides some commonly used built-in states that you can use directly:\n\n| State Name  | Description     | Typical Use Cases                    |\n| ----------- | --------------- | ------------------------------------ |\n| `selected`  | Selected state  | When user clicks to select elements  |\n| `active`    | Active state    | Currently interacting element        |\n| `highlight` | Highlight state | Elements that need emphasis          |\n| `inactive`  | Inactive state  | Dimmed display of unfocused elements |\n| `disabled`   | Disabled state  | Non-interactive elements             |\n\n> 💡 **Tip**: These built-in states are not mandatory. You can completely define your own state names according to business requirements.\n\n## Configuring State Styles\n\n### Basic Configuration\n\nConfigure corresponding styles for different states when creating a graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Node state style configuration\n  node: {\n    // Default style (style when no state is applied)\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // Styles for various states\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // Edge state style configuration\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // Combo state style configuration\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### Custom States\n\nYou can create any custom states that meet your business requirements:\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // Custom state: error\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // Dashed border\n      },\n      // Custom state: success\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // Custom state: warning\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // Add icon\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## Setting Element States\n\n### Setting Initial States in Data\n\nSet initial states for elements in data:\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // Initially in selected state\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // Initially in disabled state\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // Initially has multiple states\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // Initial state of the edge\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### Dynamic State Setting\n\nDynamically change element states through API:\n\n```javascript\n// Set a single state for a single element\ngraph.setElementState('node1', 'selected');\n\n// Set multiple states for a single element\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// Batch set states for multiple elements\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### State Stacking Effect\n\nWhen an element has multiple states, styles are stacked in order:\n\n```javascript\n// Assume a node has both selected and highlight states\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// Final style = default style + selected state style + highlight state style\n// If there are style conflicts, later state styles will override earlier ones\n```\n\n## Clearing Element States\n\n### Clear All States\n\nRestore elements to default state (no states):\n\n```javascript\n// Clear all states of a single element\ngraph.setElementState('node1', []);\n\n// Batch clear states of multiple elements\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### Clear Specific States\n\nIf an element has multiple states, you can clear only some of them:\n\n```javascript\n// Assume node1 currently has ['selected', 'highlight', 'active'] three states\n// Now only want to keep 'selected' state, clear other states\ngraph.setElementState('node1', ['selected']);\n\n// Or get current states, then filter out unwanted states\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### Clear Specific States from All Elements\n\n```javascript\n// Clear 'highlight' state from all nodes\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## Querying Element States\n\n### Get Element States\n\n```javascript\n// Get all states of a specified element\nconst states = graph.getElementState('node1');\nconsole.log(states); // For example: ['selected', 'highlight']\n\n// If element has no states, returns empty array\nconsole.log(states); // []\n```\n\n### Find Elements with Specific States\n\n```javascript\n// Get all node data in 'selected' state\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// Get all edge data in 'highlight' state\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### Check if Element is in Specific State\n\n```javascript\n// Check if element is in specific state\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('Is node selected:', isSelected);\nconsole.log('Is node highlighted:', isHighlight);\n```\n","packages/site/docs/manual/element/state.zh.md":"---\ntitle: 元素状态\norder: 2\n---\n\n## 什么是元素状态\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n元素状态(State)是指图中元素（节点、边、组合）在不同交互场景下的视觉表现形式。比如当用户点击一个节点时，节点可能会变成\"选中\"状态并改变颜色；当鼠标悬停在边上时，边可能会进入\"高亮\"状态并加粗显示。\n\n**简单来说，状态让元素能够根据用户的操作或业务逻辑动态改变外观。**\n\n### 状态的特点\n\n- **多状态共存**：一个元素可以同时拥有多个状态，比如既是\"选中\"又是\"高亮\"\n- **样式叠加**：多个状态的样式会叠加在一起，后设置的状态样式优先级更高\n- **完全自定义**：除了内置状态，您可以创建任何符合业务需求的自定义状态\n\n## 内置状态类型\n\nG6 提供了一些常用的内置状态，您可以直接使用：\n\n| 状态名      | 说明       | 典型使用场景       |\n| ----------- | ---------- | ------------------ |\n| `selected`  | 选中状态   | 用户点击选择元素时 |\n| `active`    | 激活状态   | 当前正在交互的元素 |\n| `highlight` | 高亮状态   | 需要强调显示的元素 |\n| `inactive`  | 非活跃状态 | 淡化显示非关注元素 |\n| `disabled`   | 禁用状态   | 不可交互的元素     |\n\n> 💡 **提示**：这些内置状态并非必须使用，您完全可以根据业务需求定义自己的状态名称。\n\n## 配置状态样式\n\n### 基础配置\n\n在创建图实例时，为不同状态配置相应的样式：\n\n```javascript\nconst graph = new Graph({\n  // 节点的状态样式配置\n  node: {\n    // 默认样式（无状态时的样式）\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // 各种状态下的样式\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // 边的状态样式配置\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // 组合的状态样式配置\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### 自定义状态\n\n您可以创建任何符合业务需求的自定义状态：\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // 自定义状态：错误\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // 虚线边框\n      },\n      // 自定义状态：成功\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // 自定义状态：警告\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // 添加图标\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## 设置元素状态\n\n### 数据中设置初始状态\n\n在数据中为元素设置初始状态：\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // 初始为选中状态\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // 初始为禁用状态\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // 初始有多个状态\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // 边的初始状态\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### 动态设置状态\n\n通过 API 动态改变元素状态：\n\n```javascript\n// 设置单个元素的单个状态\ngraph.setElementState('node1', 'selected');\n\n// 设置单个元素的多个状态\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// 批量设置多个元素的状态\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### 状态的叠加效果\n\n当元素有多个状态时，样式会按顺序叠加：\n\n```javascript\n// 假设节点同时有 selected 和 highlight 状态\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// 最终样式 = 默认样式 + selected状态样式 + highlight状态样式\n// 如果有样式冲突，后面的状态样式会覆盖前面的\n```\n\n## 清除元素状态\n\n### 清除所有状态\n\n将元素恢复到默认状态（无任何状态）：\n\n```javascript\n// 清除单个元素的所有状态\ngraph.setElementState('node1', []);\n\n// 批量清除多个元素的状态\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### 清除特定状态\n\n如果元素有多个状态，您可以只清除其中的某些状态：\n\n```javascript\n// 假设 node1 当前有 ['selected', 'highlight', 'active'] 三个状态\n// 现在只想保留 'selected' 状态，清除其他状态\ngraph.setElementState('node1', ['selected']);\n\n// 或者获取当前状态，然后过滤掉不需要的状态\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### 清除所有元素的特定状态\n\n```javascript\n// 清除所有节点的 'highlight' 状态\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## 查询元素状态\n\n### 获取元素状态\n\n```javascript\n// 获取指定元素的所有状态\nconst states = graph.getElementState('node1');\nconsole.log(states); // 例如：['selected', 'highlight']\n\n// 如果元素没有任何状态，返回空数组\nconsole.log(states); // []\n```\n\n### 查找特定状态的元素\n\n```javascript\n// 获取所有处于 'selected' 状态的节点数据\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// 获取所有处于 'highlight' 状态的边数据\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### 判断元素是否处于某状态\n\n```javascript\n// 检查元素是否处于特定状态\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('节点是否选中:', isSelected);\nconsole.log('节点是否高亮:', isHighlight);\n```\n","packages/site/docs/manual/extension/3d.en.md":"---\ntitle: g6-extension-3d\n---\n","packages/site/docs/manual/extension/3d.zh.md":"---\ntitle: g6-extension-3d\n---\n","packages/site/docs/manual/faq.en.md":"---\ntitle: FAQ\norder: 13\n---\n\n### What is the Difference Between Extension and Plugin?\n\n`Extension` is a concept in G6 that collectively refers to all types of registrable content, including elements, behaviors, layouts, and plugins, among others.\n\n`Plugin` represents a flexible extension mechanism provided by G6 and is a special type of `Extension`.\n\n### Set Text Overflow Ellipsis\n\nTaking `label` as an example, you can set `labelWordWrap` and `labelWordWrapWidth` to achieve text overflow ellipsis.\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### Key Press Not Working\n\nSome plugins or behaviors support configuring key press triggers. Please use standard key names, such as `Control`, `Shift`, `Alt`, `Meta`, as well as letters, numbers, symbols, and so on.\n\n### Canvas Not Updating After Data Update\n\nEnsure that you call `graph.draw()` or `graph.render()` to update the canvas after updating the data.\n\n> G6 merges differences and updates the canvas uniformly after `draw` or `render` for multiple data updates to improve performance.\n\n### How to Resolve Interaction Conflicts\n\nWhen multiple interactions conflict with each other, you can set the enable timing of interactions to avoid multiple interactions being triggered simultaneously.\n\nTaking `drag-canvas` and `brush-select` as an example, if you directly configure these two interactions, dragging on the canvas will cause interaction exceptions. You can disable the `drag-canvas` interaction when the `shift` key is pressed.\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\nAt this point, when the `shift` key is pressed, the `drag-canvas` interaction will be disabled, and the `brush-select` interaction will not be affected.\n\n### Difference Between `draw` and `render`\n\nBoth `draw` and `render` execute drawing operations, but `render` additionally performs **layout** and **auto fit** operations based on `draw`.\n\nYou can simply understand it as: `render` = `draw` + `layout` + `fitView`/`fitCenter`.\n\n### Style in Data Not Effective\n\nReason 1: The style in the data is overridden by the style in the style mapping.\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // No matter what the style in the data is, it will be overridden by the style here\n    }\n  }\n}\n```\n\nSolution: Use a callback method to prioritize obtaining styles from the data to improve data priority.\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### Residual content in the canvas\n\nWhen using the Canvas renderer for drawing, residual content may appear in the canvas, which is referred to as \"dirty rectangles\". This phenomenon occurs because the underlying rendering engine improves performance by only drawing the parts that have changed each time, rather than clearing the entire canvas.\n\nHowever, when the graphics in the canvas change, there may be cases where some graphics are not correctly cleared, resulting in residual content.\n\nYou can solve this issue by:\n\n1. Using the SVG or WebGL renderer;\n2. Checking whether there are illegal values in the element of the nodes, such as null, NaN, and so on;\n3. Using integers as much as possible for numeric style values, such as r, width, height, fontSize, and so on.\n\n### Use Vanilla JavaScript Object Data\n\nPlease avoid using Vue reactive data, Immer.js, and other wrapped objects as the data source for G6, as these objects will be deeply monitored internally, and even freeze the data object, causing G6 to fail to operate normally.\n\n### G6 project startup Warning during compilation Type mapping points to non-existent path\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> Explanation: [@antv/util](https://github.com/antvis/util) is a tool library that AntV relies on at the bottom.\n\nFrom the partial warning message above, we can see that there is a problem with the type declaration file of the `@antv/util` tool library that G6 depends on.**This warning does not affect the normal operation of the project**.\n\nThis message will only appear in TypeScript projects. The following are ways to turn it off:\n\n1. Turn off TypeScript sourcemap\n\nCreate a `.env` file in the root directory of the project and add the following content:\n\ntext\nGENERATE_SOURCEMAP=false\ntext\n\n2. Disable sourcemapping for specific modules\n\nDisabling sourcemapping directly is too simple and crude, and is not user-friendly for developers who may have debugging needs. Therefore, sourcemapping can be disabled for specific modules by configuring the build tool separately.\n\na. webpack configuration\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite configuration\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // Ignore warnings for specific modules\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // For other warnings, use the default warning handling\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### Manually configuring the color palette does not take effect\n\n> In v5, the built-in colors are: export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\nThe solution is as follows:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line plugin does not take effect\n\n> In v5, built-in plugins include `bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [Detailed reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\nActual reason: The parent container of the `graph` instance, `<div ref={containerRef} />`, does not have a height set, so the G6 Graph may not be able to calculate the correct size.**If you want to enable the `grid-line` canvas plugin, you need to set the width and height of the parent element, which is not valid in the graph configuration**.\n\n### v5 cannot use the tree layout\n\nUse `new Graph({xxx})` uniformly.\n\n> In v5, built-in layouts include `antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [Specific reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5 merges the graph and tree graph, no longer creates the tree graph layout by instantiating `G6.TreeGraph`, and removes this method. For details, see [Features - Merge Graph and Tree Graph](https://g6.antv.antgroup.com/manual/feature#-%E5%90%88%E5%B9%B6%E5%9B%BE%E4%B8%8E%E6%A0%91%E5%9B%BE)\n\n### edge does not have a connection at the center of the node\n\nis configured [portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter) to `true`.\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### How to dynamically set the width of a node based on the length of the label content\n\nImplementation solution: [#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent node event object type is not complete\n\nYou can manually specify the `IPointerEvent` type. For details, see [#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### Remove the parent combo of the node\n\nUpdate the node data, set the `combo` value to `null`.\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","packages/site/docs/manual/faq.zh.md":"---\ntitle: 常见问题\norder: 13\n---\n\n### Extension 和 Plugin 有什么区别？\n\n`Extension` 是 G6 中的一个概念，是所有可注册内容的统称，包含元素、交互、布局、插件等。\n\n`Plugin` 是 G6 提供的灵活扩展机制，是一种特殊的 `Extension`。\n\n### 设置文本超出省略\n\n以 label 为例，设置 `labelWordWrap` 和 `labelWordWrapWidth` 即可实现文本超出省略。\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### 按键不生效\n\n一些插件或交互支持配置触发按键，请使用标准按键名：如 `Control`, `Shift`, `Alt`, `Meta`，以及字母、数字、符号等。\n\n### 更新数据后画布不更新\n\n请确保数据更新后调用 `graph.draw()` 或者 `graph.render()` 更新画布。\n\n> G6 对于多次数据更新，会在 `draw` 或 `render` 后合并差异并统一更新画布，以提高性能。\n\n### 交互有冲突如何解决\n\n当多个交互之间存在冲突时，你可以设置交互的启用时机来避免多个交互被同时触发。\n\n以 `drag-canvas` 和 `brush-select` 为例，如果直接配置这两个交互，当指针在画布上进行拖拽时，会导致交互异常。可以设置为在按下 `shift` 键时禁用 `drag-canvas` 交互。\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\n此时，当按下 `shift` 键时，`drag-canvas` 交互会被禁用，`brush-select` 交互会不会受到影响。\n\n### draw 和 render 的区别\n\n`draw` 和 `render` 都会执行绘制操作，但 `render` 会在 `draw` 的基础上额外进行**布局**、**视图自适应**操作。\n\n可以简单理解为：`render` = `draw` + `layout` + `fitView`/`fitCenter`。\n\n### 数据中的样式不生效\n\n原因一：被样式映射中的样式覆盖\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // 无论数据中的样式如何，都会被这里的样式覆盖\n    }\n  }\n}\n```\n\n解决方式：使用回调方法，优先从数据中获取样式以提高数据优先级\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### 画布中出现残影\n\n在使用 Canvas 渲染器进行绘制时，可能会出现残影现象，这些图形被称为“脏矩形”。该现象出现的原因是底层渲染引擎为了提高性能，每次绘制时只会绘制发生变化的部分，而不会清空整个画布。\n\n但是，当画布中的图形发生变化时，可能会出现部分图形未被正确清除的情况，从而导致残影现象。\n\n可以通过以下方式解决：\n\n1. 使用 SVG 或 WebGL 渲染器；\n2. 检查节点中的图形样式中是否存在非法值，例如 null、NaN 等；\n3. 尽量使用整数作为数值型的样式值，例如 r、width、height、fontSize 等；\n\n### 使用原生 JavaScript 对象数据\n\n请避免使用 Vue 响应式数据、Immer.js 等包装过的对象作为 G6 的数据源，因为这些对象会在内部进行深度监听，甚至冻结数据对象，导致 G6 无法正常操作数据。\n\n### G6 项目启动在编译时警告类型映射指向不存在路径\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> 解释: [@antv/util](https://github.com/antvis/util) 是 AntV 底层依赖的工具库。\n\n从上面部分警告信息中我们可以得知是 G6 依赖的 `@antv/util` 工具库的类型声明文件存在问题，**该警告不影响项目正常运行**。\n\n该信息只会在 TypeScript 项目中出现，关闭办法如下:\n\n1. 关闭TypeScript 的sourcemap源码映射\n\n在项目根目录下创建`.env`文件，并添加以下内容:\n\n```text\nGENERATE_SOURCEMAP=false\n```\n\n2. 单独禁用指定模块的源码映射\n\n直接禁用sourcemap映射的方式过于简单粗暴，对于部分可能有调试需求的开发者不太友好，所以也可以通过在构建工具单独配置，单独禁用这些特定模块的源码映射。\n\na. webpack配置\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite配置\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // 忽略特定模块的警告\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // 对于其他警告,使用默认的警告处理\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### 手动配置色板颜色不生效\n\n> 在 v5 中内置颜色有：export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\n解决办法如下:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line 插件不生效\n\n> 在 v5 中内置插件有`bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\n实际原因: `graph`实例的父容器`<div ref={containerRef} />`本身没有设置高度，G6 Graph图 可能无法正确计算出合适的大小。**如果要启用`grid-line`画布插件，需要给父元素 div 设置宽高，在 graph 配置中是无效的**。\n\n### v5无法使用树图布局\n\n统一使用`new Graph({xxx})`。\n\n> 在 v5 中内置布局有`antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5合并了图和树图，不再通过实例化`G6.TreeGraph`创建树图布局，并且移除该方式。具体参考[特性-合并图与树图](/manual/whats-new/feature#🌲-合并图与树图)\n\n### edge 没有连接在 node 的边缘中心\n\n配置[portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter)为 `true`。\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### 如何根据label内容长度动态设置node宽度\n\n参考方案：[#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent节点事件对象类型不齐全问题\n\n可以手动指定`IPointerEvent`类型。具体参考[#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### 解除节点所在组合\n\n更新节点数据，`combo` 值设置为 `null`。\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","packages/site/docs/manual/further-reading/3d.en.md":"---\ntitle: Use 3D\norder: 5\n---\n\n## Install Dependencies\n\nBefore using 3D capabilities, please install the 3D extension package first:\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\nThe extension package exports the following:\n\n- renderer: 3D renderer\n\n**Elements**\n\n- Capsule: capsule node\n- Cone: cone node\n- Cube: cube node\n- Cylinder: cylinder node\n- Sphere: sphere node\n- Torus: torus node\n- Line3D: 3D line\n\n**Layout**\n\n- D3Force3DLayout: 3D force-directed layout\n\n**Behaviors**\n\n- DragCanvas3D: drag canvas\n- ObserveCanvas3D: observe canvas\n- RollCanvas3D: rotate canvas\n- ZoomCanvas3D: zoom canvas\n\n**Plugin**\n\n- Light: light source\n\n## Register Extensions\n\nThe following extensions are required:\n\n- renderer\n- at least one 3D node\n- Line3D\n- Light\n\n> The renderer does not need to be registered, it can be passed in during the instantiation of Graph.\n\nRegister as follows:\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## Create 3D Graph\n\nAfter completing the above steps, you can create a 3D graph:\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... other options\n  // use 3d renderer\n  renderer,\n  node: {\n    type: 'sphere', // use 3d node\n    style: {\n      materialType: 'phong', // use Phong material\n    },\n  },\n  edge: {\n    type: 'line3d', // use 3D edge\n  },\n  plugins: [\n    {\n      type: 'light', // Add light source\n      // configure directional light\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\nYou can also refer to:\n\n- [Lite Solar System](/examples/feature/default/#lite-solar-system)\n- [3D Force Layout](/examples/layout/force-directed/#3d-force)\n\n## Tips\n\n`@antv/g6` has a built-in registered plugin for CameraSetting for camera configuration, refer to [plugin](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts).\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","packages/site/docs/manual/further-reading/3d.zh.md":"---\ntitle: 使用 3D\norder: 5\n---\n\n## 安装依赖\n\n在使用 3D 能力之前，请首先安装 3D 扩展包：\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\n该扩展包导出了以下内容：\n\n- renderer：3D 渲染器\n\n**元素**\n\n- Capsule：胶囊节点\n- Cone：圆锥节点\n- Cube：立方体节点\n- Cylinder：圆柱节点\n- Sphere：球体节点\n- Torus：圆环节点\n- Line3D：3D 线\n\n**布局**\n\n- D3Force3DLayout：3D 力导向布局\n\n**交互**\n\n- DragCanvas3D：拖拽画布\n- ObserveCanvas3D：观察画布\n- RollCanvas3D：旋转画布\n- ZoomCanvas3D：缩放画布\n\n**插件**\n\n- Light：光源\n\n## 注册扩展\n\n其中下列扩展是必须的：\n\n- renderer\n- 至少一个 3D 节点\n- Line3D\n- Light\n\n> renderer 无需注册，实例化 Graph 过程中传入即可。\n\n使用如下方式进行注册：\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## 创建 3D 图\n\n完成上述步骤后，即可创建 3D 图：\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 3D 渲染器\n  renderer,\n  node: {\n    type: 'sphere', // 使用 3D 节点\n    style: {\n      materialType: 'phong', // 使用 Phong 材质\n    },\n  },\n  edge: {\n    type: 'line3d', // 使用 3D 边\n  },\n  plugins: [\n    {\n      type: 'light', // 添加光源\n      // 配置方向光\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n你可以参考以下示例：\n\n- [精简太阳系](/examples/feature/default/#lite-solar-system)\n- [3D 力导向布局](/examples/layout/force-directed/#3d-force)\n\n## 其他\n\n`@antv/g6` 中内置注册了 `CameraSetting` 插件，可用于配置相机，具体可参考[插件](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts)。\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","packages/site/docs/manual/further-reading/bundle.en.md":"---\ntitle: Bundle Project\norder: 6\n---\n\nIn general, if you are using modern build tools such as Webpack, Rollup, or ESBuild, you can easily build projects that depend on `@antv/g6`.\n\nSome build tools, such as Vite, use ESBuild as the underlying tool, so you can refer to ESBuild's configuration.\n\nBelow are some example configurations that you can refer to when building your project. If you find that these configurations do not work properly, make sure that your build tool version is up to date.\n\n## Bundle Project with Webpack\n\n1. Make sure that `webpack` and `webpack-cli` are installed in your project:\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. Refer to the following `webpack.config.js` for configuration:\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx webpack\n```\n\n> The above configuration works with `\"webpack\": \"^5.94.0\"`, `\"webpack-cli\": \"^5.1.4\"`.\n\n:::error{title=Webpack4}\n⚠️ It is strongly recommended that projects use Webpack 5. If you are using Webpack 4, follow the steps below to configure:\n\n1. Install the necessary dependencies: `babel-loader` (<9), `@babel/preset-env`, `@open-wc/webpack-import-meta-loader`\n\n> If you are using TypeScript, you also need to install `ts-loader`.\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. Modify the `webpack.config.js` configuration:\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> This configuration is for a standard webpack project. If you are using vue-cli, you should REMOVE the `mode: 'production'` option as it is unnecessary.\n\n## Bundle Project with Rollup\n\n1. First, make sure that `rollup` and the necessary plugins are installed in your project:\n\n- `@rollup/plugin-commonjs`: Used to load CommonJS modules\n- `@rollup/plugin-node-resolve`: Used to load Node.js modules\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. Refer to the following `rollup.config.js` for configuration:\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx rollup -c\n```\n\n## Bundle Project with ESBuild\n\n1. First, make sure that `esbuild` is installed in your project:\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. Run the build command:\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","packages/site/docs/manual/further-reading/bundle.zh.md":"---\ntitle: 项目打包\norder: 6\n---\n\n通常情况下，如果你使用的现代构建工具，如 Webpack、Rollup 或 ESBuild，你可以很容易地构建依赖于 `@antv/g6` 的项目。\n\n一些构建工具例如 Vite，其底层是使用 ESBuild，因此你可以参考 ESBuild 的配置。\n\n下面是一些示例配置，你可以参考这些配置来构建你的项目。如果你发现这些配置无法正常工作，请确保你的构建工具版本较新。\n\n## 使用 Webpack 打包项目\n\n1. 确保你的项目中已经安装了 `webpack` 和 `webpack-cli`：\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. 参考下面的 `webpack.config.js` 进行配置：\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx webpack\n```\n\n> 上述配置在：\"webpack\": \"^5.94.0\"，\"webpack-cli\": \"^5.1.4\" 可以正常工作。\n\n:::error{title=Webpack4}\n⚠️ 强烈建议项目使用 Webpack 5，如果你使用的是 Webpack 4，按以下步骤配置：\n\n1. 安装相关依赖：babel-loader(<9)、@babel/preset-env、@open-wc/webpack-import-meta-loader\n\n> 如果你使用的 typescript，还需要安装 ts-loader\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. 修改 `webpack.config.js` 配置：\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> 如果你使用的是 vue-cli，请移除 mode: 'production' 配置，否则可能会影响开发模式下的构建性能。\n\n## 使用 Rollup 打包项目\n\n1. 首先，确保你的项目中已经安装了 `rollup` 及必要的插件：\n\n- `@rollup/plugin-commonjs`：用于加载 CommonJS 模块\n- `@rollup/plugin-node-resolve`：用于加载 Node.js 模块\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. 参考下面的 `rollup.config.js` 进行配置：\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx rollup -c\n```\n\n## 使用 ESBuild 打包项目\n\n1. 首先，确保你的项目中已经安装了 `esbuild`：\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. 执行构建命令：\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","packages/site/docs/manual/further-reading/coordinate.en.md":"---\ntitle: coordinate\norder: 2\n---\n\n## Overview\n\nThere are three coordinate systems in G6 5.0: Canvas, Viewport, and Client.\n\n### Canvas Coordinate System\n\nThe coordinate system used when drawing G6 elements is not affected by camera zooming or panning. To change the position of an element, you need to directly modify the element's position properties (x/y/z).\n\nThe canvas space is theoretically infinite. In the initial state (no panning, zoom ratio is 1), the origin of the canvas coordinate system is located at the upper-left corner of the viewport.\n\n### Viewport Coordinate System\n\nThe viewport coordinate system is the projection of the camera coordinate system. When the camera pans or zooms, the position of elements in the canvas will also change in the viewport coordinate system.\n\nThe size of the viewport is the size of the canvas DOM container. The origin of the viewport coordinate system is located at the upper-left corner of the viewport, with the x-axis pointing to the right and the y-axis pointing down.\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### Client Coordinate System\n\nThe client coordinate system has the browser's upper-left corner as the origin, with the x-axis pointing to the right and the y-axis pointing down.\n\nThe following figure describes the relationship between the viewport coordinate system and the client coordinate system:\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Coordinate System Conversion\n\nG6 provides methods for coordinate system conversion, making it easy to convert between different coordinate systems.\n\n- Canvas coordinate system to viewport coordinate system: [getViewportByCanvas](/en/api/coordinate#graphgetviewportbycanvaspoint)\n- Client coordinate system to canvas coordinate system: [getCanvasByClient](/en/api/coordinate#graphgetcanvasbyclientpoint)\n- Viewport coordinate system to canvas coordinate system: [getCanvasByViewport](/en/api/coordinate#graphgetcanvasbyviewportpoint)\n- Canvas coordinate system to client coordinate system: [getClientByCanvas](/en/api/coordinate#graphgetclientbycanvaspoint)\n\nOther related APIs are also provided:\n\n- Get the viewport center in viewport coordinates: [getCanvasCenter](/en/api/viewport#graphgetcanvascenter)\n- Get the viewport center in canvas coordinates: [getViewportCenter](/en/api/viewport#graphgetviewportcenter)\n- Get the position of the graph origin in the viewport coordinate system: [getPosition](/en/api/viewport#graphgetposition)\n","packages/site/docs/manual/further-reading/coordinate.zh.md":"---\ntitle: 坐标系\norder: 2\n---\n\n## 概述\n\n在 G6 5.0 中主要会涉及三个坐标系：画布坐标系(Canvas)、视口坐标系(Viewport)和浏览器坐标系(Client)。\n\n### 画布坐标系\n\nG6 元素绘制时所使用的坐标系，其不受相机缩放、平移的影响，要改变一个元素的位置，需要直接修改元素的位置属性(x/y/z)。\n\n画布空间理论上是无限大的，在初始状态下（无平移、缩放倍率为1），画布坐标系的原点位于视口左上角位置。\n\n### 视口坐标系\n\n视口坐标系是相机坐标系的投影，当相机发生平移、缩放时，画布中元素位置在视口坐标系中的位置也会发生变化。\n\n视口的大小即画布 DOM 容器的大小，视口坐标系的原点位于视口左上角位置，x 轴正方向向右，y 轴正方向向下。\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### 浏览器坐标系\n\n浏览器坐标系以浏览器左上角为原点，x 轴正方向向右，y 轴正方向向下。\n\n下图描述了视口坐标系和浏览器坐标系之间的关系：\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 坐标系转换\n\nG6 提供了坐标系转换的方法，可以方便地在不同坐标系之间进行转换。\n\n- 画布坐标系转视口坐标系：[getViewportByCanvas](/api/coordinate#graphgetviewportbycanvaspoint)\n- 浏览器坐标系转画布坐标系：[getCanvasByClient](/api/coordinate#graphgetcanvasbyclientpoint)\n- 视口坐标系转画布坐标系：[getCanvasByViewport](/api/coordinate#graphgetcanvasbyviewportpoint)\n- 画布坐标系转浏览器坐标系：[getClientByCanvas](/api/coordinate#graphgetclientbycanvaspoint)\n\n另外还提供了其他相关 API：\n\n- 获取视口中心的视口坐标：[getCanvasCenter](/api/viewport#graphgetcanvascenter)\n- 获取视口中心的画布坐标：[getViewportCenter](/api/viewport#graphgetviewportcenter)\n- 获取图原点在视口坐标系中的位置：[getPosition](/api/viewport#graphgetposition)\n","packages/site/docs/manual/further-reading/download-image.en.md":"---\ntitle: download-image\norder: 3\n---\n\nG6 5.0 only provides an API for exporting the canvas as a Base64 image ([toDataURL](/en/api/export-image#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=note}\nThe exported image may not contain the complete canvas content; the export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., and this content will not appear in the exported image.\n:::\n","packages/site/docs/manual/further-reading/download-image.zh.md":"---\ntitle: 下载图片\norder: 3\n---\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](/api/export-image#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","packages/site/docs/manual/further-reading/event.en.md":"---\ntitle: Event\norder: 0\n---\n\n## Overview\n\nThe event system in G6 is encapsulated based on the event system of [G](https://g.antv.antgroup.com/en/api/event/intro), providing a wider range of event types and more convenient methods for event binding and unbinding.\n\n## Event Types\n\nThe event types in G6 are mainly divided into the following categories:\n\n1. Graph events\n2. Canvas events\n3. Element events\n\n### Graph Events\n\nGraph events refer to events associated with the entire graph instance, such as the graph's rendering completion event, the graph's update event, etc. The complete list of graph events can be found at [GraphEvent](/en/api/event#graph-lifecycle-events-graphevent).\n\n#### Listening to Graph Events\n\nListening to graph events is consistent with the default event listening method. For example, to listen to the graph's rendering completion event:\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### Canvas Events\n\nCanvas events refer to events associated with the canvas, such as the canvas's click event, the canvas's drag event, etc. The complete list of canvas events can be found at [CanvasEvent](/en/api/event#canvas-events-canvasevent).\n\n#### Listening to Canvas Events\n\nFor example, to listen to the canvas's click event:\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### Element Events\n\nElement events primarily refer to events that are triggered on element objects, such as a node's drag event, an edge's click event, etc. Elements are categorized into three types: nodes (`node`), edges (`edge`), and combos (`combo`). The complete list of corresponding events can be found at: [NodeEvent](/en/api/event#node-events-nodeevent), [EdgeEvent](/en/api/event#edge-events-edgeevent), [ComboEvent](/en/api/event#combo-events-comboevent).\n\n#### Listening to Element Events\n\nSimilar to canvas events, for example, to listen to a node's drag event and an edge's click event:\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## Event Listening and Unlistening\n\nG6 provides the following APIs for event listening and unlistening:\n\n### on\n\nAdd an event listener\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\nRemove an event listener\n\n```typescript\ngraph.off('event_name', handler);\n```\n\nWhen no arguments are passed, it will remove all event listeners:\n\n```typescript\ngraph.off();\n```\n\n### once\n\nAdd a one-time event listener, which means the event listener will be automatically removed after the event is triggered\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\nIf you want to manually trigger an event, you can use the `emit` method:\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","packages/site/docs/manual/further-reading/event.zh.md":"---\ntitle: 事件\norder: 0\n---\n\n## 概述\n\nG6 中的事件系统是在 [G](https://g.antv.antgroup.com/api/event/intro) 的事件系统基础上进行了封装，提供了更多的事件类型，以及更加方便的事件绑定和解绑方法。\n\n## 事件类型\n\nG6 中的事件类型主要分为以下几类：\n\n1. 图(Graph)事件\n2. 画布(Canvas)事件\n3. 元素(Element)事件\n\n### 图事件\n\n图事件是指与整个图实例相关的事件，例如图的渲染完成事件、图的更新事件等。图事件的完整列表见[GraphEvent](/api/event#图表生命周期事件-graphevent)。\n\n#### 监听图事件\n\n图事件的监听与默认的事件监听方式一致，例如监听图的渲染完成事件：\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### 画布事件\n\n画布事件是指与画布相关的事件，例如画布的点击事件、画布的拖拽事件等。画布事件的完整列表见[CanvasEvent](/api/event#画布事件-canvasevent)。\n\n#### 监听画布事件\n\n例如监听画布的点击事件：\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### 元素事件\n\n元素事件主要指在元素对象上触发的事件，例如节点的拖拽事件、边的点击事件等。元素分为节点(`node`)、边(`edge`)、组合(`combo`)三类，对应的事件完整列表分别见：[NodeEvent](/api/event#节点事件-nodeevent) 、[EdgeEvent](/api/event#边事件-edgeevent)、[ComboEvent](/api/event#combo事件-comboevent)。\n\n#### 监听元素事件\n\n与画布事件类似，例如监听节点的拖拽和边的点击事件：\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## 事件监听与解除\n\nG6 提供以下 API 用于事件监听和解除：\n\n### on\n\n添加事件监听\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\n移除事件监听\n\n```typescript\ngraph.off('event_name', handler);\n```\n\n当不传入任何参数时，会移除所有事件监听：\n\n```typescript\ngraph.off();\n```\n\n### once\n\n添加一次性事件监听，即事件触发后会自动移除事件监听\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\n如果你想手动触发一个事件，可以使用 `emit` 方法：\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","packages/site/docs/manual/further-reading/iconfont.en.md":"---\ntitle: Using Iconfont\norder: 4\n---\n\n## Overview\n\nWhy use iconfont? It offers great compatibility, a wide variety of icons, and multicolor options. For more details, please visit the [Alibaba Iconfont Platform](https://www.iconfont.cn).\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## Usage\n\n### Download Font Icons\n\nFirst, you need to download the desired font icons from the [iconfont](https://www.iconfont.cn) website. Create a project, select the required icons, and then download the generated icon files.\n\n### Add Font Icons\n\nAfter downloading, place the directory containing the icon font files (typically including `.eot`, `.woff`, `.ttf`, and `.svg` files, as well as the `iconfont.css` stylesheet) into your project.\n\nYou can choose how to include them. Below is an example of how to include them in HTML:\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### Using the Font\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // Corresponds to the `font-family` value in iconfont.css\n      iconText: '\\ue7f1', // Corresponds to the `content` value in iconfont.css, make sure to add `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### Utility Function `getIcon()`\n\nTo make it easier to retrieve icons, you can create a utility function `getIcon`. This function reads the icon information from the `iconfont.json` file and returns the corresponding Unicode character. Note that manually concatenating Unicode (`\\\\u${icon.unicode}`) won't work. Refer to [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) for details.\n\nFirst, ensure you have an `iconfont.json` file containing the detailed icon information.\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\nUse it in your project:\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","packages/site/docs/manual/further-reading/iconfont.zh.md":"---\ntitle: 使用 iconfont\norder: 4\n---\n\n## 概述\n\n为什么使用 iconfont？ 兼容性好、种类多、多色等。在此不做过多介绍，请直接移步 [阿里巴巴-iconfont 平台](https://www.iconfont.cn)。\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## 使用\n\n### 下载字体图标\n\n首先，你需要从 [iconfont](https://www.iconfont.cn) 网站下载所需的图标字体。创建一个项目并选择所需的图标，然后下载生成的图标文件。\n\n### 添加字体图标\n\n下载完成后，将包含图标字体文件的目录（通常包括 `.eot`、`.woff`、`.ttf` 和 `.svg` 文件，以及 `iconfont.css` 样式文件）放入你的项目中。\n\n引入方式可自行选择，下面为在 HTML 中引入的例子：\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### 使用字体\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // 对应 iconfont.css 中的 `font-family` 属性值\n      iconText: '\\ue7f1', // 对应 iconfont.css 中的 `content` 属性值，注意加 `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### 工具函数 `getIcon()`\n\n为了更方便地获取图标，可以创建一个工具函数 `getIcon`。该函数会从图标文件 `iconfont.json` 中读取图标信息并返回相应的 Unicode 字符。这里注意，手动拼接 unicode 是不行的（`\\\\u${icon.unicode}`）。详细参考 [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)。\n\n首先，确保你有一个 `iconfont.json` 文件，包含图标的详细信息。\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type: string) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\n在项目中使用：\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","packages/site/docs/manual/further-reading/renderer.en.md":"---\ntitle: renderer\norder: 1\n---\n\nG6 uses Canvas as the default renderer, but also supports rendering with SVG and WebGL. To switch to the SVG or WebGL renderer, simply pass the `renderer` parameter during initialization.\n\n## Using the SVG Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the SVG renderer here\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## Using the WebGL Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the WebGL renderer here\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## Using Different Renderers for Different Layers\n\nG6 uses layered canvases for rendering, so `renderer` is a callback function that takes the canvas type as a parameter and returns the renderer instance. If you want to use different renderers on different canvases, you can configure it like this:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // The main canvas uses the WebGL renderer, and the other canvases use the SVG renderer\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## Switch Renderers Dynamically\n\nG6 does not provide a API to switch the renderer, but you can still update the `renderer` option through the `setOptions` method.\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// Use the WebGL renderer by default\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// Switch to the SVG renderer\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","packages/site/docs/manual/further-reading/renderer.zh.md":"---\ntitle: 渲染器\norder: 1\n---\n\nG6 默认使用 Canvas 作为渲染器，但也支持通过 SVG 和 WebGL 进行渲染，要切换到 SVG 或 WebGL 渲染器，只需在初始化时传入 `renderer` 参数即可。\n\n## 使用 SVG 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 SVG 渲染器\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## 使用 WebGL 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 WebGL 渲染器\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## 分层使用不同的渲染器\n\nG6 采用了分层画布进行渲染，因此 `renderer` 是一个回调函数，参数是画布类型，返回渲染器实例，如果你想在不同的画布上使用不同的渲染器，可以这样配置：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // 主画布使用 WebGL 渲染器，其他画布使用 SVG 渲染器\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## 动态切换渲染器\n\nG6 没有提供单独的 API 来切换渲染器，但你仍可以通过 `setOptions` 方法来更新 `renderer` 参数：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// 初始化时使用 WebGL 渲染器\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// 切换到 SVG 渲染器\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","packages/site/docs/manual/getting-started/installation.en.md":"---\ntitle: Installation\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\nImport G6 in the code:\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\nVisit [G6 npm Example](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) to view the complete example code.\n\n## CDN\n\n`@antv/g6` Available on multiple CDNs:\n\n- unpkg: https://unpkg.com/@antv/g6@5/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\nImport G6 using a `script` tag:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\nVisit [G6 CDN Example](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) to view the complete example code.\n","packages/site/docs/manual/getting-started/installation.zh.md":"---\ntitle: 安装\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\n在代码中引入 G6：\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\n访问 [G6 npm 示例](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) 查看完整示例代码。\n\n## CDN\n\n`@antv/g6` 在多个 CDN 上提供：\n\n- unpkg: https://unpkg.com/@antv/g6@latest/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\n使用 `script` 标签引入 G6：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n访问 [G6 CDN 示例](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) 查看完整示例代码。\n","packages/site/docs/manual/getting-started/integration/angular.en.md":"---\ntitle: angular\norder: 2\n---\n\nRefer to the example below, you can use G6 in Angular, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/angular.zh.md":"---\ntitle: 在 Angular 中使用\norder: 2\n---\n\n参考下面的示例，你可以在 Angular 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/react.en.md":"---\ntitle: react\norder: 0\n---\n\n## Non-Strict Mode\n\nRefer to the example below, you can use G6 in React, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## Strict Mode\n\nIn strict mode, React intentionally mounts, unmounts, and remounts components in development. Create the Graph instance inside an effect, keep it in a ref, and destroy it in the cleanup callback so the first development-only mount does not leave a stale graph behind. The following complete example also shows how to register and render a React node.\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","packages/site/docs/manual/getting-started/integration/react.zh.md":"---\ntitle: 在 React 中使用\norder: 0\n---\n\n:::info{title=建议}\n如果你需要更完善的 React 与 G6 集成解决方案，可以使用 AntV 官方封装库 [`@antv/graphin`](https://github.com/antvis/graphin)。\n:::\n\n## 非严格模式\n\n参考下面的示例，你可以在 React 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## 严格模式\n\n在严格模式下，React 会在开发环境中有意执行挂载、卸载、再挂载。请把 Graph 实例放在 effect 里创建，用 ref 保存，并在清理函数中销毁，这样第一次开发态挂载不会留下旧实例。下面的完整示例同时演示了如何注册和渲染 React 节点。\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","packages/site/docs/manual/getting-started/integration/vue.en.md":"---\ntitle: vue\norder: 1\n---\n\n:::warning\nPlease do not pass Vue reactive data directly to the G6 instance, which may cause G6 to fail to render correctly, or even cause the page to crash.\n:::\n\nRefer to the example below, you can use G6 in Vue, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/vue.zh.md":"---\ntitle: 在 Vue 中使用\norder: 1\n---\n\n:::warning{title=注意}\n请不要将 Vue 响应式数据直接传递给 G6 实例，这可能会导致 G6 无法正确渲染，甚至导致页面崩溃。\n:::\n\n参考下面的示例，你可以在 Vue 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","packages/site/docs/manual/getting-started/quick-start.en.md":"---\ntitle: Quick Start\norder: 0\n---\n\n## Online Experience with G6\n\nVisit [Chart Examples](/en/examples) to experience G6 online without any environment setup.\n\n## Creating a Simple Graph\n\nIn this example, we will create a simple graph using G6 based on an HTML page.\n\nCopy the following code into an HTML file and then open this file in a browser:\n\n```html\n<!-- Prepare a container -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- Import G6's JS file -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\nYou will get a graph as shown below:\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\nLet's analyze the following code snippet:\n\n1. First, we create a `div` element to serve as the container for the graph:\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. Then, include the G6's JS file:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. Use the `fetch` method to obtain the graph's data:\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. Finally, create an instance of the graph, pass in the configuration object, and call the `render` method to render the graph:\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\nIf you are using frameworks such as React, Vue, Angular, etc., you can refer to:\n\n- [Using G6 in React](./integration/react)\n- [Using G6 in Vue](./integration/vue)\n- [Using G6 in Angular](./integration/angular)\n","packages/site/docs/manual/getting-started/quick-start.zh.md":"---\ntitle: 快速开始\norder: 0\n---\n\n## 在线体验 G6\n\n访问 [图表示例](/examples) 无需任何环境配置即可在线体验 G6。\n\n## 创建一个简单的图\n\n在本例子中，我们将基于 HTML 页面使用 G6 创建一个简单的图。\n\n将下面的代码复制到一个 HTML 文件中，然后在浏览器中打开这个文件：\n\n```html\n<!-- 准备一个容器 -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- 引入 G6 的 JS 文件 -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\n会得到如下所示的图：\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\n下面分析一下这段代码：\n\n1. 首先我们创建一个 `div` 元素作为图的容器：\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. 然后引入 G6 的 JS 文件：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. 使用 `fetch` 方法获取图的数据：\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. 最后创建一个图实例，传入配置对象，并调用 `render` 方法渲染图：\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n如果你使用 React、Vue、Angular 等框架，可以查看：\n\n- [在 React 中使用 G6](./integration/react)\n- [在 Vue 中使用 G6](./integration/vue)\n- [在 Angular 中使用 G6](./integration/angular)\n","packages/site/docs/manual/getting-started/step-by-step.en.md":"---\ntitle: Step-by-step guide\norder: 3\n---\n\nThis tutorial will guide you through the development of a G6 chart from scratch, and along the way, you will learn and understand the main concepts of G6.\n\n## Create Application\n\nWe will use Vite to create a simple front-end application.\n\n### Initialization\n\nFirst, create an empty directory:\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\nInitialize the project:\n\n```bash\nnpm init -y\n```\n\nInstall G6:\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite is a new type of front-end build tool that is based on ESModule and can quickly start up projects.\n\nInstall Vite:\n\n```bash\nnpm install vite --save-dev\n```\n\nAdd a start script to the `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### Create Files\n\nCreate the `index.html` and `main.ts` files with the following content:\n\n**index.html**:\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### Start project\n\n```bash\nnpm run dev\n```\n\nOpen a web browser and visit the address output in the terminal (typically: http://127.0.0.1:5173/), and you will see a pop-up displaying \"Hello, G6!\".\n\n## Creating a Simple Graph\n\nNext, we will create a simple chart using G6.\n\n### Preparing the Data\n\nG6 uses JSON-formatted data to describe the graph, which usually includes nodes and edges. We will use the following prepared data:\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\nThe data includes two nodes and one edge. The `id` attribute for nodes is mandatory, and the position of each node is set in the `style`. The `source` and `target` attributes of the edge represent the `id` of the starting node and the ending node, respectively.\n\n### Creating and Drawing the Graph\n\nCreate an instance of the Graph, pass in a configuration object that includes the container and data, and then call the `render` method to draw the Graph:\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\nAs shown below, you can see that the chart has been successfully drawn:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### Element\n\nNext, we will introduce how to configure the style and types of elements in the canvas.\n\nG6 provides various mechanisms to configure element styles, which can be done in the data itself or within the chart instance. In the previous example, we configured the position of the nodes in the data. Next, we will configure the styles of nodes and edges in the graph configuration options:\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\nAs the code shows, we have configured the fill color of the nodes to be pink and the stroke color of the edges to be light green within the chart instance. You can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\nThe key parts are the `node.style` and `edge.style` options, which are used to configure the styles of nodes and edges, respectively.\n\n> In the subsequent code examples, we will only display the parts of the options. For the complete code of this project, please refer to the [Complete Example](https://codesandbox.io/s/g6-tutorial).\n\nNext, we will demonstrate more types of nodes by setting the node type:\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\nIn the code above, we set the `type` attribute of the node, which can be a string or a function. When `type` is a function, the argument of the function is the current node's data object, and the return value is the type of the node.\n\n> Similarly, each attribute under the `style` style of an element can also be a function, with the argument being the current element's data object.\n\n> You can even set the entire `style` property as a function, allowing you to dynamically set the element's style based on the data object.\n\nThe circular node (`circle`) is the default node type in G6. Here, we set the type of the first node to a circle and the type of the second node to a rectangle.\n\nAt the same time, we also set the size of the nodes to 20, so the first node is a circle with a radius of 10, and the second node is a square with a side length of 20.\n\n> If you want to set the size of the rectangular node to 20x10, you can set `size` to an array `[20, 10]`.\n\nYou can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### Behaviors\n\nThe chart provided in the previous example is static. Next, we will add some interactive behaviors.\n\nG6 offers a variety of interactive behaviors. We will add a few commonly used Behaviors to allow users to drag, zoom the canvas, and drag nodes.\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\nTry dragging nodes and the canvas in the example below, and use the scroll wheel to zoom in and out on the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### Layout\n\nIn the previous example, we manually set the positions of the nodes. However, this can become very difficult when there are many nodes.\n\nLayout algorithms can automatically adjust the positions of nodes based on certain rules. G6 provides a variety of layout algorithms, such as tree layout, force-directed layout, and so on.\n\nFirst, generate a set of data that does not include position information:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nBy default, if a node does not have position information, G6 will place the node at the top-left corner, that is, at the coordinates `(0, 0)`.\n\nNext, we will use the `d3-force` layout algorithm, which is a force-directed layout algorithm that can simulate the forces of attraction and repulsion between nodes, allowing the nodes to automatically adjust to suitable positions.\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\nView the example below, and you can see that the nodes have automatically adjusted to suitable positions:\n\n<details>\n<summary>Complete Code</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### Palette\n\nSimilarly, when there are many nodes, manually setting the color of each node can become difficult. G6 provides a palette mechanism that makes it easy to assign colors to elements.\n\nPalettes typically assign colors to elements based on a specific field in the data, such as the type of node, the weight of an edge, etc.\n\nBelow, we add a `category` field in the data:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nThen, use the `tableau` palette to set the colors for the nodes, where the `field` attribute specifies the field in the data, and the `color` attribute specifies the name of the palette.\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> It is important to note that the `fill` style in `node.style` should be removed, as its priority is higher than the colors assigned by the palette.\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### Plugins\n\nThe plugin mechanism is an important feature of G6, which allows you to extend the functionality of G6 through plugins. G6 provides a wealth of built-in plugins, such as `tooltip`, `legend`, etc., and also supports user-defined plugins.\n\nBelow, we will use the `grid-line` plugin to add grid lines to the canvas:\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\nYou can see that grid lines have been added to the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\nThe plugin configuration mentioned above used a shorthand form. Most plugins support the passing of additional parameters. For example, the `grid-line` plugin allows you to configure the `follow` property to specify whether the grid lines should follow the canvas when it is dragged.\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\nTry dragging the canvas in the example below, and you will see that the grid lines move along with the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## Summary\n\nIn this tutorial, we created a G6 chart from scratch and became acquainted with the main concepts of G6. We learned how to create a simple chart, how to configure the style and types of elements, how to add interactive behaviors, how to use layout algorithms, how to use palettes, and how to use plugins.\n\nFor a more detailed introduction to the concepts of G6, you can refer to [Core Concepts](/en/manual/graph/graph).\n\nDetailed explanations of options such as elements, layouts, and plugins can be found in the [API](/en/api/data).\n","packages/site/docs/manual/getting-started/step-by-step.zh.md":"---\ntitle: 详细教程\norder: 3\n---\n\n本教程将引导你从头开始完成一个 G6 图表开发，并在过程中了解和学习 G6 的主要概念。\n\n## 创建应用\n\n我们将使用 Vite 来创建一个简单的前端应用。\n\n### 初始化\n\n首先创建一个空目录：\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\n初始化项目：\n\n```bash\nnpm init -y\n```\n\n安装 G6：\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite 是一个新型的前端构建工具，它基于 ESModule，可以快速启动项目。\n\n安装 Vite：\n\n```bash\nnpm install vite --save-dev\n```\n\n在 `package.json` 中添加启动脚本：\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### 创建文件\n\n创建 `index.html` 和 `main.ts` 文件，内容如下：\n\n**index.html**：\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### 启动项目\n\n```bash\nnpm run dev\n```\n\n打开浏览器访问终端中输出的地址（通常为：http://127.0.0.1:5173/ ），你将看到一个弹窗显示 \"Hello, G6!\"。\n\n## 创建一个简单的图表\n\n接下来，我们将使用 G6 创建一个简单的图表。\n\n### 准备数据\n\nG6 使用 JSON 格式的数据来描述图，通常包括节点和边。我们将使用下面准备的数据：\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\n数据中包括两个节点和一条边，节点的 `id` 属性是必须的，并在 `style` 设置了每个节点的位置。边的 `source` 和 `target` 属性分别表示边的起始节点 `id` 和结束节点 `id`。\n\n### 创建并绘制图表\n\n创建一个图表实例，传入一个配置对象，包括容器和数据，然后调用 `render` 方法渲染图表：\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\n如下所示，可以看到图表已经顺利绘制出来：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### 元素\n\n接下来将介绍如何配置画布中的元素样式和种类。\n\nG6 提供了多种机制来配置元素样式，可以在数据中进行配置，也可以在图表实例中进行配置。前面的示例中，我们在数据中配置了节点的位置，接下来我们在图配置项中配置节点和边的样式：\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\n正如代码所示，我们在图表实例中配置了节点的填充颜色为粉色，边的描边颜色为浅绿色。你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\n其中的关键部分是 `node.style` 和 `edge.style` 配置项，分别用来配置节点和边的样式。\n\n> 在后续的代码示例中，我们仅展示配置项的部分代码，本项目的完整代码请查看 [完整示例](https://codesandbox.io/s/g6-tutorial)。\n\n下面我们将通过设置节点的类型来展示更多的节点种类：\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\n上面的代码中，我们设置了节点的 `type` 属性，其值可以是一个字符串，也可以是一个函数。当 `type` 是一个函数时，函数的参数是当前节点的数据对象，函数的返回值是节点的类型。\n\n> 同样的，元素中 `style` 样式下的每个属性都可以是一个函数，函数的参数是当前元素的数据对象。\n\n> 你甚至可以将整个 `style` 属性设置为一个函数，这样你可以根据数据对象动态设置元素的样式。\n\n圆形节点(`circle`)是 G6 的默认节点类型，这里我们将第一个节点的类型设置为圆形，第二个节点的类型设置为矩形。\n\n同时我们还将节点的大小设置为 20，因此第一个节点是一个半径为 10 的圆形，第二个节点是一个边长为 20 的正方形。\n\n> 如果你想将矩形节点的大小设置为 20x10，可以将 `size` 设置为一个数组 `[20, 10]`。\n\n你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### 交互\n\n在上面的例子中提供的图表是静态的，接下来我们将添加一些交互行为。\n\nG6 提供了多种交互行为，我们添加几个常用的交互，使得用户可以拖拽、缩放画布，拖拽节点。\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\n尝试在下面的示例中拖拽节点和画布，并使用滚轮缩放画布：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### 布局\n\n在上面的示例中，我们手动设置了节点的位置。但当节点数量较多时，这会变得非常困难。\n\n布局算法可以基于一定的规则自动调整节点的位置，G6 提供了多种布局算法，例如树形布局、力导向布局等。\n\n首先生成一组不包括位置信息的数据：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n默认情况下，如果节点没有位置信息，G6 会将节点放置在左上角，即 `(0, 0)`。\n\n接下来我们使用 `d3-force` 布局算法，它是一种力导向布局算法，可以模拟节点之间的引力和斥力，使得节点自动调整到合适的位置。\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\n查看下面的示例，可以看到节点已经自动调整到合适的位置：\n\n<details>\n<summary>完整代码</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### 色板\n\n同样的，当节点数量较多时，手动设置节点的颜色也会变得困难。G6 提供了色板机制，可以便捷地为元素设置颜色。\n\n色板通常会基于数据的某个字段为元素设置颜色，例如节点的类型、边的权重等。\n\n下面我们在数据中的添加 `category` 字段：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n然后使用 `tableau` 色板为节点设置颜色，`field` 属性指定了数据中的字段，`color` 属性指定了色板的名称。\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> 需要注意将 `node.style` 中的 `fill` 样式移除，因为其优先级高于色板分配的颜色。\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### 插件\n\n插件机制是 G6 的一个重要特性，可以通过插件扩展 G6 的功能。G6 提供了丰富的内置插件，例如 `tooltip`、`legend` 等，也支持用户自定义插件。\n\n下面我们将使用 `grid-line` 插件为画布添加网格线：\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\n可以看到画布已经添加了网格线：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\n上面的插件配置项中使用了简写形式，大部分的插件都支持传递额外的参数，例如 `grid-line` 插件可以配置 `follow` 属性来指定拖拽画布时网格线是否跟随画布移动。\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\n尝试在下面的示例中拖拽画布，可以看到网格线跟随画布移动：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## 小结\n\n在本教程中，我们从头开始创建了一个 G6 图表，并了解了 G6 的主要概念。我们学习了如何创建一个简单的图表，如何配置元素的样式和种类，如何添加交互行为，如何使用布局算法，如何使用色板，如何使用插件。\n\n关于 G6 更加详细的概念介绍可以在 [核心概念](/manual/graph/graph) 中查看。\n\n图的 API 详细说明可以在 [API](/api/graph) 中查看。\n","packages/site/docs/manual/graph/extension.en.md":"---\ntitle: extension\norder: 9\n---\n\n## Concept\n\nExtension is an important concept in G6, it is a general term for all expandable parts in G6, including the following types:\n\n- Animation\n- Behavior\n- Element\n  - Node\n  - Edge\n  - Combo\n- Layout\n- Palette\n- Plugin\n- Theme\n- Transform\n\n## Register Extension\n\nG6 provides the `register` function for registering extensions, for example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// # Registering Nodes\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\nThe first parameter of the `register` function is the type of the extension, the second parameter is the name of the extension, and the third parameter is the implementation of the extension(refer to the custom-related sections in the documentation for each extension type).\n\nDifferent types of extensions **can** use the same extension name, but when registering extensions of the same type, only the first registration will take effect.\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## Use Extension\n\nThe configuration location for different types of extensions varies, but all are used by specifying the name that was used during registration, for example:\n\n- Using node extensions: `options.node.type`\n- Using edge extensions: `options.edge.type`\n- Using combo extensions: `options.combo.type`\n- Using behavior extensions: `options.behaviors`\n- Using layout extensions: `options.layout.type`\n- Using plugin extensions: `options.plugins`\n- Using theme extensions: `options.theme`\n- Using data transform extensions: `options.transform`\n- Using palette extensions: `options.node.palette`, `options.edge.palette`, etc.\n- Using animation extensions: `options.node.animate`, `options.edge.animate`, etc.\n\n## Get Extension\n\nG6 provides the `getExtension` and `getExtensions` methods to obtain a single extension and all extensions of a specified type, respectively, for example:\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// To get the implementation of the node extension registered with the name 'custom-node'\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// Retrieve all registered node extension implementations\ngetExtensions(ExtensionCategory.NODE);\n```\n","packages/site/docs/manual/graph/extension.zh.md":"---\ntitle: Extension - 扩展\norder: 9\n---\n\n## 概念\n\n扩展 (Extension) 是 G6 中的一个重要概念，它是 G6 中所有可扩展部分的统称，包括以下几种：\n\n- 动画 (Animation)\n- 交互 (Behavior)\n- 元素 (Element)\n- 节点 (Node)\n  - 边 (Edge)\n  - 组合 (Combo)\n- 布局 (Layout)\n- 色板 (Palette)\n- 插件 (Plugin)\n- 主题 (Theme)\n- 数据转换 (Transform)\n\n## 注册扩展\n\nG6 提供了 `register` 函数用于注册扩展，例如：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// 注册节点\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\n`register` 函数的第一个参数是扩展的类型，第二个参数是扩展的名称，第三个参数是扩展的实现(扩展实现参考各扩展类型所在文档的自定义相关章节)。\n\n不同的扩展类型之间**可以**使用相同的扩展名称，但同一类型的扩展重复注册时仅会在第一次注册时生效。\n\n<!-- TODO: 详细的参数签名见：[API 文档](/api/reference/g6/register) -->\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## 使用扩展\n\n不同的扩展类型的配置位置有所不同，但都是通过指定注册时所使用的名称来使用扩展，例如：\n\n- 使用节点扩展：`options.node.type`\n- 使用边扩展：`options.edge.type`\n- 使用组合扩展：`options.combo.type`\n- 使用交互扩展：`options.behaviors`\n- 使用布局扩展：`options.layout.type`\n- 使用插件扩展：`options.plugins`\n- 使用主题扩展：`options.theme`\n- 使用数据转换扩展：`options.transform`\n- 使用色板扩展：`options.node.palette` `options.edge.palette` 等\n- 使用动画扩展：`options.node.animate` `options.edge.animate` 等\n\n## 获取扩展\n\nG6 提供了 `getExtension` 和 `getExtensions` 方法分别用于获取指定扩展类型下的单个扩展和所有扩展，例如：\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// 获取注册的名称为 'custom-node' 的节点扩展实现\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// 获取所有注册的节点扩展实现\ngetExtensions(ExtensionCategory.NODE);\n```\n","packages/site/docs/manual/graph/extensions.en.md":"---\n\ntitle: Built-in Extensions\norder: 4\n\nThe G6 built-in extensions and registered types are as follows:\n\n## Animations\n\n| Extension     | Registration Type |\n| ------------- | ----------------- |\n| ComboCollapse | 'combo-collapse'  |\n| ComboExpand   | 'combo-expand'    |\n| NodeCollapse  | 'node-collapse'   |\n| NodeExpand    | 'node-expand'     |\n| PathIn        | 'path-in'         |\n| PathOut       | 'path-out'        |\n| Fade          | 'fade'            |\n| Translate     | 'translate'       |\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].animation.[stage]`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    animation: {\n      update: 'translate', // Only use translation animation in the update stage\n    },\n  },\n});\n```\n\n## Behaviors\n\n| Extension                 | Registration Type             | Description                                    |\n| ------------------------- | ----------------------------- | ---------------------------------------------- |\n| BrushSelect               | 'brush-select'                | /                                              |\n| ClickSelect               | 'click-select'                | /                                              |\n| CollapseExpand            | 'collapse-expand'             | /                                              |\n| CreateEdge                | 'create-edge'                 | /                                              |\n| DragCanvas                | 'drag-canvas'                 | /                                              |\n| DragElementForce          | 'drag-element-force'          | Drag element when use d3-force layout          |\n| DragElement               | 'drag-element'                | /                                              |\n| FixElementSize            | 'fix-element-size'            | Keep the size of element during zooming canvas |\n| FocusElement              | 'focus-element'               | /                                              |\n| HoverActivate             | 'hover-activate'              | /                                              |\n| LassoSelect               | 'lasso-select'                | /                                              |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | Hide elements during manipulate the canvas     |\n| ScrollCanvas              | 'scroll-canvas'               | /                                              |\n| ZoomCanvas                | 'zoom-canvas'                 | /                                              |\n\nUsage:\n\nIn `GraphOptions.behaviors`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## Elements\n\n### Nodes\n\n| Extension | Registration Type |\n| --------- | ----------------- |\n| circle    | Circle            |\n| diamond   | Diamond           |\n| ellipse   | Ellipse           |\n| hexagon   | Hexagon           |\n| html      | HTML              |\n| image     | Image             |\n| rect      | Rect              |\n| star      | Star              |\n| donut     | Donut             |\n| triangle  | Triangle          |\n\nUsage:\n\n1. In `GraphOptions.data.nodes[number].type`;\n2. In `GraphOptions.node.type`;\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### Edges\n\n| Extension       | Registration Type  | Description                   |\n| --------------- | ------------------ | ----------------------------- |\n| Cubic           | 'cubic'            | Cubic Bezier Curve            |\n| Line            | 'line'             | /                             |\n| Polyline        | 'polyline'         | /                             |\n| Quadratic       | 'quadratic'        | Quadratic Bezier Curve        |\n| CubicHorizontal | 'cubic-horizontal' | Horizontal Cubic Bezier Curve |\n| CubicVertical   | 'cubic-vertical'   | Vertical Cubic Bezier Curve   |\n| CubicRadial     | 'cubic-radial'     | Radial Cubic Bezier Curve     |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.edges[number].type`;\n2. In `GraphOptions.edge.type`;\n\n### Combos\n\n| Extension   | Registration Type |\n| ----------- | ----------------- |\n| CircleCombo | 'circle'          |\n| RectCombo   | 'rect'            |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.combos[number].type`;\n2. In `GraphOptions.combo.type`;\n\n## Layouts\n\n| Extension           | Registration Type | Description                     |\n| ------------------- | ----------------- | ------------------------------- |\n| AntVDagreLayout     | 'antv-dagre'      | /                               |\n| ComboCombinedLayout | 'combo-combined'  | /                               |\n| CompactBoxLayout    | 'compact-box'     | /                               |\n| ForceAtlas2Layout   | 'force-atlas2'    | /                               |\n| CircularLayout      | 'circular'        | /                               |\n| ConcentricLayout    | 'concentric'      | /                               |\n| D3ForceLayout       | 'd3-force'        | /                               |\n| DagreLayout         | 'dagre'           | /                               |\n| DendrogramLayout    | 'dendrogram'      | /                               |\n| ForceLayout         | 'force'           | /                               |\n| FruchtermanLayout   | 'fruchterman'     | /                               |\n| GridLayout          | 'grid'            | /                               |\n| IndentedLayout      | 'indented'        | /                               |\n| MDSLayout           | 'mds'             | Multidimensional Scaling Layout |\n| MindmapLayout       | 'mindmap'         | /                               |\n| RadialLayout        | 'radial'          | /                               |\n| RandomLayout        | 'random'          | /                               |\n\nUsage:\n\nIn `GraphOptions.layout`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## Palettes\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].palette`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## Themes\n\n| Registration Type |\n| ----------------- |\n| dark              |\n| light             |\n\nUsage:\n\nIn `GraphOptions.theme`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  theme: 'dark',\n});\n```\n\n## Plugins\n\n| Extension      | Registration Type  |\n| -------------- | ------------------ |\n| BubbleSets     | 'bubble-sets'      |\n| EdgeFilterLens | 'edge-filter-lens' |\n| GridLine       | 'grid-line'        |\n| Background     | 'background'       |\n| Contextmenu    | 'contextmenu'      |\n| Fisheye        | 'fisheye'          |\n| Fullscreen     | 'fullscreen'       |\n| History        | 'history'          |\n| Hull           | 'hull'             |\n| Legend         | 'legend'           |\n| Minimap        | 'minimap'          |\n| Snapline       | 'snapline'         |\n| Timebar        | 'timebar'          |\n| Toolbar        | 'toolbar'          |\n| Tooltip        | 'tooltip'          |\n| Watermark      | 'watermark'        |\n\nUsage:\n\nIn `GraphOptions.plugins`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## Transforms\n\n| Extension            | Registration Type        | Description |\n| -------------------- | ------------------------ | ----------- |\n| ProcessParallelEdges | 'process-parallel-edges' | /           |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签    |\n\nUsage:\n\nIn `GraphOptions.transform`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## Shapes\n\n| Registration Type |\n| ----------------- |\n| circle            |\n| ellipse           |\n| group             |\n| html              |\n| image             |\n| line              |\n| path              |\n| polygon           |\n| polyline          |\n| rect              |\n| text              |\n| label             |\n| badge             |\n\nUsage:\n\nIn the [upsert](http://localhost:8000/en/manual/custom-extension/element#methods) method of the element class when customizing the shape, pass the second parameter:\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","packages/site/docs/manual/graph/extensions.zh.md":"---\ntitle: 内置扩展\norder: 4\n---\n\nG6 内置扩展及注册扩展类型如下：\n\n## 动画\n\n| 扩展          | 注册类型         | 描述     |\n| ------------- | ---------------- | -------- |\n| ComboCollapse | 'combo-collapse' | 组合收起 |\n| ComboExpand   | 'combo-expand'   | 组合展开 |\n| NodeCollapse  | 'node-collapse'  | 节点收起 |\n| NodeExpand    | 'node-expand'    | 节点展开 |\n| PathIn        | 'path-in'        | 路径进入 |\n| PathOut       | 'path-out'       | 路径退出 |\n| Fade          | 'fade'           | 渐变     |\n| Translate     | 'translate'      | 平移     |\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].animation.[stage]` 中使用，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    animation: {\n      update: 'translate', // 更新阶段仅使用平移动画\n    },\n  },\n});\n```\n\n## 交互\n\n| 扩展                      | 注册类型                      | 描述                   |\n| ------------------------- | ----------------------------- | ---------------------- |\n| BrushSelect               | 'brush-select'                | 框选                   |\n| ClickSelect               | 'click-select'                | 点击选中               |\n| CollapseExpand            | 'collapse-expand'             | 展开/收起元素          |\n| CreateEdge                | 'create-edge'                 | 创建边                 |\n| DragCanvas                | 'drag-canvas'                 | 拖拽画布               |\n| DragElementForce          | 'drag-element-force'          | 力导向拖拽元素         |\n| DragElement               | 'drag-element'                | 拖拽元素               |\n| FixElementSize            | 'fix-element-size'            | 缩放画布时固定元素大小 |\n| FocusElement              | 'focus-element'               | 聚焦元素               |\n| HoverActivate             | 'hover-activate'              | 悬停激活               |\n| LassoSelect               | 'lasso-select'                | 套索选择               |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | 操作画布时隐藏元素     |\n| ScrollCanvas              | 'scroll-canvas'               | 滚动画布               |\n| ZoomCanvas                | 'zoom-canvas'                 | 缩放画布               |\n\n配置方式：\n\n在 `GraphOptions.behaviors` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## 元素\n\n### 节点\n\n| 扩展     | 注册类型 | 描述       |\n| -------- | -------- | ---------- |\n| circle   | Circle   | 圆形节点   |\n| diamond  | Diamond  | 菱形节点   |\n| ellipse  | Ellipse  | 椭圆节点   |\n| hexagon  | Hexagon  | 六边形节点 |\n| html     | HTML     | HTML节点   |\n| image    | Image    | 图片节点   |\n| rect     | Rect     | 矩形节点   |\n| star     | Star     | 星形节点   |\n| donut    | Donut    | 甜甜圈节点 |\n| triangle | Triangle | 三角形节点 |\n\n配置方式：\n\n1. 在 `GraphOptions.data.nodes[number].type` 中配置；\n2. 在 `GraphOptions.node.type` 中配置；\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### 边\n\n| 扩展            | 注册类型           | 描述               |\n| --------------- | ------------------ | ------------------ |\n| Cubic           | 'cubic'            | 三次贝塞尔曲线     |\n| Line            | 'line'             | 直线               |\n| Polyline        | 'polyline'         | 折线               |\n| Quadratic       | 'quadratic'        | 二次贝塞尔曲线     |\n| CubicHorizontal | 'cubic-horizontal' | 水平三次贝塞尔曲线 |\n| CubicVertical   | 'cubic-vertical'   | 垂直三次贝塞尔曲线 |\n| CubicRadial     | 'cubic-radial'     | 径向三次贝塞尔曲线 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.edges[number].type` 中配置；\n2. 在 `GraphOptions.edge.type` 中配置；\n\n### 组合\n\n| 扩展        | 注册类型 | 描述     |\n| ----------- | -------- | -------- |\n| CircleCombo | 'circle' | 圆形组合 |\n| RectCombo   | 'rect'   | 矩形组合 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.combos[number].type` 中配置；\n2. 在 `GraphOptions.combo.type` 中配置；\n\n## 布局\n\n| 扩展                | 注册类型         | 描述                   |\n| ------------------- | ---------------- | ---------------------- |\n| AntVDagreLayout     | 'antv-dagre'     | AntV Dagre 布局        |\n| ComboCombinedLayout | 'combo-combined' | 组合布局               |\n| CompactBoxLayout    | 'compact-box'    | 紧凑树                 |\n| ForceAtlas2Layout   | 'force-atlas2'   | ForceAlas2 力导向布局  |\n| CircularLayout      | 'circular'       | 环形布局               |\n| ConcentricLayout    | 'concentric'     | 同心圆布局             |\n| D3ForceLayout       | 'd3-force'       | D3 力导向布局          |\n| DagreLayout         | 'dagre'          | Dagre 布局             |\n| DendrogramLayout    | 'dendrogram'     | 生态树                 |\n| ForceLayout         | 'force'          | 力导向布局             |\n| FruchtermanLayout   | 'fruchterman'    | Fruchterman 力导向布局 |\n| GridLayout          | 'grid'           | 网格布局               |\n| IndentedLayout      | 'indented'       | 缩进树                 |\n| MDSLayout           | 'mds'            | 高维数据降维布局       |\n| MindmapLayout       | 'mindmap'        | 脑图树                 |\n| RadialLayout        | 'radial'         | 径向布局               |\n| RandomLayout        | 'random'         | 随机布局               |\n\n配置方式：\n\n在 `GraphOptions.layout` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## 色板\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].palette` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## 主题\n\n| 注册类型 | 描述     |\n| -------- | -------- |\n| dark     | 深色主题 |\n| light    | 浅色主题 |\n\n配置方式：\n\n在 `GraphOptions.theme` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  theme: 'dark',\n});\n```\n\n## 插件\n\n| 扩展           | 注册类型           | 描述       |\n| -------------- | ------------------ | ---------- |\n| BubbleSets     | 'bubble-sets'      | 气泡集     |\n| EdgeFilterLens | 'edge-filter-lens' | 边过滤镜   |\n| GridLine       | 'grid-line'        | 网格线     |\n| Background     | 'background'       | 背景       |\n| Contextmenu    | 'contextmenu'      | 上下文菜单 |\n| Fisheye        | 'fisheye'          | 鱼眼放大镜 |\n| Fullscreen     | 'fullscreen'       | 全屏展示   |\n| History        | 'history'          | 历史记录   |\n| Hull           | 'hull'             | 轮廓包围   |\n| Legend         | 'legend'           | 图例       |\n| Minimap        | 'minimap'          | 小地图     |\n| Snapline       | 'snapline'         | 对齐线     |\n| Timebar        | 'timebar'          | 时间条     |\n| Toolbar        | 'toolbar'          | 工具栏     |\n| Tooltip        | 'tooltip'          | 提示框     |\n| Watermark      | 'watermark'        | 水印       |\n\n配置方式：\n\n在 `GraphOptions.plugins` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## 数据转换\n\n| 扩展                 | 注册类型                 | 描述     |\n| -------------------- | ------------------------ | -------- |\n| ProcessParallelEdges | 'process-parallel-edges' | 平行边   |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签 |\n\n配置方式：\n\n在 `GraphOptions.transforms` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## 图形\n\n| 注册类型 | 描述   |\n| -------- | ------ |\n| circle   | 圆形   |\n| ellipse  | 椭圆   |\n| group    | 分组   |\n| html     | HTML   |\n| image    | 图片   |\n| line     | 直线   |\n| path     | 路径   |\n| polygon  | 多边形 |\n| polyline | 折线   |\n| rect     | 矩形   |\n| text     | 文本   |\n| label    | 标签   |\n| badge    | 徽标   |\n\n使用方式：\n\n自定义图形时，元素类成员方法 [upsert](/manual/element/node/custom-node) 方法第二个参数传入：\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","packages/site/docs/manual/graph/graph.en.md":"---\ntitle: Graph\norder: 0\n---\n\n## Overview\n\n### Definition of Graph\n\nIn Chinese, the character \"图\" (Graph) can often be used to represent many different concepts, such as image,shape,and chart or diagram,etc.\n\nIn Graph Theory, a graph is a mathematical structure used to model pairwise relationships between objects, which we typically represent with nodes (or Vertex) and edges (or Link) to denote the objects and the relationships between them.\n\nThe \"graph\" in G6:\n\n- Conceptually, it is the \"graph\" from Graph Theory, a data structure composed of nodes and edges.\n- Visually, a \"graph\" is a figure composed of a set of graphical elements representing nodes and edges.\n- In terms of code implementation, a \"graph\" is a class capable of transforming data into a graphical display.\n\n### Types of Graph\n\nGraph Theory categorizes graphs into many different types based on their structure and properties, such as:\n\n- Directed Graph and Undirected Graph\n- Weighted Graph and Unweighted Graph\n- Simple Graph and Multigraph\n- Cyclic Graph and Acyclic Graph\n- Connected Graph and Disconnected Graph\n- Complete Graph and Non-Complete Graph\n- Sparse Graph and Dense Graph\n- ...\n\nIn G6, we provide a universal graph representation capable of depicting the various types of graphs mentioned above, for example:\n\n- Directed Graph and Undirected Graph: Defined by the start and end points of the edges.\n- Weighted Graph and Unweighted Graph: Defined by the `weight` data on the edges.\n- Simple Graph and Multigraph: Defined by the uniqueness of the edges.\n- ...\n\n### Use Scenarios\n\nGraphs are a very versatile data structure that can be used to represent a variety of scenarios, such as:\n\n- Social Networks\n- Knowledge Graphs\n- Traffic Networks\n- Power Grids\n\nIn G6, we provide a rich expression capability for graphs that can meet the needs of different scenarios. We also offer a wealth of interactive and animated effects to make the graphs more vivid and intuitive.\n\n## Use G6 Graph\n\nTo create a Graph with G6, you first need to import the `@antv/g6` library, and then instantiate the Graph class.\n\n> For installation instructions, refer to: [Getting Started - Installation](/en/manual/getting-started/installation)\n\nThe Graph class accepts an instantiation argument object, known as **options** (Options, in visualization theory it is referred to as: `Specification`), which is used to configure the graph's data, element styles, layout, interactions, etc.\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  // ... other other options\n});\n```\n\n:::warning{title=note}\nThe instantiation process only configures the basic information of the graph. To render the graph onto the page, you still need to call the `render` method.\n:::\n\n- To learn how to quickly create a graph, please refer to [Quick Start](/en/manual/getting-started/quick-start).\n- For more detailed information about the configuration options, please refer to [Options](/en/manual/graph/option).\n- To gain an in-depth understanding of the concepts within the configuration options, please read the rest of the content in this section.\n","packages/site/docs/manual/graph/graph.zh.md":"---\ntitle: Graph - 图\norder: 0\n---\n\n## 什么是 Graph\n\n中文字“图”在大家的传统认知里指的是图画、图像，而图论与可视化中的“图”—— Graph 则有着更精确的定位：主体（objects）与关系（relationships）的组成。它甚至不局限于视觉，主体与关系的数据也可以称为图。\n\n> —— 摘自 [AntV 专栏](https://zhuanlan.zhihu.com/aiux-antv) 文章：[Graph Visualization · 知多少 之 《HelloWorld 图可视化》](https://zhuanlan.zhihu.com/p/83685690)。\n\n在 G6 中，Graph 对象是图的载体，它包含了图上的所有元素（节点、边等），同时挂载了图的相关操作（如交互监听、元素操作、渲染等）。\n\nGraph 对象的完整生命周期包括：\n\n1. **创建**: 通过 `new Graph(options)` 实例化\n2. **初始化**: 在创建时进行内部初始化\n3. **渲染**: 调用 `graph.render()` 进行首次渲染\n4. **更新**: 通过各种 API 更新图的数据和配置\n5. **销毁**: 调用 `graph.destroy()` 销毁实例并释放资源\n\n## 使用 G6 Graph\n\n要使用 G6 创建 Graph，首先需要引入 `@antv/g6` 库，然后实例化 Graph 类。\n\n> 安装教程参考：[开始使用 - 安装](/manual/getting-started/installation)\n\nGraph 类接收一个实例化参数对象，称之为**配置项**(Options，在可视化理论中将其称为：`Specification`)，用于配置图的数据、元素样式、布局、交互等。\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container', // 通过 DOM ID 指定容器\n  width: 800, // 画布宽高（若容器已设尺寸可省略）\n  height: 600,\n  data: {\n    // 初始数据\n    nodes: [{ id: 'start', data: { label: 'Hello G6!' } }],\n  },\n});\n```\n\n:::warning{title=注意}\n实例化过程仅是配置图的基本信息，要将图渲染到页面上，还需要调用 `render` 方法\n:::\n\n## 图配置项\n\n通过下表速查图的配置项，更多类型定义说明和详细用法请参考 [API - 图配置项](/manual/graph/option)。\n\n| 属性             | 类型                               | 默认值      | 描述                                                          |\n| ---------------- | ---------------------------------- | ----------- | ------------------------------------------------------------- |\n| container        | string \\| HTMLElement \\| Canvas    | -           | 图容器，可以是 DOM 元素 ID、DOM 元素实例或 Canvas 实例        |\n| width            | number                             | 容器宽度    | 画布宽度(像素)                                                |\n| height           | number                             | 容器高度    | 画布高度(像素)                                                |\n| autoFit          | 'view' \\| 'center' \\| object       | -           | 自动适配策略，'view'(适应视图)或'center'(居中)                |\n| autoResize       | boolean                            | false       | 是否在窗口大小变化时自动调整画布大小                          |\n| background       | string                             | -           | 画布背景色，也作为导出图片时的背景色                          |\n| canvas           | CanvasConfig                       | -           | 画布配置                                                      |\n| cursor           | Cursor                             | `'default'` | 指针样式                                                      |\n| devicePixelRatio | number                             | 2           | 设备像素比                                                    |\n| padding          | number \\| number[]                 | -           | 画布内边距，在自适应时会根据内边距进行适配                    |\n| renderer         | (layer: string) => IRenderer       | -           | 手动指定渲染器                                                |\n| rotation         | number                             | 0           | 旋转角度(弧度)                                                |\n| zoom             | number                             | 1           | 缩放比例                                                      |\n| zoomRange        | [number, number]                   | [0.01, 10]  | 缩放比例的限制范围                                            |\n| x                | number                             | -           | 视口 x 坐标                                                   |\n| y                | number                             | -           | 视口 y 坐标                                                   |\n| data             | GraphData                          | -           | 图数据，详见 [数据](/manual/data)                             |\n| node             | NodeOptions                        | -           | 节点全局配置，详见 [节点](/manual/element/node/overview)      |\n| edge             | EdgeOptions                        | -           | 边全局配置，详见 [边](/manual/element/edge/overview)          |\n| combo            | ComboOptions                       | -           | 组合全局配置，详见 [组合](/manual/element/combo/overview)     |\n| animation        | boolean \\| AnimationEffectTiming   | -           | 全局动画配置，详见 [动画](/manual/animation/animation)        |\n| theme            | string \\| false                    | `'light'`   | 主题配置，支持 `'light'`、`'dark'` 或自定义主题名             |\n| layout           | LayoutOptions \\| LayoutOptions[]   | -           | 布局配置，详见 [布局](/manual/layout/overview)                |\n| behaviors        | (string \\| CustomBehaviorOption)[] | -           | 交互行为配置，详见 [交互](/manual/behavior/overview)          |\n| plugins          | (string \\| CustomPluginOption)[]   | -           | 插件配置，详见 [插件](/manual/plugin/overview)                |\n| transforms       | TransformOptions                   | -           | 数据转换器配置，详见 [数据转换器](/manual/transform/overview) |\n\n## 图属性\n\n图实例提供了一些只读属性，用于获取图的状态信息：\n\n| 属性      | 类型    | 描述                     |\n| --------- | ------- | ------------------------ |\n| destroyed | boolean | 当前图实例是否已被销毁   |\n| rendered  | boolean | 当前图实例是否已完成渲染 |\n\n## 参考示例\n\n### 完整的创建和配置示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\ngraph.render();\n```\n\n```typescript\nimport { Graph } from '@antv/g6';\n\n// 创建图实例\nconst graph = new Graph({\n  // 基础配置\n  container: 'container',\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\n// 渲染图\ngraph.render();\n```\n\n- 要了解如何快速创建一个图，请参考[快速上手](/manual/getting-started/quick-start)。\n- 要深入了解配置项中个部分的概念，请阅读本章节的其他内容。\n","packages/site/docs/manual/graph/option.en.md":"---\ntitle: Options\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\nWhether to automatically fit the canvas. ⚠️ **Note**: Each time `render` is executed, it will adapt according to `autoFit`.\n\nTwo basic adaptation modes:\n\n- `'view'` - Automatically scale to ensure all content is visible within the view\n- `'center'` - Center the content without changing the zoom level\n\nMore precise adaptation control can be achieved through object form:\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // Adaptation type: 'view' or 'center'\n    options: {\n      // Only applicable to 'view' type\n      when: 'overflow', // When to adapt: 'overflow' (only when content overflows) or 'always' (always adapt)\n      direction: 'x', // Adaptation direction: 'x', 'y', or 'both'\n    },\n    animation: {\n      // Adaptation animation effect\n      duration: 1000, // Animation duration (milliseconds)\n      easing: 'ease-in-out', // Animation easing function\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| Property  | Description                                                                                                                                                             | Type                       | Default    | Required |\n| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | -------- |\n| when      | Adaptation occurs under the following conditions <br/> - `'overflow'` adapt only when content overflows <br/> - `'always'` always adapt                                 | `'overflow'` \\| `'always'` | `'always'` |          |\n| direction | Adapt only in the specified direction <br/> - `'x'` adapt only in x direction <br/> - `'y'` adapt only in y direction <br/> - `'both'` adapt in both x and y directions | `'x'` \\| `'y'` \\| `'both'` | `'both'`   |          |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## autoResize\n\n> _boolean_ **Default:** `false`\n\nWhether to automatically resize the canvas.\n\nImplemented based on the `window.onresize` event. When the browser window size changes, the canvas will automatically resize to fit the container.\n\n## background\n\n> _string_\n\nCanvas background color.\n\nThis color is used as the background color when exporting images. Any valid CSS color value can be used, such as hexadecimal, RGB, RGBA, etc.\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\nCanvas configuration. Related configuration items under GraphOptions (such as `container`, `width`, `height`, `devicePixelRatio`, `background`, `cursor`) are shortcut configuration items and will be converted to canvas configuration items.\n\n#### CanvasConfig\n\n| Property         | Description                                                                                | Type                                                                           | Default | Required |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------- | -------- |\n| container        | Canvas container                                                                           | string \\| HTMLElement                                                          | -       |          |\n| devicePixelRatio | Device pixel ratio                                                                         | number                                                                         | -       |          |\n| width            | Canvas width                                                                               | number                                                                         | -       |          |\n| height           | Canvas height                                                                              | number                                                                         | -       |          |\n| cursor           | Cursor style, same as [GraphOptions.cursor](#cursor)                                       | string                                                                         | -       |          |\n| background       | Canvas background color                                                                    | string                                                                         | -       |          |\n| renderer         | Renderer, same as [GraphOptions.renderer](#renderer)                                       | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -       |          |\n| enableMultiLayer | Whether to enable multi-layer. Non-dynamic parameter, effective only during initialization | boolean                                                                        | -       |          |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\nCanvas container, can be one of the following three assignments:\n\n- ID string of the DOM element, such as `'container'`\n- HTML element object, such as `document.getElementById('container')`\n- Canvas instance, such as `new Canvas(options)`, where `options` is of type [CanvasConfig](#canvasconfig).\n\n## cursor\n\n> string\n\nCursor style, controls the cursor shape when hovering over the canvas. Any valid CSS cursor value can be used.\n\nSupported values include: `'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'.\n\nCursor values are referenced from [MDN - cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n\n## devicePixelRatio\n\n> _number_\n\nDevice pixel ratio.\n\nUsed for high-definition screens, the default is [window.devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio).\n\n## width\n\n> _number_\n\nCanvas width. If not set, the container width will be automatically obtained.\n\n## height\n\n> _number_\n\nCanvas height. If not set, the container height will be automatically obtained.\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\nManually specify the renderer\n\nG6 uses a layered rendering approach, divided into four layers: `background`, `main`, `label`, `transient`. Users can set the renderer for each layer of the canvas through this configuration item.\n\n**Example**: Use SVG renderer for rendering\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\nCanvas padding\n\nUsually, during adaptation, it will be adapted according to the padding. It can be a single value (same padding on all sides) or an array form (specify the padding for top, right, bottom, left in order).\n\n**Example:**\n\n```javascript\n// Single value\nconst graph1 = new Graph({\n  padding: 20, // 20 pixels of padding on all sides\n});\n\n// Array form\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // Padding for top, right, bottom, left\n});\n```\n\n## rotation\n\n> _number_ **Default:** `0`\n\nRotation angle (in radians)\n\n## x\n\n> _number_\n\nViewport x coordinate, sets the initial horizontal position of the viewport.\n\n## y\n\n> _number_\n\nViewport y coordinate, sets the initial vertical position of the viewport.\n\n## zoom\n\n> _number_ **Default:** `1`\n\nSets the initial zoom level of the viewport, 1 means 100% (original size).\n\n## zoomRange\n\n> _[number, number]_ **Default:** `[0.01, 10]`\n\nZoom range, limits the minimum and maximum scale that users can zoom.\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\nEnable or disable global animation\n\nWhen configured as an animation option, animation will be enabled, and this animation configuration will be used as the base configuration for global animation.\n\n#### AnimationEffectTiming\n\n| Property   | Description                    | Type                                                                | Default     | Required |\n| ---------- | ------------------------------ | ------------------------------------------------------------------- | ----------- | -------- |\n| delay      | Animation delay time           | number                                                              | -           |          |\n| direction  | Animation direction            | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |          |\n| duration   | Animation duration             | number                                                              | -           |          |\n| easing     | Animation easing function      | string                                                              | -           |          |\n| fill       | Fill mode after animation ends | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |          |\n| iterations | Animation iteration count      | number                                                              | -           |          |\n\n**Example:**\n\n```javascript\n// Simple enable\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// Detailed configuration\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // Animation duration (milliseconds)\n    easing: 'ease-in-out', // Easing function\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\nData.\n\n#### GraphData\n\n| Property | Description | Type                      | Default | Required |\n| -------- | ----------- | ------------------------- | ------- | -------- |\n| nodes    | Node data   | [NodeData](#nodedata)[]   | -       | ✓        |\n| edges    | Edge data   | [EdgeData](#edgedata)[]   | -       | ✓        |\n| combos   | Combo data  | [ComboData](#combodata)[] | -       | ✓        |\n\n#### NodeData\n\n| Property | Description                                                                                                                                         | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                                 | string         | -       | ✓        |\n| type     | Node type, built-in node type name or custom node name                                                                                              | string         | -       |          |\n| data     | Node data, used to store custom data for the node, such as node name, description, etc. Can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Node style, including visual attributes such as position, size, color, etc.                                                                         | object         | -       |          |\n| states   | Initial state of the node, such as selected, activated, hovered, etc.                                                                               | string[]       | -       |          |\n| combo    | ID of the combo to which it belongs, used to organize the hierarchical relationship of nodes, if none, it is null                                   | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                                     | string[]       | -       |          |\n\n#### EdgeData\n\n| Property | Description                                                                                                    | Type     | Default | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source   | Starting node ID of the edge                                                                                   | string   | -       | ✓        |\n| target   | Target node ID of the edge                                                                                     | string   | -       | ✓        |\n| id       | Unique identifier for the edge                                                                                 | string   | -       |          |\n| type     | Edge type, built-in edge type name or custom edge name                                                         | string   | -       |          |\n| data     | Edge data, used to store custom data for the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style    | Edge style, including visual attributes such as line color, width, arrow, etc.                                 | object   | -       |          |\n| states   | Initial state of the edge                                                                                      | string[] | -       |          |\n\n#### ComboData\n\n| Property | Description                                                                                                      | Type           | Default | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the combo                                                                                  | string         | -       | ✓        |\n| type     | Combo type, built-in combo type name or custom combo name                                                        | string         | -       |          |\n| data     | Combo data, used to store custom data for the combo, can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Combo style                                                                                                      | object         | -       |          |\n| states   | Initial state of the combo                                                                                       | string[]       | -       |          |\n| combo    | Parent combo ID. If there is no parent combo, it is null                                                         | string \\| null | -       |          |\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- Read [Data](/en/manual/data) to learn more about graph data, including but not limited to data formats, how to manipulate data, etc.\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\nNode configuration options.\n\n#### NodeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default  | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name                           | [Type](/en/manual/element/node/base-node#type)           | `circle` |          |\n| style     | Node style, including color, size, etc.                                          | [Style](/en/manual/element/node/base-node#style)         | -        |          |\n| state     | Define the style of the node in different states                                 | [State](/en/manual/element/node/base-node#state)         | -        |          |\n| palette   | Define the color palette of the node, used to map colors based on different data | [Palette](/en/manual/element/node/base-node#palette)     | -        |          |\n| animation | Define the animation effect of the node                                          | [Animation](/en/manual/element/node/base-node#animation) | -        |          |\n\nSee [Node](/en/manual/element/node/base-node) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {\n      fill: '#e6f7ff', // Fill color\n      stroke: '#91d5ff', // Border color\n      lineWidth: 1, // Border width\n      r: 20, // Radius\n      labelText: (d) => d.id, // Label text\n    },\n    // Node state style\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\nEdge configuration options\n\n#### EdgeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name                           | [Type](/en/manual/element/edge/base-edge#type)           | `line`  |          |\n| style     | Edge style, including color, size, etc.                                          | [Style](/en/manual/element/edge/base-edge#style)         | -       |          |\n| state     | Define the style of the edge in different states                                 | [State](/en/manual/element/edge/base-edge#state)         | -       |          |\n| palette   | Define the color palette of the edge, used to map colors based on different data | [Palette](/en/manual/element/edge/base-edge#palette)     | -       |          |\n| animation | Define the animation effect of the edge                                          | [Animation](/en/manual/element/edge/base-edge#animation) | -       |          |\n\nSee [Edge](/en/manual/element/edge/base-edge) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // Edge type\n    style: {\n      stroke: '#91d5ff', // Edge color\n      lineWidth: 2, // Edge width\n      endArrow: true, // Whether there is an arrow\n    },\n    // Edge state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\nCombo configuration options\n\n| Property  | Description                                                                       | Type                                                       | Default  | Required |\n| --------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name                         | [Type](/en/manual/element/combo/base-combo#type)           | `circle` |          |\n| style     | Combo style, including color, size, etc.                                          | [Style](/en/manual/element/combo/base-combo#style)         | -        |          |\n| state     | Define the style of the combo in different states                                 | [State](/en/manual/element/combo/base-combo#state)         | -        |          |\n| palette   | Define the color palette of the combo, used to map colors based on different data | [Palette](/en/manual/element/combo/base-combo#palette)     | -        |          |\n| animation | Define the animation effect of the combo                                          | [Animation](/en/manual/element/combo/base-combo#animation) | -        |          |\n\nSee [Combo](/en/manual/element/combo/base-combo) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {\n      fill: '#f0f0f0', // Background color\n      stroke: '#d9d9d9', // Border color\n      lineWidth: 1, // Border width\n    },\n    // Combo state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\nLayout configuration options, can be an object (normal layout) or an array (pipeline layout).\n\n**Example**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // Force-directed layout\n    preventOverlap: true, // Prevent node overlap\n    nodeStrength: -50, // Repulsion between nodes\n    edgeStrength: 0.5, // Elastic coefficient of edges\n    iterations: 200, // Number of iterations\n    animation: true, // Enable layout animation\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\nSet the theme of the chart, can be the built-in `'light'`, `'dark'` theme, or the name of a custom theme. Set to `false` to use no theme.\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure the interaction behaviors of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // Enable canvas dragging with default configuration\n    'zoom-canvas', // Enable canvas zooming with default configuration\n    {\n      type: 'drag-element', // Custom configuration for dragging elements\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // Only allow dragging nodes\n    },\n    function () {\n      console.log(this); // Output graph instance\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- View [Interaction Overview](/en/manual/behavior/overview) to learn more about interaction principles\n- Browse [Built-in Interactions](/en/manual/behavior/auto-adapt-label) to get a list of all built-in interactions and their configuration options\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nSet the plugins of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // Enable minimap with default configuration\n    {\n      type: 'grid', // Enable grid background\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // Enable toolbar\n      key: 'graph-toolbar',\n      position: 'top-right', // Position\n    },\n  ],\n});\n```\n\n- View [Plugin Overview](/en/manual/plugin/overview) to learn more about plugin principles\n- Browse [Built-in Plugins](/en/manual/plugin/background) to get a list of all built-in plugins and their configuration options\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure data processing, used to process data before rendering, does not affect the original data. Can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // Process parallel edges with default configuration\n    {\n      type: 'map-node-size', // Map node size based on node data\n      field: 'value', // Use the value of the field\n      max: 50, // Maximum radius\n      min: 20, // Minimum radius\n    },\n  ],\n});\n```\n\n- View [Data Processing Overview](/en/manual/transform/overview) to learn more about data processing principles\n- Browse [Built-in Data Processing](/en/manual/transform/map-node-size) to get a list of all built-in data processing and their configuration options\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** Extension type */\n  type: string;\n  /** Extension key, i.e., unique identifier */\n  key?: string;\n}\n```\n","packages/site/docs/manual/graph/option.zh.md":"---\ntitle: Options 配置项\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\n是否自动适应画布。⚠️ **注意**：每次执行 `render` 时，都会根据 `autoFit` 进行自适应。\n\n两种基本自适应模式：\n\n- `'view'` - 自动缩放，确保所有内容都在视图内可见\n- `'center'` - 内容居中显示，但不改变缩放比例\n\n还可通过对象形式实现更精细的自适应控制：\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // 自适应类型：'view' 或 'center'\n    options: {\n      // 仅适用于 'view' 类型\n      when: 'overflow', // 何时适配：'overflow'(仅当内容溢出时) 或 'always'(总是适配)\n      direction: 'x', // 适配方向：'x'、'y' 或 'both'\n    },\n    animation: {\n      // 自适应动画效果\n      duration: 1000, // 动画持续时间(毫秒)\n      easing: 'ease-in-out', // 动画缓动函数\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| 属性      | 描述                                                                                                           | 类型                       | 默认值     | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | ---- |\n| when      | 在以下情况下进行适配 <br/> - `'overflow'` 仅当图内容超出视口时进行适配 <br/> - `'always'` 总是进行适配         | `'overflow`' \\| `'always'` | `'always'` |      |\n| direction | 仅对指定方向进行适配 <br/> - `'x'` 仅适配 x 方向 <br/> - `'y'` 仅适配 y 方向 <br/> - `'both'` 适配 x 和 y 方向 | `'x`' \\| `'y`' \\| `'both'` | `'both'`   |      |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## autoResize\n\n> _boolean_ **默认值:** `false`\n\n是否自动调整画布大小。\n\n基于 `window.onresize` 事件实现。当浏览器窗口大小变化时，画布将自动调整大小以适应容器。\n\n## background\n\n> _string_\n\n画布背景色。\n\n该颜色作为导出图片时的背景色。可以使用任何有效的 CSS 颜色值，如十六进制、RGB、RGBA 等。\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\n画布配置。GraphOptions 下相关配置项（如 `container`、`width`、`height`、`devicePixelRatio`、`background`、`cursor`）为快捷配置项，会被转换为 canvas 配置项。\n\n#### CanvasConfig\n\n| 属性             | 描述                                                   | 类型                                                                           | 默认值 | 必填 |\n| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------ | ------ | ---- |\n| container        | 画布容器                                               | string \\| HTMLElement                                                          | -      |      |\n| devicePixelRatio | 设备像素比                                             | number                                                                         | -      |      |\n| width            | 画布宽度                                               | number                                                                         | -      |      |\n| height           | 画布高度                                               | number                                                                         | -      |      |\n| cursor           | 指针样式，与 [GraphOptions.cursor](#cursor) 配置相同   | string                                                                         | -      |      |\n| background       | 画布背景色                                             | string                                                                         | -      |      |\n| renderer         | 渲染器，与 [GraphOptions.renderer](#renderer) 配置相同 | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -      |      |\n| enableMultiLayer | 是否启用多图层。非动态参数，仅在初始化时生效           | boolean                                                                        | -      |      |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\n画布容器，可以是以下三种赋值之一：\n\n- DOM 元素的 ID 字符串，如 `'container'`\n- HTML 元素对象，如 `document.getElementById('container')`\n- Canvas 实例，如 `new Canvas(options)`，其中 `options` 为 [CanvasConfig](#canvasconfig) 类型。\n\n## cursor\n\n> string\n\n指针样式，控制鼠标悬停在画布上时的光标形状。可以使用任何有效的 CSS cursor 值。\n\n支持的值有： `'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'`。\n\n这里的 Cursor 值参考 [MDN - cursor](https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor)。\n\n## devicePixelRatio\n\n> _number_\n\n设备像素比。\n\n用于高清屏的设备像素比，默认为 [window.devicePixelRatio](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio)。\n\n## width\n\n> _number_\n\n画布宽度。如果未设置，则会自动获取容器宽度。\n\n## height\n\n> _number_\n\n画布高度。如果未设置，则会自动获取容器高度。\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\n手动指定渲染器\n\nG6 采用了分层渲染的方式，分为 `background`、`main`、`label`、`transient` 四层，用户可以通过该配置项分别设置每层画布的渲染器。\n\n**示例**: 使用 SVG 渲染器进行渲染\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\n画布内边距\n\n通常在自适应时，会根据内边距进行适配。可以是单个数值（四边相同）或者数组形式（按顺序指定上、右、下、左的内边距）。\n\n**示例：**\n\n```javascript\n// 单个数值\nconst graph1 = new Graph({\n  padding: 20, // 四边均为 20 像素的内边距\n});\n\n// 数组形式\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // 上、右、下、左的内边距\n});\n```\n\n## rotation\n\n> _number_ **默认值:** `0`\n\n旋转角度（以弧度为单位）\n\n## x\n\n> _number_\n\n视口 x 坐标，设置视口的初始水平位置。\n\n## y\n\n> _number_\n\n视口 y 坐标，设置视口的初始垂直位置。\n\n## zoom\n\n> _number_ **默认值:** `1`\n\n设置视口的初始缩放级别，1 表示 100%（原始大小）。\n\n## zoomRange\n\n> _[number, number]_ **默认值:** `[0.01, 10]`\n\n缩放范围，限制用户可以缩放的最小和最大比例。\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\n启用或关闭全局动画\n\n为动画配置项时，会启用动画，并将该动画配置作为全局动画的基础配置。\n\n#### AnimationEffectTiming\n\n| 属性       | 描述                 | 类型                                                                | 默认值      | 必选 |\n| ---------- | -------------------- | ------------------------------------------------------------------- | ----------- | ---- |\n| delay      | 动画延迟时间         | number                                                              | -           |      |\n| direction  | 动画方向             | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |      |\n| duration   | 动画持续时间         | number                                                              | -           |      |\n| easing     | 动画缓动函数         | string                                                              | -           |      |\n| fill       | 动画结束后的填充模式 | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |      |\n| iterations | 动画迭代次数         | number                                                              | -           |      |\n\n**示例：**\n\n```javascript\n// 简单启用\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// 详细配置\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // 动画持续时间（毫秒）\n    easing: 'ease-in-out', // 缓动函数\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\n数据。\n\n#### GraphData\n\n| 属性   | 描述     | 类型                      | 默认值 | 必选 |\n| ------ | -------- | ------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#nodedata)[]   | -      | ✓    |\n| edges  | 边数据   | [EdgeData](#edgedata)[]   | -      | ✓    |\n| combos | 组合数据 | [ComboData](#combodata)[] | -      | ✓    |\n\n#### NodeData\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n#### EdgeData\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n#### ComboData\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- 阅读 [数据](/manual/data) 深入了解图数据，包括不限于数据格式、如何操作数据等。\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\n节点配置项。\n\n#### NodeOptions\n\n| 属性      | 描述                                         | 类型                                                  | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------------------------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](/manual/element/node/base-node#type)           | `circle` |      |\n| style     | 节点样式，包括颜色、大小等                   | [Style](/manual/element/node/base-node#style)         | -        |      |\n| state     | 定义节点在不同状态下的样式                   | [State](/manual/element/node/base-node#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/node/base-node#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](/manual/element/node/base-node#animation) | -        |      |\n\n详见 [Node](/manual/element/node/base-node)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {\n      fill: '#e6f7ff', // 填充色\n      stroke: '#91d5ff', // 边框色\n      lineWidth: 1, // 边框宽度\n      r: 20, // 半径\n      labelText: (d) => d.id, // 标签文本\n    },\n    // 节点状态样式\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\n边配置项\n\n#### EdgeOptions\n\n| 属性      | 描述                                   | 类型                                                  | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------------------------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](/manual/element/edge/base-edge#type)           | `line` |      |\n| style     | 边样式，包括颜色、大小等               | [Style](/manual/element/edge/base-edge#style)         | -      |      |\n| state     | 定义边在不同状态下的样式               | [State](/manual/element/edge/base-edge#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](/manual/element/edge/base-edge#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](/manual/element/edge/base-edge#animation) | -      |      |\n\n详见 [Edge](/manual/element/edge/base-edge)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // 边类型\n    style: {\n      stroke: '#91d5ff', // 边的颜色\n      lineWidth: 2, // 边的宽度\n      endArrow: true, // 是否有箭头\n    },\n    // 边的状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\n组合配置项\n\n| 属性      | 描述                                         | 类型                                                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ------------------------------------------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](/manual/element/combo/base-combo#type)           | `circle` |      |\n| style     | 组合样式，包括颜色、大小等                   | [Style](/manual/element/combo/base-combo#style)         | -        |      |\n| state     | 定义组合在不同状态下的样式                   | [State](/manual/element/combo/base-combo#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/combo/base-combo#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](/manual/element/combo/base-combo#animation) | -        |      |\n\n详见 [Combo](/manual/element/combo/base-combo)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {\n      fill: '#f0f0f0', // 背景色\n      stroke: '#d9d9d9', // 边框色\n      lineWidth: 1, // 边框宽度\n    },\n    // 组合状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\n布局配置项，可以是对象（普通布局）或数组（流水线布局）。\n\n**示例**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // 力导向布局\n    preventOverlap: true, // 防止节点重叠\n    nodeStrength: -50, // 节点之间的斥力\n    edgeStrength: 0.5, // 边的弹性系数\n    iterations: 200, // 迭代次数\n    animation: true, // 启用布局动画\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\n设置图表的主题，可以是内置的 `'light'`、`'dark'` 主题，也可以是自定义主题的名称。设为 `false` 则不使用任何主题。\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置图表的交互行为，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // 使用默认配置启用画布拖拽\n    'zoom-canvas', // 使用默认配置启用画布缩放\n    {\n      type: 'drag-element', // 自定义配置拖拽元素\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // 只允许拖拽节点\n    },\n    function () {\n      console.log(this); // 输出 graph 实例\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- 查看 [交互总览](/manual/behavior/overview) 深入了解交互原理\n- 浏览 [内置交互](/manual/behavior/auto-adapt-label) 获取所有内置交互列表及其配置选项\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n设置图表的插件，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // 启用小地图，使用默认配置\n    {\n      type: 'grid', // 启用网格背景\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // 启用工具栏\n      key: 'graph-toolbar',\n      position: 'top-right', // 位置\n    },\n  ],\n});\n```\n\n- 查看 [插件总览](/manual/plugin/overview) 深入了解插件原理\n- 浏览 [内置插件](/manual/plugin/background) 获取所有内置插件列表及其配置项\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置数据处理，用于在渲染前对数据进行处理，不会影响原始数据。可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // 处理平行边，使用默认配置\n    {\n      type: 'map-node-size', // 根据节点数据映射节点大小\n      field: 'value', // 使用 value 字段的值\n      max: 50, // 最大半径\n      min: 20, // 最小半径\n    },\n  ],\n});\n```\n\n- 查看 [数据处理总览](/manual/transform/overview) 深入了解数据处理原理\n- 浏览 [内置数据处理](/manual/transform/map-node-size) 获取所有内置数据处理列表及其配置项\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** 拓展类型 */\n  type: string;\n  /** 拓展 key，即唯一标识 */\n  key?: string;\n}\n```\n","packages/site/docs/manual/introduction.en.md":"---\ntitle: Introduction\norder: 0\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 is a graph visualization engine. It provides capabilities for graph drawing, layout, analysis, interaction, animation, and other aspects of graph visualization. It aims to offer developers a set of tools that are easy to use, professionally reliable, and highly customizable for graph visualization development.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Rich Elements</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ elements to meet the needs of common scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Flexible Interactions</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ interactions that can be freely combined according to different scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High-Performance Layout Algorithms</h4>\n\n<p style=\"text-align: center;\">High-performance layouts, built-in 10+ common graph layouts, with support for WebGPU and WASM computational acceleration.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Multicolor Themes for Various Scenarios</h4>\n\n<p style=\"text-align: center;\"><img height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D Scenes</h4>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">Supports 3D elements and layouts to create immersive graph visualization scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High Customizability</h4>\n\n<p style=\"text-align: center;\">Elements, layouts, interactions, and plugins are all customizable, enabling every creative idea you have.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Start Your G6 Journey in Just 3 Minutes</h4>\n\n<p style=\"text-align: center;\">Click to enter 👉 <a href=\"/manual/getting-started/quick-start\">Quick Start</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","packages/site/docs/manual/introduction.zh.md":"---\ntitle: 简介\norder: 0\nsidebar: false\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 是一个图可视化引擎。它提供了图的绘制、布局、分析、交互、动画等图可视化能力。旨在为开发者提供一套简单易用、专业可靠、可高度定制的图可视化开发工具</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">丰富元素</h4>\n\n<p style=\"text-align: center;\">内置 10+ 元素，满足常规场景需求</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">灵活交互</h4>\n\n<p style=\"text-align: center;\">内置 10+ 交互，并可根据不同场景自由组合</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高性能布局算法</h4>\n\n<p style=\"text-align: center;\">高性能布局，内置 10+ 常用的图布局，支持 WebGPU、 WASM 计算加速</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">多色主题，适用多种场景</h4>\n\n<p style=\"text-align: center;\"><image height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D 场景</h4>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">支持 3D 元素、布局，打造沉浸式的图可视化场景</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高可定制性</h4>\n\n<p style=\"text-align: center;\">元素、布局、交互、插件统统可定制，实现你的每一个创意</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">仅需 3 分钟，开启 G6 之旅</h4>\n\n<p style=\"text-align: center;\">点击进入👉 <a href=\"/manual/getting-started/quick-start\">快速开始</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","packages/site/docs/manual/layout/AntvDagreLayout.en.md":"---\ntitle: AntvDagre Layout\norder: 2\n---\n\n## Overview\n\nAntvDagre builds upon the original [dagre](https://github.com/dagrejs/dagre/wiki) layout and adds more useful options, such as `nodeOrder`, `edgeLabelSpace`, and more. The `dagre` layout itself is a hierarchical layout suitable for directed acyclic graphs (DAGs), which can automatically handle node direction and spacing, and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## Options\n\n> For more native `dagre` options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout). Here, only some core and new options are listed.\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Diagram\" />\n\n| Property       | Description                                                                                                                                                                                        | Type                                                | Default | Required |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------- | -------- |\n| type           | Layout type                                                                                                                                                                                        | `antv-dagre`                                        | -       | ✓        |\n| rankdir        | Layout direction, options                                                                                                                                                                          | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`    |          |\n| align          | Node alignment, options                                                                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`    |          |\n| nodesep        | Node spacing (px). For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing.                                                                                             | number                                              | 50      |          |\n| nodesepFunc    | Callback for node spacing (px), allows different spacing for different nodes. For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing. Takes precedence over `nodesep`. | (d?: Node) => number                                |         |          |\n| ranksep        | Rank spacing (px). For `TB` or `BT`, it's vertical spacing between adjacent ranks; for `LR` or `RL`, it's horizontal spacing.                                                                      | number                                              | 50      |          |\n| ranksepFunc    | Callback for rank spacing (px), allows different spacing for different ranks. For `TB` or `BT`, it's vertical spacing; for `LR` or `RL`, it's horizontal spacing. Takes precedence over `ranksep`. | (d?: Node) => number                                |         |          |\n| ranker         | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                                                                         | `network-simplex` \\| `tight-tree` \\| `longest-path` | -       |          |\n| nodeSize       | Specify node size for all nodes or each node, used for occupying space and spacing calculation                                                                                                     | Size \\| ((nodeData: Node) => Size)                  | -       |          |\n| controlPoints  | Whether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that consumes `style.controlPoints` as control points                 | boolean                                             | false   |          |\n| begin          | Top-left alignment position of the layout                                                                                                                                                          | [number, number] \\| [number, number, number]        | -       |          |\n| sortByCombo    | Whether to sort nodes in the same rank based on `parentId` in each node's data to avoid Combo overlap                                                                                              | boolean                                             | false   |          |\n| edgeLabelSpace | Whether to reserve space for edge labels                                                                                                                                                           | boolean                                             | true    |          |\n| nodeOrder      | Reference array for node order in the same rank, storing node ids                                                                                                                                  | string[]                                            | -       |          |\n| radial         | Whether to use radial layout based on `dagre`                                                                                                                                                      | boolean                                             | -       |          |\n| focusNode      | Focus node, only effective when `radial` is true                                                                                                                                                   | ID \\| Node \\| null                                  | -       |          |\n| preset         | Reference node positions for layout calculation, usually used to keep transitions smooth when switching data                                                                                       | NodeData[]                                          | -       |          |\n\n> Note: In G6, the control points computed by `antv-dagre` are written into `edge.style.controlPoints`.\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\nNode alignment: U = upper, D = down, L = left, R = right\n\n- `UL`: align to upper left\n- `UR`: align to upper right\n- `DL`: align to lower left\n- `DR`: align to lower right\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\nLayout direction. T = top, B = bottom, L = left, R = right\n\n- `TB`: top to bottom\n- `BT`: bottom to top\n- `LR`: left to right\n- `RL`: right to left\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\nLayout mode\n\n### ranksep\n\n> _number_ **Default:** 50\n\nRank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. `ranksepFunc` has higher priority.\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\nCallback for rank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. Takes precedence over nodesep if set.\n\n### nodesep\n\n> _number_ **Default:** 50\n\nNode spacing (px)\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. `nodesepFunc` has higher priority.\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\nCallback for node spacing (px), allows different spacing for different nodes\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. Takes precedence over nodesep if set.\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\nTop-left alignment position of the layout\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\nWhether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that uses `style.controlPoints` as control points. Adds `style.controlPoints` to edge data.\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\nWhether to reserve space for edge labels\n\nThis affects whether a dummy node is added in the middle of the edge.\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\nFocus node, only effective when `radial` is true\n\n- ID: node id\n- Node: node instance\n- null: cancel focus\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\nReference array for node order in the same rank, stores node ids\n\nIf not specified, dagre's default order is used.\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\nSpecify node size for all or each node.\n\nUsed for collision detection to prevent node overlap\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\nReference node positions for layout calculation\n\nUsually for smooth transitions when switching data. In G6, if updating data, the existing layout result is used as input.\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout based on dagre\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\nWhether to sort nodes in the same rank by their parentId to prevent Combo overlap\n\nRecommended to enable when using Combo\n\n## Suitable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, node direction and spacing are automatically handled\n- **Dependency Graphs**: Display dependencies between packages or modules\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks\n\n## Related Documentation\n\n> The following documents can help you better understand the Dagre layout\n\n- [Graph Layout Algorithms: In-depth Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/AntvDagreLayout.zh.md":"---\ntitle: AntV Dagre 布局 AntvDagre\norder: 2\n---\n\n## 概述\n\nAntvDagre 在原先[dagre](https://github.com/dagrejs/dagre/wiki)布局的基础上增加了更多有用的设置项，比如`nodeOrder`、`edgeLabelSpace`等等。 `dagre`布局本身一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## 配置项\n\n> 更多`dagre`原生配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)，这里仅列出部分核心配置和新增的配置\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性           | 描述                                                                                                                                               | 类型                                                | 默认值 | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------ | ---- |\n| type           | 布局类型                                                                                                                                           | `antv-dagre`                                        | -      | ✓    |\n| rankdir        | 布局方向，可选值                                                                                                                                   | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`   |      |\n| align          | 节点对齐方式，可选值                                                                                                                               | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`   |      |\n| nodesep        | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                                 | number                                              | 50     |      |\n| nodesepFunc    | 节点间距（px）的回调函数，优先级高于 `nodesep`                                                                                                     | (d?: Node) => number                                | -      |      |\n| ranksep        | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                               | number                                              | 50     |      |\n| ranksepFunc    | 层间距（px）的回调函数，优先级高于 `ranksep`                                                                                                       | (d?: Node) => number                                | -      |      |\n| ranker         | 为每个节点分配等级的算法，共支持三种算法：`longest-path`、`tight-tree`、`network-simplex`                                                          | `network-simplex` \\| `tight-tree` \\| `longest-path` | -      |      |\n| nodeSize       | 统一指定或为每个节点指定节点大小，用于占位与间距计算                                                                                               | Size \\| ((nodeData: Node) => Size)                  | -      |      |\n| controlPoints  | 是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'）时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效 | boolean                                             | false  |      |\n| begin          | 布局的左上角对齐位置                                                                                                                               | [number, number] \\| [number, number, number]        | -      |      |\n| sortByCombo    | 同一层节点是否根据每个节点数据中的 `parentId` 进行排序，以防止 Combo 重叠                                                                          | boolean                                             | false  |      |\n| edgeLabelSpace | 是否为边的 label 预留位置                                                                                                                          | boolean                                             | true   |      |\n| nodeOrder      | 同层节点顺序的参考数组，存放节点 id 值                                                                                                             | string[]                                            | -      |      |\n| radial         | 是否基于 `dagre` 进行辐射布局                                                                                                                      | boolean                                             | -      |      |\n| focusNode      | 关注的节点，仅在 `radial` 为 true 时生效                                                                                                           | ID \\| Node \\| null                                  | -      |      |\n| preset         | 布局计算时参考的节点位置，一般用于切换数据时保证重新布局的连续性                                                                                   | NodeData[]                                          | -      |      |\n\n> 补充：在 G6 中，`antv-dagre` 计算得到的控制点会被写入边的 `style.controlPoints`。\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\n节点对齐方式 U：upper（上）；D：down（下）；L：left（左）；R：right（右）\n\n- `UL`:对齐到左上角\n- `UR`:对齐到右上角\n- `DL`:对齐到左下角\n- `DR`:对齐到右下角\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\n布局的方向。T：top（上）；B：bottom（下）；L：left（左）；R：right（右）\n\n- `TB`:从上至下布局\n- `BT`:从下至上布局\n- `LR`:从左至右布局\n- `RL`:从右至左布局\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\n布局的模式\n\n### ranksep\n\n> _number_ **Default:** 50\n\n层间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。ranksepFunc 拥有更高的优先级\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\n层间距（px）的回调函数\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### nodesep\n\n> _number_ **Default:** 50\n\n节点间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。nodesepFunc 拥有更高的优先级\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\n节点间距（px）的回调函数，通过该参数可以对不同节点设置不同的节点间距\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\n布局的左上角对齐位置\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\n是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'） 时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效。本质上就是给边数据增加了 `style.controlPoints`\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\n是否为边的label留位置\n\n这会影响是否在边中间添加dummy node\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\n关注的节点，注意，仅在`radial` 为 true 时生效\n\n- ID: 节点 id\n- Node: 节点实例\n- null: 取消关注\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\n同层节点顺序的参考数组，存放节点 id 值\n\n若未指定，则将按照 dagre 本身机制排列同层节点顺序\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\n统一指定或为每个节点指定节点大小。\n\n用于防止节点重叠时的碰撞检测\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\n布局计算时参考的节点位置\n\n一般用于切换数据时保证重新布局的连续性。在 G6 中，若是更新数据，则将自动使用已存在的布局结果数据作为输入\n\n### radial\n\n> _boolean_\n\n是否基于 dagre 进行辐射布局\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\n同一层节点是否根据每个节点数据中的 parentId 进行排序，以防止 Combo 重叠\n\n建议在有 Combo 的情况下配置\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解 Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/BaseLayout.en.md":"---\ntitle: Common Layout Configuration Options\norder: 1\n---\n\nThis article introduces the common attribute configurations for built-in layouts.\n\n## General Configuration\n\n| Property               | Description                                                                             | Type                                                  | Default    | Required |\n| ---------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------- | -------- |\n| type                   | Layout type, name of built-in or custom layout                                          | [Type](#Type)                                         | -          | ✓        |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in the layout (takes effect when preLayout is true) | boolean                                               | false      |          |\n| nodeFilter             | Nodes participating in the layout                                                       | (node: NodeData) => boolean                           | () => true |          |\n| comboFilter            | Combos participating in the layout                                                      | (combo: ComboData) => boolean                         | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements                           | boolean                                               | false      |          |\n| enableWorker           | Whether to run the layout in a WebWorker                                                | boolean                                               | -          |          |\n| iterations             | Number of iterations for iterative layout                                               | number                                                | -          |          |\n| animation              | Whether to enable layout animation                                                      | boolean                                               | false      |          |\n| width                  | Width of the layout area, defaults to the current container width                       | number                                                | -          |          |\n| height                 | Height of the layout area, defaults to the current container height                     | number                                                | -          |          |\n| center                 | Layout center point                                                                     | [number, number] \\| [number, number, number]          | -          |          |\n| node                   | Node field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |          |\n| edge                   | Edge field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, source?, target? })                | -          |          |\n\nAdditional notes:\n\n- `width` / `height` / `center` are common layout fields uniformly supported by `@antvis/layout`.\n- `node` / `edge` are used to adapt non-standard business fields such as custom `id` / `source` / `target`.\n- `iterations` is the step count used by the G6 runtime to drive iterative layouts, and is not the same as some layouts' internal algorithm parameters.\n\n### Type\n\nSpecifies the layout type, either the name of a built-in layout type or a custom layout.\n\n```js {4}\nconst graph = new Graph({\n  // Other configurations...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\nOptional values include:\n\n- `antv-dagre`: [Custom layout based on dagre](/en/manual/layout/antv-dagre-layout)\n- `circular`: [Circular layout](/en/manual/layout/circular-layout)\n- `combo-combined`: [Layout suitable for combinations](/en/manual/layout/combo-combined-layout)\n- `concentric`: [Concentric layout](/en/manual/layout/concentric-layout)\n- `d3-force`: [Force-directed layout based on D3](/en/manual/layout/d3-force-layout)\n- `d3-force-3d`: [3D Force-directed layout](/en/manual/layout/d3-force3-d-layout)\n- `dagre`: [Dagre layout](/en/manual/layout/dagre-layout)\n- `fishbone`: [Fishbone layout](/en/manual/layout/fishbone)\n- `force`: [Force-directed layout](/en/manual/layout/force-layout)\n- `force-atlas2`: [ForceAtlas2 layout](/en/manual/layout/force-atlas2-layout)\n- `fruchterman`: [Fruchterman layout](/en/manual/layout/fruchterman-layout)\n- `grid`: [Grid layout](/en/manual/layout/grid-layout)\n- `mds`: [MDS layout for high-dimensional data](/en/manual/layout/mds-layout)\n- `radial`: [Radial layout](/en/manual/layout/radial-layout)\n- `random`: [Random layout](/en/manual/layout/random-layout)\n- `snake`: [Snake layout](/en/manual/layout/snake)\n- `compact-box`: [Compact box tree layout](/en/manual/layout/compact-box-layout)\n- `dendrogram`: [Dendrogram layout](/en/manual/layout/dendrogram-layout)\n- `mindmap`: [Mindmap layout](/en/manual/layout/mindmap-layout)\n- `indented`: [Indented tree layout](/en/manual/layout/indented-layout)\n","packages/site/docs/manual/layout/BaseLayout.zh.md":"---\ntitle: 布局通用配置项\norder: 1\n---\n\n本文介绍内置布局通用属性配置。\n\n## 通用配置\n\n| 属性                   | 描述                                                  | 类型                                                  | 默认值     | 必选 |\n| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ---------- | ---- |\n| type                   | 布局类型，内置布局或自定义布局的名称                  | [Type](#Type)                                         | -          | ✓    |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（当 preLayout 为 true 时生效） | boolean                                               | false      |      |\n| nodeFilter             | 参与该布局的节点                                      | (node: NodeData) => boolean                           | () => true |      |\n| comboFilter            | 参与该布局的combo元素                                 | (combo: ComboData) => boolean                         | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                    | boolean                                               | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                           | boolean                                               | -          |      |\n| iterations             | 迭代布局的迭代次数                                    | number                                                | -          |      |\n| animation              | 是否启用布局动画                                      | boolean                                               | false      |      |\n| width                  | 布局区域宽度，默认使用当前容器宽度                    | number                                                | -          |      |\n| height                 | 布局区域高度，默认使用当前容器高度                    | number                                                | -          |      |\n| center                 | 布局中心点                                            | [number, number] \\| [number, number, number]          | -          |      |\n| node                   | 节点字段映射，用于把业务字段映射为布局字段            | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |      |\n| edge                   | 边字段映射，用于把业务字段映射为布局字段              | (datum) => ({ id?, source?, target? })                | -          |      |\n\n补充说明：\n\n- `width` / `height` / `center` 是 `@antvis/layout` 统一支持的通用布局字段。\n- `node` / `edge` 用于适配非标准 `id/source/target` 业务数据。\n- `iterations` 是 G6 运行时用于驱动迭代布局的步数，不等同于某些布局内部自己的算法参数。\n\n### Type\n\n指定布局类型，内置布局类型名称或自定义布局的名称。\n\n```js {4}\nconst graph = new Graph({\n  // 其他配置...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\n可选值有：\n\n- `antv-dagre`：[基于 dagre 定制的布局](/manual/layout/antv-dagre-layout)\n- `circular`：[环形布局](/manual/layout/circular-layout)\n- `combo-combined`：[适用于存在组合的布局](/manual/layout/combo-combined-layout)\n- `concentric`：[同心圆布局](/manual/layout/concentric-layout)\n- `d3-force`[基于 D3 的力导向布局](/manual/layout/d3-force-layout)\n- `d3-force-3d`：[3D力导向布局](/manual/layout/d3-force3-d-layout)\n- `dagre`：[dagre 布局](/manual/layout/dagre-layout)\n- `fishbone`：[鱼骨布局](/manual/layout/fishbone)\n- `force`：[力导向布局](/manual/layout/force-layout)\n- `force-atlas2`：[ForceAtlas2 布局](/manual/layout/force-atlas2-layout)\n- `fruchterman`：[Fruchterman 布局](/manual/layout/fruchterman-layout)\n- `grid`：[网格布局](/manual/layout/grid-layout)\n- `mds`：[高维数据降维算法布局](/manual/layout/mds-layout)\n- `radial`：[径向布局](/manual/layout/radial-layout)\n- `random`：[随机布局](/manual/layout/random-layout)\n- `snake`：[蛇形布局](/manual/layout/snake)\n- `compact-box`：[紧凑树布局](/manual/layout/compact-box-layout)\n- `dendrogram`：[树状布局](/manual/layout/dendrogram-layout)\n- `mindmap`：[思维导图布局](/manual/layout/mindmap-layout)\n- `indented`：[缩进树布局](/manual/layout/indented-layout)\n","packages/site/docs/manual/layout/CircularLayout.en.md":"---\ntitle: Circular Layout\norder: 3\n---\n\n## Overview\n\nCircular layout arranges nodes evenly or at intervals on a circle, and also supports spiral layouts by configuring different startRadius and endRadius. See more circular layout [examples](en/examples#layout-circular) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n**Circular layout**:\n\n- Suitable for networks with equal relationships and no hierarchical structure\n\n**Spiral layout**:\n\n- Suitable for implicit hierarchies or time series graphs (such as organizational charts, propagation networks)\n\n## Basic Usage\n\nOther settings use the default configuration (layout width and height default to the entire canvas container)\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## Options\n\n| Property    | Description                                                                                                       | Type                                          | Default                                   | Required |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------- | -------- |\n| type        | Layout type                                                                                                       | circular                                      | -                                         | ✓        |\n| angleRatio  | How many 2\\*PI between the first and last node                                                                    | number                                        | 1                                         |          |\n| center      | Center of the layout                                                                                              | [number, number]\\|[number, number, number]    | [`layout width` / 2, `layout height` / 2] |          |\n| clockwise   | Whether to arrange clockwise                                                                                      | boolean                                       | true                                      |          |\n| divisions   | Number of segments on the ring (segments will be evenly distributed, effective when endRadius - startRadius != 0) | number                                        | 1                                         |          |\n| nodeSize    | Node size (diameter), used for collision detection                                                                | Size \\| ((nodeData: Node) => Size)            | 10                                        |          |\n| nodeSpacing | Minimum spacing between rings, used to adjust radius                                                              | number \\| ((nodeData: Node) => number)        | 10                                        |          |\n| ordering    | Node ordering on the ring, [see details](#ordering)                                                               | `topology` \\| `topology-directed` \\| `degree` | -                                         |          |\n| radius      | Circle radius, if set, spiral layout configs `startRadius` and `endRadius` are ignored, [see details](#radius)    | number                                        | -                                         |          |\n| startAngle  | Start angle of the layout                                                                                         | number                                        | 0                                         |          |\n| endAngle    | End angle of the layout                                                                                           | number                                        | 2 \\* Math.PI                              |          |\n| startRadius | Start radius for spiral layout, [usage](#spiral-layout)                                                           | number                                        | -                                         |          |\n| endRadius   | End radius for spiral layout                                                                                      | number                                        | -                                         |          |\n| width       | Layout width                                                                                                      | number                                        | canvas width                              |          |\n| height      | Layout height                                                                                                     | number                                        | canvas height                             |          |\n\n### ordering\n\nNode ordering on the ring\n\n- `topology`: topological order\n- `topology-directed`: topological order (directed graph)\n- `degree`: order by degree\n\nIf not set (`null`), the order in the array is used directly\n\n### radius\n\nIf radius, startRadius, and endRadius are not set, the default is `Math.min(layout width, layout height) / 2`, i.e., fills the entire layout area\n\n## Code Examples\n\n### Basic Circular Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### Spiral Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CircularLayout.zh.md":"---\ntitle: 环形布局 Circular\norder: 3\n---\n\n## 概述\n\n环形布局是一种把节点均匀或者按间隔放置在圆上的布局，也支持通过配置 startRadius 和 endRadius 为不一样的值实现螺旋状布局。参考更多环形布局[样例](/examples#layout-circular)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n**环形布局**:\n\n- 适用于平等关系网络、无层级结构的图\n\n**螺旋状布局**:\n\n- 适用于隐式层级或时间序列图（如组织架构、传播网络）\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## 配置项\n\n| 属性        | 描述                                                                                | 类型                                          | 默认值                           | 必选 |\n| ----------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | -------------------------------- | ---- |\n| type        | 布局类型                                                                            | circular                                      | -                                | ✓    |\n| angleRatio  | 从第一个节点到最后节点之间相隔多少个 2\\*PI                                          | number                                        | 1                                |      |\n| center      | 布局的中心                                                                          | [number, number]\\|[number, number, number]    | [`布局宽度` / 2, `布局高度` / 2] |      |\n| clockwise   | 是否顺时针排列                                                                      | boolean                                       | true                             |      |\n| divisions   | 节点在环上的分段数（几个段将均匀分布，在 endRadius - startRadius != 0 时生效）      | number                                        | 1                                |      |\n| nodeSize    | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                      | Size \\| ((nodeData: Node) => Size)            | 10                               |      |\n| nodeSpacing | 环与环之间最小间距，用于调整半径                                                    | number \\| ((nodeData: Node) => number)        | 10                               |      |\n| ordering    | 节点在环上排序的依据，[说明](#ordering)                                             | `topology` \\| `topology-directed` \\| `degree` | -                                |      |\n| radius      | 圆的半径，设置了则螺旋状布局的配置`startRadius`、`endRadius`不生效，[说明](#radius) | number                                        | -                                |      |\n| startAngle  | 布局的开始角度                                                                      | number                                        | 0                                |      |\n| endAngle    | 布局的结束角度                                                                      | number                                        | 2 \\* Math.PI                     |      |\n| startRadius | 螺旋状布局的开始半径，[用法](#螺旋状布局)                                           | number                                        | -                                |      |\n| endRadius   | 螺旋状布局的结束半径                                                                | number                                        | -                                |      |\n| width       | 布局的宽度                                                                          | number                                        | 画布宽度                         |      |\n| height      | 布局的高度                                                                          | number                                        | 画布高度                         |      |\n\n### ordering\n\n节点在环上排序的依据\n\n- `topology`: 按照拓扑排序\n- `topology-directed`: 按照拓扑排序（有向图）\n- `degree`: 按照度数大小排序\n\n不配置（`null`）则直接使用数组中的顺序\n\n### radius\n\n如果radius、startRadius、endRadius都没配置，则默认为最终计算出来的`Math.min(布局宽度, 布局高度) / 2`，即布满整个布局区域\n\n## 代码示例\n\n### 基础环形布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### 螺旋状布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ComboCombinedLayout.en.md":"---\ntitle: ComboCombined Layout\norder: 4\n---\n\n## Overview\n\nComboCombined composite layout is suitable for graph data with composite group structures. It supports flexible configuration of the layout for elements inside combos as well as the layout between the outermost combos and nodes. By default, the internal elements use the Concentric layout, and the outer layout uses the gForce force-directed layout, balancing layout effect and overall stability. See more ComboCombined layout [examples](/en/examples#layout-combo-layout) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts).\n\n## Usage Scenarios\n\n- User profile analysis: Analyze user behavior and product relationships, use user interest circles as combos, display specific products and behavior tags as internal nodes, and help operators identify user consumption paths.\n- Supply chain management graph: Divide suppliers, manufacturers, warehouses, and distributors into combos by role or region, display resources, personnel, or equipment as internal nodes, and clearly show the internal structure of each link in the supply chain.\n\n## Options\n\n| Property     | Description                                                                                                                                        | Type                                                                                       | Default      | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------ | -------- |\n| type         | Layout type                                                                                                                                        | `combo-combined`                                                                           | -            | ✓        |\n| center       | Layout center                                                                                                                                      | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | Graph center |          |\n| layout       | Layout configuration. Can be fixed, or returned dynamically based on `comboId`                                                                     | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -            |          |\n| nodeSize     | Node size (diameter), used for collision detection                                                                                                 | `number` \\| `number[]` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number     | -            |          |\n| nodeSpacing  | Spacing between nodes                                                                                                                              | `number` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number                   | -            |          |\n| comboSpacing | Spacing between combos                                                                                                                             | `number` \\| (d?: unknown) => number                                                        | -            |          |\n| comboPadding | Padding value inside the combo, used only for force calculation, not for rendering. It is recommended to set the same value as the visual padding. | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -            |          |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\nIn `5.1`, it is recommended to use a single `layout` field to choose layouts for different levels, instead of configuring `innerLayout` and `outerLayout` separately.\n\n**Example**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ComboCombinedLayout.zh.md":"---\ntitle: 复合布局 ComboCombined\norder: 4\n---\n\n## 概述\n\nComboCombined 复合布局适用于复合分组结构的图数据展示场景，支持灵活配置 Combo 内部元素的布局以及最外层 Combo 和节点之间的布局。 默认情况内部元素采用 Concentric 同心圆布局，外部布局采用 gForce 力导向布局，兼顾布局效果与整体稳定性。参考更多 ComboCombined 复合布局[样例](/examples#layout-combo-layout)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts)\n\n## 使用场景\n\n- 用户画像分析: 分析用户行为与商品关系，将用户兴趣圈层作为 Combo，内部节点展示具体商品和行为标签，帮助运营人员识别用户消费路径。\n- 供应链管理图：供应商、制造商、仓储、分销商按角色或区域划分 Combo，内部节点展示资源、人员或设备，清晰展示供应链各环节内部结构。\n\n## 配置项\n\n| 属性         | 描述                                                                                                | 类型                                                                                       | 默认值 | 必选 |\n| ------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---- |\n| type         | 布局类型                                                                                            | `combo-combined`                                                                           | -      | ✓    |\n| center       | 布局中心                                                                                            | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | 图中心 |      |\n| layout       | 布局配置。可固定指定，也可根据 `comboId` 动态返回                                                   | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -      |      |\n| nodeSize     | 节点大小（直径）。用于碰撞检测                                                                      | `number` \\| `number[]` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number        | -      |      |\n| nodeSpacing  | 节点间距                                                                                            | `number` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number                      | -      |      |\n| comboSpacing | Combo 之间的间距                                                                                    | `number` \\| (d?: unknown) => number                                                        | -      |      |\n| comboPadding | Combo 内部的 padding 值，不用于渲染，仅用于计算力。推荐设置为与视图上 Combo 内部 padding 值相同的值 | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -      |      |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\n5.1 中推荐使用单个 `layout` 字段为不同层级选择布局，而不是分别配置 `innerLayout` 和 `outerLayout`。\n\n**示例**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## 示例代码\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CompactBoxLayout.en.md":"---\ntitle: CompactBox Layout\norder: 5\n---\n\n## Overview\n\nThe CompactBox layout is suitable for visualizing structured tree data. It is evolved from the classic [Reingold–Tilford tidy layout algorithm](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf), and considers the bounding box of each tree node during layout, effectively maintaining the compactness and hierarchical clarity of the tree structure. See more CompactBox layout [examples](/en/examples#layout-compact-box) and [source code](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox Tidy Tree Layout Example'/>\n\n## Usage Scenarios\n\n- Decision trees: The compact tree layout can visually and intuitively display each decision path.\n- Knowledge graphs: Show hierarchical relationships and connections between concepts. The compact layout can present complex knowledge networks in limited space.\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## Options\n\n| Property  | Description                                                                                                   | Type                                                         | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------- | -------- |\n| type      | Layout type                                                                                                   | `compact-box`                                                | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                       | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                   | `LR`    |          |\n| getSide   | Set whether the node is on the left or right of the root. Only works for `H` direction. [See below](#getside) | (d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string |         |          |\n| getId     | Callback for node id                                                                                          | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => string |         |          |\n| getWidth  | Callback for node width                                                                                       | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHeight | Callback for node height                                                                                      | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHGap   | Callback for horizontal gap                                                                                   | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getVGap   | Callback for vertical gap                                                                                     | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| radial    | Whether to enable radial layout, [see below](#radial)                                                         | boolean                                                      | false   |          |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\nTree layout direction\n\n- `TB`: Root at the top, layout downwards\n- `BT`: Root at the bottom, layout upwards\n- `LR`: Root at the left, layout to the right\n- `RL`: Root at the right, layout to the left\n- `H`: Root in the middle, horizontal symmetric layout. You can use `getSide` to specify the left/right logic for each node\n- `V`: Root in the middle, vertical symmetric layout\n\n### getSide\n\n> _(d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string_\n\nSet whether the node is on the left or right of the root. Only works for `H` direction. If not set, the algorithm will automatically assign left/right. See [getSide auto logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n({ data }) => {\n  // data is a node\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => string_\n\nCallback for node id\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node width\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node height\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for horizontal gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for vertical gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout. If `radial` is `true`, it is recommended to set `direction` to `'LR'` or `'RL'`.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CompactBoxLayout.zh.md":"---\ntitle: 紧凑树布局 CompactBox\norder: 5\n---\n\n## 概述\n\n紧凑树布局适用于结构化树形数据的展示，基于经典的 [Reingold–Tilford tidy 布局算法](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf) 演进而来，通过布局时综合考虑每个树节点的包围盒，有效保持树结构的紧凑性与层次清晰。参考更多 CompactBox 布局[样例](/examples#layout-compact-box)和[源码](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js)\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox 紧凑树布局示例'/>\n\n## 使用场景\n\n- 决策树: 通过紧凑树布局可简单直观的图形化展示每个决策路径\n- 知识图谱: 展示概念之间的层级关系和连接，紧凑布局可以在有限空间内呈现复杂的知识网络\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                                                                                    | 类型                                                      | 默认值 | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                                | `compact-box`                                             | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                          | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                | `LR`   |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在 `H` 布局方向上生效 | (d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string |        |      |\n| getId     | 节点 id 的回调函数                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => string |        |      |\n| getWidth  | 计算每个节点的宽度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHeight | 计算每个节点的高度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHGap   | 计算每个节点的水平间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getVGap   | 计算每个节点的垂直间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)                                                                     | boolean                                                   | false  |      |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\n树布局方向\n\n- `TB`：根节点在上，往下布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*KrAqTrFbNjMAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `BT`：根节点在下，往上布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vNmOTJ4q0uwAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `LR`：根节点在左，往右布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ffD6S74MXw4AAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `RL`：根节点在右，往左布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vTg2SJbtj_sAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `H`：根节点在中间，水平对称布局。可传入 `getSide` 方法指定每个节点的左右分布逻辑\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0GsIQISvieYAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n### getSide\n\n> _(d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在 `direction` 为 `H` 时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考 [getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n({ data }) => {\n  // data 是一个节点\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => string_\n\n节点 id 的回调函数\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\n是否按照辐射状布局。若 `radial` 为 `true`，建议 `direction` 设置为 `'LR'` 或 `'RL'`\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ConcentricLayout.en.md":"---\ntitle: Concentric Layout\norder: 6\n---\n\n## Overview\n\nThe concentric layout arranges nodes in layers according to a certain sorting rule, with each layer of nodes placed around a common center. See more concentric layout [examples](/en/examples#layout-concentric) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n- Layered data visualization, such as permission structures, organizational charts, etc., with the center as the top-level role and outer rings as lower-level nodes.\n- Visualization of ranking analysis results, with high-importance nodes in the center and low-importance nodes on the periphery, quickly expressing the relative influence of nodes in the graph.\n\n## Options\n\n| Property       | Description                                                                                                                                                                 | Type                                               | Default                                                   | Required |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- | -------- | --------- | --- |\n| type           | Layout type                                                                                                                                                                 | `concentric`                                       | -                                                         | ✓        |\n| center         | Center position of the circular layout, defaults to the center of the container                                                                                             | [number, number] \\| [number, number, number]       | -                                                         |          |\n| clockwise      | Whether to arrange nodes clockwise                                                                                                                                          | boolean                                            | false                                                     |          |\n| equidistant    | Whether the distance between rings is equal                                                                                                                                 | boolean                                            | false                                                     |          |\n| width          | Layout width, defaults to container width                                                                                                                                   | number                                             | -                                                         |          |\n| height         | Layout height, defaults to container height                                                                                                                                 | number                                             | -                                                         |          |\n| sortBy         | The property to sort by (node attribute name). The higher the value, the closer to the center. If set to 'degree', nodes with higher degree are placed closer to the center | string                                             | `degree`                                                  |          |\n| maxLevelDiff   | Maximum attribute difference in the same layer. If undefined, set to maxValue / 4, where maxValue is the maximum value of the sorting property                              | number                                             | undefined                                                 |          |\n| nodeSize       | Node size (diameter), used for collision detection                                                                                                                          | number \\| number[] \\| ((nodeData: Node) => number) | 30                                                        |          |\n| nodeSpacing    | Minimum spacing between rings, used to adjust the radius                                                                                                                    | number \\| number[] \\| ((node?: Node) => number)    | 10                                                        |          |\n| preventOverlap | Whether to prevent overlap. Must be used with nodeSize or data.size. Only works if node size is set in data or in this layout config.                                       | boolean                                            | false                                                     |          |\n| startAngle     | The angle (in radians) to start laying out nodes                                                                                                                            | number                                             | 3 / 2 \\* Math.PI                                          |          |\n| sweep          | The angle difference between the first and last node in the same layer. If undefined, it is set to `2 _ Math.PI _ (1 - 1 /                                                  | level.nodes                                        | )`, where `level.nodes` is the set of nodes in that layer | number   | undefined |     |\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: 'Center', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/ConcentricLayout.zh.md":"---\ntitle: 同心圆布局 Concentric\norder: 6\n---\n\n## 概述\n\n同心圆布局是一种将节点根据某种排序规则分层，并以圆心为中心、沿圆周排列每层节点的布局方式。参考更多同心圆布局[样例](/examples#layout-concentric)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n- 分层数据可视化，如权限控制结构、组织架构图等，中心是顶级角色，外圈为下级节点。\n- 排序分析结果可视化，高重要度放中心，低重要度放外围，快速表达图中节点的相对影响力。\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                        | 类型                                               | 默认值           | 必选 |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------- | ---- |\n| type           | 布局类型                                                                                                                                                                                                    | `concentric`                                       | -                | ✓    |\n| center         | 圆形布局的中心位置，默认为当前容器的中心位置                                                                                                                                                                | [number, number] \\| [number, number, number]       | -                |      |\n| clockwise      | 是否按照顺时针排列                                                                                                                                                                                          | boolean                                            | false            |\n| equidistant    | 环与环之间的距离是否相等                                                                                                                                                                                    | boolean                                            | false            |      |\n| width          | 布局的宽度，默认使用容器宽度                                                                                                                                                                                | number                                             | -                |      |\n| height         | 布局的高度，默认使用容器高度                                                                                                                                                                                | number                                             | -                |      |\n| sortBy         | 指定排序的依据（节点属性名）<br>数值越高则该节点被放置得越中心。若为 degree，则会计算节点的度数，度数越高，节点将被放置得越中心                                                                             | string                                             | `degree`         |      |\n| maxLevelDiff   | 同一层节点的最大属性差值<br>若为 undefined，则将会被设置为 maxValue / 4 ，其中 maxValue 为最大的排序依据的属性值。例如，若 sortBy 为 'degree'，则 maxValue 为所有节点中度数最大的节点的度数                 | number                                             | undefined        |      |\n| nodeSize       | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                                                                                                                                              | number \\| number[] \\| ((nodeData: Node) => number) | 30               |      |\n| nodeSpacing    | 环与环之间最小间距，用于调整半径                                                                                                                                                                            | number \\| number[] \\| ((node?: Node) => number)    | 10               |      |\n| preventOverlap | 是否防止重叠<br>必须配合 nodeSize 属性或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测                        | boolean                                            | false            |      |\n| startAngle     | 开始布局节点的弧度                                                                                                                                                                                          | number                                             | 3 / 2 \\* Math.PI |      |\n| sweep          | 同一层中第一个节点与最后一个节点之间的弧度差<br>若为 undefined ，则将会被设置为 2 \\* Math.PI \\* (1 - 1 / \\|level.nodes\\|) ，其中 level.nodes 为该算法计算出的每一层的节点，\\|level.nodes\\| 代表该层节点数量 | number                                             | undefined        |      |\n\n## 代码示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/D3Force3DLayout.en.md":"---\ntitle: 3D Force-Directed Layout\norder: 7\n---\n\n## Overview\n\nThe D3Force3D layout is a 3D extension based on [d3-force](https://d3js.org/d3-force), which simulates physical forces in three-dimensional space to achieve automatic layout. Compared to 2D layouts, it adds force effects in the Z-axis direction, allowing richer data relationships to be displayed in 3D space.\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D Force-Directed Layout Illustration\" />\n\n## Core Concepts\n\n### Force System\n\nD3Force3D extends the traditional 2D force-directed layout with the following forces:\n\n- **3D Centering Force**: Pulls nodes toward the center point in 3D space\n- **3D Collision Force**: Prevents node overlap in 3D space\n- **3D Radial Force**: Attracts nodes to a sphere in 3D space\n- **3D Axis Forces**: Applies forces along the X, Y, and Z axes\n\n### Iteration System\n\nThe layout is computed through iterations, mainly involving the following parameters:\n\n- **alpha**: The current energy value of the iteration, controlling node movement speed\n- **alphaDecay**: The decay rate of the energy value\n- **alphaMin**: The minimum energy value; iteration stops below this value\n- **velocityDecay**: The velocity decay factor\n\n## Options\n\n| Property        | Description                                                      | Type                                                                       | Default       | Required |\n| --------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------- | -------- |\n| type            | Layout type                                                      | string                                                                     | `d3-force-3d` | ✓        |\n| nodeSize        | Node size (diameter), used for collision detection               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -             |          |\n| iterations      | Number of force iterations; higher means more precise but slower | number                                                                     | -             |          |\n| numDimensions   | Number of dimensions (2 or 3)                                    | number                                                                     | 3             |          |\n| forceSimulation | Custom force simulation method                                   | Simulation<NodeDatum, EdgeDatum>                                           | -             |          |\n| onTick          | Callback for each iteration                                      | (data: LayoutMapping) => void                                              | -             |          |\n| randomSource    | Random number generator                                          | () => number                                                               | -             |          |\n\n### Iteration Control\n\n| Property      | Description                   | Type   | Default | Required |\n| ------------- | ----------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold | number | 1       |          |\n| alphaDecay    | Convergence decay rate (0-1)  | number | 0.028   |          |\n| alphaMin      | Stop iteration threshold      | number | 0.001   |          |\n| alphaTarget   | Target convergence threshold  | number | 0       |          |\n| velocityDecay | Velocity decay factor         | number | 0.4     |          |\n\n### Force Model Options\n\n#### Centering Force (center)\n\n| Property        | Description         | Type   | Default | Required |\n| --------------- | ------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate | number | 0       |          |\n| center.y        | Center y coordinate | number | 0       |          |\n| center.z        | Center z coordinate | number | 0       |          |\n| center.strength | Force strength      | number | 1       |          |\n\n#### Collision Force (collide)\n\n| Property           | Description          | Type                                                                       | Default | Required |\n| ------------------ | -------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| collide.radius     | Collision radius     | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10      |          |\n| collide.strength   | Force strength       | number                                                                     | 1       |          |\n| collide.iterations | Collision iterations | number                                                                     | 1       |          |\n\n#### Link Force (link)\n\n| Property        | Description           | Type                                                                       | Default | Required |\n| --------------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| link.id         | Edge id generator     | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |          |\n| link.distance   | Ideal edge length     | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |          |\n| link.strength   | Force strength        | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |          |\n| link.iterations | Link force iterations | number                                                                     | 1       |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                  | Type                                                                       | Default  | Required |\n| -------------------- | ---------------------------- | -------------------------------------------------------------------------- | -------- | -------- |\n| manyBody.strength    | Force strength               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy          | number                                                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum interaction distance | number                                                                     | 1        |          |\n| manyBody.distanceMax | Maximum interaction distance | number                                                                     | Infinity |          |\n\n#### Radial Force (radial)\n\n| Property        | Description     | Type                                                                       | Default | Required |\n| --------------- | --------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| radial.strength | Force strength  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1     |          |\n| radial.radius   | Target radius   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100     |          |\n| radial.x        | Sphere center x | number                                                                     | 0       |          |\n| radial.y        | Sphere center y | number                                                                     | 0       |          |\n| radial.z        | Sphere center z | number                                                                     | 0       |          |\n\n#### Axis Forces (x, y, z)\n\nEach axis can be configured separately:\n\n| Property   | Description           | Type                                                                       | Default | Required |\n| ---------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| x.strength | X-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| x.x        | Target x coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.strength | Y-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.y        | Target y coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.strength | Z-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.z        | Target z coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n","packages/site/docs/manual/layout/D3Force3DLayout.zh.md":"---\ntitle: 3D D3力导向布局 D3Force3D\norder: 7\n---\n\n## 概述\n\nD3Force3D 布局是基于 [d3-force](https://d3js.org/d3-force) 的三维扩展版本，通过在三维空间中模拟物理力的作用来实现自动布局。相比二维布局，它增加了 Z 轴方向的力作用，能够在三维空间中展现更丰富的数据关系。\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D 力导向布局示意图\" />\n\n## 核心概念\n\n### 力系统\n\nD3Force3D 在传统二维力导向布局的基础上，扩展了以下力的作用：\n\n- **三维中心力**：将节点拉向三维空间的中心点\n- **三维碰撞力**：在三维空间中防止节点重叠\n- **三维径向力**：将节点吸引到三维空间中的球面上\n- **三维坐标力**：分别在 X、Y、Z 三个方向上施加作用力\n\n### 迭代系统\n\n布局计算通过迭代来实现，主要涉及以下参数：\n\n- **alpha**：当前迭代的活力值，控制节点移动速度\n- **alphaDecay**：活力值的衰减率\n- **alphaMin**：最小活力值，低于此值停止迭代\n- **velocityDecay**：速度衰减因子\n\n## 配置项\n\n| 属性            | 描述                                         | 类型                                                                       | 默认值        | 必选 |\n| --------------- | -------------------------------------------- | -------------------------------------------------------------------------- | ------------- | ---- |\n| type            | 布局类型                                     | string                                                                     | `d3-force-3d` | ✓    |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10            |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大 | number                                                                     | -             |      |\n| numDimensions   | 维度数量，固定为 3                           | number                                                                     | 3             |      |\n| forceSimulation | 自定义力模拟方法                             | Simulation<NodeDatum, EdgeDatum>                                           | -             |      |\n| onTick          | 每次迭代的回调函数                           | (data: LayoutMapping) => void                                              | -             |      |\n| randomSource    | 随机数生成函数                               | () => number                                                               | -             |      |\n\n### 迭代控制\n\n| 属性          | 描述                  | 类型   | 默认值 | 必选 |\n| ------------- | --------------------- | ------ | ------ | ---- |\n| alpha         | 当前迭代收敛阈值      | number | 1      |      |\n| alphaDecay    | 收敛阈值衰减率（0-1） | number | 0.028  |      |\n| alphaMin      | 停止迭代的阈值        | number | 0.001  |      |\n| alphaTarget   | 目标收敛阈值          | number | 0      |      |\n| velocityDecay | 速度衰减因子          | number | 0.4    |      |\n\n### 力模型配置\n\n#### 中心力（center）\n\n| 属性            | 描述          | 类型   | 默认值 | 必选 |\n| --------------- | ------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标 | number | 0      |      |\n| center.y        | 中心点 y 坐标 | number | 0      |      |\n| center.z        | 中心点 z 坐标 | number | 0      |      |\n| center.strength | 力的强度      | number | 1      |      |\n\n#### 碰撞力（collide）\n\n| 属性               | 描述               | 类型                                                                       | 默认值 | 必选 |\n| ------------------ | ------------------ | -------------------------------------------------------------------------- | ------ | ---- |\n| collide.radius     | 碰撞半径           | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10     |      |\n| collide.strength   | 力的强度           | number                                                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数 | number                                                                     | 1      |      |\n\n#### 链接力（link）\n\n| 属性            | 描述             | 类型                                                                       | 默认值  | 必选 |\n| --------------- | ---------------- | -------------------------------------------------------------------------- | ------- | ---- |\n| link.id         | 边的 id 生成函数 | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |      |\n| link.distance   | 理想边长         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |      |\n| link.strength   | 力的强度         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |      |\n| link.iterations | 链接力的迭代次数 | number                                                                     | 1       |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                      | 类型                                                                       | 默认值   | 必选 |\n| -------------------- | ------------------------- | -------------------------------------------------------------------------- | -------- | ---- |\n| manyBody.strength    | 力的强度                  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数 | number                                                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离              | number                                                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离              | number                                                                     | Infinity |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述        | 类型                                                                       | 默认值 | 必选 |\n| --------------- | ----------- | -------------------------------------------------------------------------- | ------ | ---- |\n| radial.strength | 力的强度    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1    |      |\n| radial.radius   | 目标半径    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100    |      |\n| radial.x        | 球心 x 坐标 | number                                                                     | 0      |      |\n| radial.y        | 球心 y 坐标 | number                                                                     | 0      |      |\n| radial.z        | 球心 z 坐标 | number                                                                     | 0      |      |\n\n#### 坐标力（x、y、z）\n\n每个方向的力可以单独配置：\n\n| 属性       | 描述             | 类型                                                                       | 默认值 | 必选 |\n| ---------- | ---------------- | -------------------------------------------------------------------------- | ------ | ---- |\n| x.strength | X 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| x.x        | 目标 x 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.strength | Y 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.y        | 目标 y 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.strength | Z 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.z        | 目标 z 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n","packages/site/docs/manual/layout/D3ForceLayout.en.md":"---\ntitle: D3 Force-Directed Layout\norder: 8\n---\n\n## Overview\n\nThe D3Force layout is a force-directed layout based on [d3-force](https://d3js.org/d3-force). It simulates physical forces (such as attraction, repulsion, collision, etc.) to make the graph reach a stable state with minimal energy.\n\nThe main features of this layout are:\n\n1. **Automatic arrangement**: No need to manually set node positions, the system will automatically find suitable positions\n2. **Real-time adjustment**: When you drag a node, other nodes will adjust their positions in real time\n3. **Flexible configuration**:\n   - You can adjust the attraction and repulsion between nodes\n   - You can set the ideal length of edges\n   - You can fix the positions of important nodes\n4. **Animation effect**: Nodes move with smooth animation, making changes more natural\n\n<img alt=\"D3Force layout diagram\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Core Concepts\n\n### Force System\n\nThe D3Force layout simulates five different forces to achieve automatic layout. Imagine a physical world where these forces act simultaneously and eventually reach equilibrium:\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> Note: The arrows of different colors in the diagram represent different types of forces. In the actual layout, these forces are invisible and also affected by other forces.\n\n- **Link Force**: Imagine nodes connected by rubber bands, which pull connected nodes to a suitable distance. The tightness of the rubber band is the force strength, and the ideal length is the distance we set.\n- **Many-Body Force**: Similar to magnets, it allows all nodes to attract or repel each other. When the force strength is negative, nodes repel each other (like like poles of magnets); when positive, they attract (like opposite poles). This force determines the density of the graph.\n- **Center Force**: Like all nodes are tied to the center of the canvas by an invisible string. This force prevents nodes from drifting too far and keeps the graph centered.\n- **Collision Force**: Treats nodes as solid balls. When nodes get too close, they automatically bounce apart. This force mainly prevents node overlap and improves readability.\n- **Radial Force**: Imagine an invisible ring that attracts nodes to the ring. By setting the radius and force strength, nodes can form a beautiful circular layout.\n\n### Iteration System\n\nLayout calculation is an iterative process with two key concepts:\n\n#### Alpha Value (Energy)\n\nLike the \"energy\" of the layout, it determines how vigorously nodes move:\n\n- **Initial state**: Alpha = 1, nodes move vigorously\n- **During calculation**: Alpha gradually decreases, node movement slows\n- **End state**: When Alpha < alphaMin, nodes stop moving\n\n#### Iterations\n\nControls the number of times forces are applied in each calculation:\n\n- **Effect**: The larger the value, the more precise the layout, but the slower the computation\n- **Adjustment**:\n  - Simple graphs: use the default value\n  - Complex graphs: increase the number of iterations as needed\n  - Real-time interaction: use fewer iterations\n\n> Tip: Iterations and alpha value work together. Increasing iterations makes each step more precise, while alpha controls the overall progress.\n\n## Options\n\n| Property        | Description                                        | Type                                       | Default    | Required |\n| --------------- | -------------------------------------------------- | ------------------------------------------ | ---------- | -------- |\n| type            | Layout type                                        | string                                     | 'd3-force' | ✓        |\n| centerX         | Layout center x coordinate                         | number                                     | width / 2  |          |\n| centerY         | Layout center y coordinate                         | number                                     | height / 2 |          |\n| centerStrength  | Center force strength                              | number                                     | -          |          |\n| nodeSize        | Node size (diameter), for collision detection      | number \\| ((node, index, nodes) => number) | 10         |          |\n| nodeSpacing     | Extra spacing between nodes                        | number \\| ((node, index, nodes) => number) | 0          |          |\n| iterations      | Number of force iterations, higher is more precise | number                                     | -          |          |\n| onTick          | Callback for each iteration, for real-time results | (data: LayoutMapping) => void              | -          |          |\n| forceSimulation | Custom force simulation, defaults to d3.js method  | Simulation<NodeDatum, EdgeDatum>           | -          |          |\n| randomSource    | Function to generate random numbers                | () => number                               | -          |          |\n\n### Iteration Control\n\n| Property      | Description                                          | Type   | Default | Required |\n| ------------- | ---------------------------------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold, controls activity     | number | 1       |          |\n| alphaMin      | Minimum threshold to stop, when alpha < this, stop   | number | 0.001   |          |\n| alphaDecay    | Decay rate of alpha, [0, 1], 0.028 ≈ 300 iterations  | number | 0.028   |          |\n| alphaTarget   | Target alpha, system tries to converge to this value | number | 0       |          |\n| velocityDecay | Velocity decay factor, higher means slower movement  | number | 0.4     |          |\n\n### Force Model Options\n\n#### Link Force (link)\n\n| Property        | Description                                  | Type                                       | Default     | Required |\n| --------------- | -------------------------------------------- | ------------------------------------------ | ----------- | -------- |\n| link.id         | Function to generate edge id                 | (edge, index, edges) => string             | (e) => e.id |          |\n| link.distance   | Ideal edge length                            | number \\| ((edge, index, edges) => number) | 30          |          |\n| link.strength   | Force strength, higher means closer to ideal | number \\| ((edge, index, edges) => number) | 1           |          |\n| link.iterations | Number of link force iterations              | number                                     | 1           |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                                                     | Type                                       | Default  | Required |\n| -------------------- | --------------------------------------------------------------- | ------------------------------------------ | -------- | -------- |\n| manyBody.strength    | Force strength, negative for repulsion, positive for attraction | number \\| ((node, index, nodes) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy, smaller is more accurate                   | number                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum distance, prevents excessive force                      | number                                     | 1        |          |\n| manyBody.distanceMax | Maximum distance, beyond which no force is applied              | number                                     | Infinity |          |\n\n#### Center Force (center)\n\n| Property        | Description                                   | Type   | Default | Required |\n| --------------- | --------------------------------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate                           | number | -       |          |\n| center.y        | Center y coordinate                           | number | -       |          |\n| center.strength | Force strength, higher means closer to center | number | -       |          |\n\n> Note: In `5.1`, `centerX` / `centerY` are the recommended shortcut fields. If you configure the `center` force directly, it follows the native `d3-force` style.\n\n#### Collision Force (collide)\n\n| Property           | Description                                     | Type                                       | Default | Required |\n| ------------------ | ----------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| collide.radius     | Collision radius, nodes repel if closer         | number \\| ((node, index, nodes) => number) | 10      |          |\n| collide.strength   | Force strength, higher means stronger repulsion | number                                     | 1       |          |\n| collide.iterations | Number of collision iterations                  | number                                     | 1       |          |\n\n#### Radial Force (radial)\n\n| Property        | Description                                   | Type                                       | Default | Required |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| radial.strength | Force strength, higher means closer to radius | number \\| ((node, index, nodes) => number) | 0.1     |          |\n| radial.radius   | Target radius, nodes are attracted to circle  | number \\| ((node, index, nodes) => number) | 100     |          |\n| radial.x        | Center x coordinate                           | number                                     | 0       |          |\n| radial.y        | Center y coordinate                           | number                                     | 0       |          |\n\n#### X Axis Force (x)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| x.strength | Force strength in x direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| x.x        | Target x coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n#### Y Axis Force (y)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| y.strength | Force strength in y direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| y.y        | Target y coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n## Code Examples\n\n### Prevent Node Overlap\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\nSee [Example - Prevent Node Overlap in Force-Directed Layout](/en/examples/layout/force-directed/#prevent-overlap)\n\n### Team Clustering Layout\n\nThis example shows how to use force-directed layout for team clustering, where nodes of different teams automatically cluster together.\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // Team A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // Team B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // Team C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // Team A internal connections\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // Team B internal connections\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // Team C internal connections\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // Few connections between teams\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// Create mock data with nodes from different teams\nconst data = {\n  nodes: [\n    // Team A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // Team B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // Team C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // Team A internal connections\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // Team B internal connections\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // Team C internal connections\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // Few connections between teams\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\nMain configuration notes:\n\n- `link.distance`: Shorter within teams, longer between teams\n- `link.strength`: Stronger within teams, weaker between teams\n- `manyBody.strength`: Controls repulsion between nodes\n- `collide`: Prevents node overlap\n- `center`: Keeps the layout centered\n\nSee also [Customize parameters for different nodes](/en/examples/layout/force-directed/#functional-params).\n","packages/site/docs/manual/layout/D3ForceLayout.zh.md":"---\ntitle: D3力导向布局 D3Force\norder: 8\n---\n\n## 概述\n\nD3Force 布局是基于 [d3-force](https://d3js.org/d3-force) 实现的力导向布局。它通过模拟物理力的作用（如引力、斥力、碰撞等），使图布局达到一个能量最小的稳定状态。\n\n这种布局的主要特点是：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的理想长度\n   - 可以固定某些重要节点的位置\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img alt=\"D3Force 布局示意图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 核心概念\n\n### 力系统 Force System\n\nD3Force 布局通过模拟五种不同的力来实现自动布局。想象一个物理世界，这些力同时作用，最终达到平衡：\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> 注：图中不同颜色的箭头代表不同类型的力，实际布局中这些力是无形的，同时也会受其他力影响。\n\n- **链接力**（Link Force）：想象节点之间连着橡皮筋，可以把相连的节点拉到合适的距离。橡皮筋的松紧度就是力的强度（strength），理想长度就是我们设置的距离（distance）。\n- **多体力**（Many-Body Force）：类似磁铁的效果，可以让所有节点互相吸引或排斥。力的强度为负值时节点会互相排斥（像相同磁极），为正值时会互相吸引（像相反磁极）。这个力决定了图的疏密程度。\n- **中心力**（Center Force）：就像所有节点都被一根看不见的绳子拴在画布中心。这个力可以防止节点飘得太远，让整个图保持在画布的中心位置。\n- **碰撞力**（Collision Force）：让节点变成有实体大小的小球，当节点太近时会自动弹开。这个力主要用来防止节点重叠，提高图的可读性。\n- **径向力**（Radial Force）：想象有一个看不见的圆环，这个力会把节点吸引到圆环上。通过设置圆的半径和力的强度，可以让节点形成漂亮的环形布局。\n\n### 迭代系统（Iteration System）\n\n布局计算是一个反复调整的过程，包含两个关键概念：\n\n#### Alpha 值（活力值）\n\n就像布局的\"能量\"，决定节点移动的剧烈程度：\n\n- **初始状态**：Alpha = 1，节点移动剧烈\n- **计算过程**：Alpha 值逐渐降低，节点移动变缓\n- **结束状态**：当 Alpha < alphaMin 时，节点停止移动\n\n#### 迭代次数（Iterations）\n\n控制每次计算时力的作用次数：\n\n- **作用**：值越大，布局越精确，但计算越慢\n- **调节**：\n  - 简单图：使用默认值即可\n  - 复杂图：可以适当增加迭代次数\n  - 实时交互：建议使用较小的迭代次数\n\n> 提示：迭代次数（iterations）和活力值（alpha）是相互配合的。增加迭代次数可以让每一步计算更精确，而活力值则控制整体计算的进度。\n\n## 配置项\n\n| 属性            | 描述                                          | 类型                                       | 默认值     | 必选 |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ---------- | ---- |\n| type            | 布局类型                                      | string                                     | 'd3-force' | ✓    |\n| centerX         | 布局中心点 x 坐标                             | number                                     | width / 2  |      |\n| centerY         | 布局中心点 y 坐标                             | number                                     | height / 2 |      |\n| centerStrength  | 中心力强度                                    | number                                     | -          |      |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠    | number \\| ((node, index, nodes) => number) | 10         |      |\n| nodeSpacing     | 节点间额外间距                                | number \\| ((node, index, nodes) => number) | 0          |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大  | number                                     | -          |      |\n| onTick          | 每次迭代的回调函数，用于实时获取布局结果      | (data: LayoutMapping) => void              | -          |      |\n| forceSimulation | 自定义力模拟方法，若不指定则使用 d3.js 的方法 | Simulation<NodeDatum, EdgeDatum>           | -          |      |\n| randomSource    | 用于生成随机数的函数                          | () => number                               | -          |      |\n\n### 迭代控制\n\n| 属性          | 描述                                                   | 类型   | 默认值 | 必选 |\n| ------------- | ------------------------------------------------------ | ------ | ------ | ---- |\n| alpha         | 当前迭代的收敛阈值，控制布局的活跃程度                 | number | 1      |      |\n| alphaMin      | 停止迭代的最小阈值，当 alpha 小于该值时停止迭代        | number | 0.001  |      |\n| alphaDecay    | 收敛阈值的衰减率，范围 [0, 1]，0.028 对应约 300 次迭代 | number | 0.028  |      |\n| alphaTarget   | 目标收敛阈值，系统会尝试将 alpha 收敛到该值            | number | 0      |      |\n| velocityDecay | 速度衰减因子，值越大节点运动越缓慢                     | number | 0.4    |      |\n\n### 力模型配置\n\n#### 链接力（link）\n\n| 属性            | 描述                               | 类型                                       | 默认值      | 必选 |\n| --------------- | ---------------------------------- | ------------------------------------------ | ----------- | ---- |\n| link.id         | 边的 id 生成函数                   | (edge, index, edges) => string             | (e) => e.id |      |\n| link.distance   | 理想边长，边会趋向于该长度         | number \\| ((edge, index, edges) => number) | 30          |      |\n| link.strength   | 力的强度，值越大边长越接近理想边长 | number \\| ((edge, index, edges) => number) | 1           |      |\n| link.iterations | 链接力的迭代次数                   | number                                     | 1           |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                                                  | 类型                                       | 默认值   | 必选 |\n| -------------------- | ----------------------------------------------------- | ------------------------------------------ | -------- | ---- |\n| manyBody.strength    | 力的强度，负值为斥力，正值为引力                      | number \\| ((node, index, nodes) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数，值越小越精确但性能消耗越大 | number                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离，防止力过大                              | number                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离，超过该距离的节点不产生力                | number                                     | Infinity |      |\n\n#### 中心力（center）\n\n| 属性            | 描述                               | 类型   | 默认值 | 必选 |\n| --------------- | ---------------------------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标                      | number | -      |      |\n| center.y        | 中心点 y 坐标                      | number | -      |      |\n| center.strength | 力的强度，值越大节点越趋向于中心点 | number | -      |      |\n\n> 补充：5.1 中推荐优先使用 `centerX` / `centerY` 作为快捷配置；如果直接配置 `center` force，则按 d3-force 原生写法生效。\n\n#### 碰撞力（collide）\n\n| 属性               | 描述                                   | 类型                                       | 默认值 | 必选 |\n| ------------------ | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| collide.radius     | 碰撞半径，小于该距离的节点会产生排斥力 | number \\| ((node, index, nodes) => number) | 10     |      |\n| collide.strength   | 力的强度，值越大排斥效果越明显         | number                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数                     | number                                     | 1      |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述                                   | 类型                                       | 默认值 | 必选 |\n| --------------- | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| radial.strength | 力的强度，值越大节点越趋向于目标半径   | number \\| ((node, index, nodes) => number) | 0.1    |      |\n| radial.radius   | 目标半径，节点会被吸引到该半径的圆周上 | number \\| ((node, index, nodes) => number) | 100    |      |\n| radial.x        | 圆心 x 坐标                            | number                                     | 0      |      |\n| radial.y        | 圆心 y 坐标                            | number                                     | 0      |      |\n\n#### X 轴力（x）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| x.strength | X 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| x.x        | 目标 x 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n#### Y 轴力（y）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| y.strength | Y 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| y.y        | 目标 y 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n## 代码示例\n\n### 防止节点重叠\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\n效果见 [示例 - 力导向布局防止节点重叠](/examples/layout/force-directed/#prevent-overlap)\n\n### 团队聚类布局\n\n该示例展示了如何使用力导向布局实现团队聚类效果，不同团队的节点会自动聚集在一起。\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // 团队 A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // 团队 B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // 团队 C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // 团队 A 内部连接\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // 团队 B 内部连接\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // 团队 C 内部连接\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // 团队间的少量连接\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 创建模拟数据，包含不同团队的节点\nconst data = {\n  nodes: [\n    // 团队 A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // 团队 B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // 团队 C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // 团队 A 内部连接\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // 团队 B 内部连接\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // 团队 C 内部连接\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // 团队间的少量连接\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\n主要配置说明：\n\n- `link.distance`：团队内部距离短，团队间距离长\n- `link.strength`：团队内部连接强度大，团队间连接强度小\n- `manyBody.strength`：控制节点间排斥力\n- `collide`：防止节点重叠\n- `center`：保持整体布局在画布中心\n\n还可以参考 [定制不同节点的参数](/examples/layout/force-directed/#functional-params) 示例。\n","packages/site/docs/manual/layout/DagreLayout.en.md":"---\ntitle: Dagre Layout\norder: 9\n---\n\n# Dagre Layout\n\n## Overview\n\nDagre is a hierarchical layout suitable for directed acyclic graphs (DAGs). It can automatically handle the direction and spacing between nodes and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## Options\n\n> For more options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Illustration\" />\n\n| Property        | Description                                                                                                                                | Type                                                | Default           | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- | ----------------- | -------- |\n| type            | Layout type                                                                                                                                | `dagre`                                             | -                 | ✓        |\n| rankdir         | Layout direction, options                                                                                                                  | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |          |\n| align           | Node alignment, options                                                                                                                    | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |          |\n| nodesep         | Node spacing (px). For `TB` or `BT`, it is the horizontal spacing; for `LR` or `RL`, it is the vertical spacing                            | number                                              | 50                |          |\n| ranksep         | Rank spacing (px). For `TB` or `BT`, it is the vertical spacing between adjacent ranks; for `LR` or `RL`, it is the horizontal spacing     | number                                              | 100               |          |\n| ranker          | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                 | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |          |\n| directed        | Whether to treat the graph as directed                                                                                                     | boolean                                             | true              |          |\n| compound        | Whether to support nested structures                                                                                                       | boolean                                             | true              |          |\n| multigraph      | Whether to allow multi-edges                                                                                                               | boolean                                             | true              |          |\n| nodeSize        | G6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |          |\n| edgeMinLen      | Minimum number of ranks crossed by an edge                                                                                                 | number \\| (edge) => number                          | 1                 |          |\n| edgeWeight      | Edge weight, used to affect optimization priority                                                                                          | number \\| (edge) => number                          |                   |          |\n| edgeLabelSize   | Edge label size, used to reserve layout space                                                                                              | number[] \\| (edge) => number[]                      |                   |          |\n| edgeLabelPos    | Edge label position                                                                                                                        | string \\| (edge) => string                          |                   |          |\n| edgeLabelOffset | Offset between the label and the edge                                                                                                      | number \\| (edge) => number                          |                   |          |\n\n> Note: `dagre` does not require configuring `controlPoints` separately. G6 automatically converts the polyline points returned by the layout into `style.controlPoints` on the edge.\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`, **Default**: `TB`\n\nLayout direction\n\n- `TB`: Top to Bottom;\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='Top to Bottom Layout'/>\n\n- `BT`: Bottom to Top;\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='Bottom to Top Layout'/>\n\n- `LR`: Left to Right;\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='Left to Right Layout'/>\n\n- `RL`: Right to Left.\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='Right to Left Layout'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`, **Default**: `UL`\n\nNode alignment\n\n- `UL`: Upper Left\n- `UR`: Upper Right\n- `DL`: Down Left\n- `DR`: Down Right\n\n### nodesep\n\n> number, **Default**: 50\n\nNode spacing (px). For `TB` or `BT`, it's the horizontal spacing; for `LR` or `RL`, it's the vertical spacing\n\n### ranksep\n\n> number, **Default**: 50\n\nRank spacing (px). For `TB` or `BT`, it's the vertical spacing between ranks; for `LR` or `RL`, it's the horizontal spacing between ranks\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`, **Default**: `network-simplex`\n\nAlgorithm for assigning ranks to nodes, supports three algorithms:\n\n- `longest-path`: Uses DFS to recursively find the longest path for each node. Simple and fast, but may result in many long edges.\n- `tight-tree`: An optimization algorithm to reduce the number of long edges. It first uses `longest-path` to compute initial ranks, then adjusts slack edges to build a feasible tree.\n- `network-simplex`: Based on [A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf), iteratively modifies node ranks to minimize slack edges.\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]`\n\n```js\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n## Applicable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, automatically handling direction and spacing between nodes.\n- **Dependency Graphs**: Display dependencies between packages or modules.\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks.\n\n## Related Documentation\n\n> The following documents can help you better understand Dagre layout\n\n- [Graph Layout Algorithms｜Detailed Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Interpretation of Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/DagreLayout.zh.md":"---\ntitle: Dagre 布局\norder: 9\n---\n\n## 概述\n\nDagre 是一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## 配置项\n\n> 更多配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性            | 描述                                                                                                                                            | 类型                                                | 默认值            | 必选 |\n| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ----------------- | ---- |\n| type            | 布局类型                                                                                                                                        | `dagre`                                             | -                 | ✓    |\n| rankdir         | 布局方向，可选值                                                                                                                                | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |      |\n| align           | 节点对齐方式，可选值                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |      |\n| nodesep         | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                              | number                                              | 50                |      |\n| ranksep         | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                            | number                                              | 100               |      |\n| ranker          | 为每个节点分配等级的算法，共支持三种算法，分别是：`longest-path`、`tight-tree`、`network-simplex`                                               | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |      |\n| directed        | 是否按有向图处理                                                                                                                                | boolean                                             | true              |      |\n| compound        | 是否支持嵌套结构                                                                                                                                | boolean                                             | true              |      |\n| multigraph      | 是否允许多重边                                                                                                                                  | boolean                                             | true              |      |\n| nodeSize        | G6 自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个 number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |      |\n| edgeMinLen      | 边跨越的最小层数                                                                                                                                | number \\| (edge) => number                          | 1                 |      |\n| edgeWeight      | 边权重，用于影响优化优先级                                                                                                                      | number \\| (edge) => number                          |                   |      |\n| edgeLabelSize   | 边标签尺寸，用于预留空间                                                                                                                        | number[] \\| (edge) => number[]                      |                   |      |\n| edgeLabelPos    | 边标签位置                                                                                                                                      | string \\| (edge) => string                          |                   |      |\n| edgeLabelOffset | 标签与边的偏移                                                                                                                                  | number \\| (edge) => number                          |                   |      |\n\n> 补充：`dagre` 不需要单独配置 `controlPoints`，G6 会把布局输出的折线点自动转换为边的 `style.controlPoints`。\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`， **Default**: `TB`\n\n布局方向\n\n- `TB`：从上到下；\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='：从上到下布局'/>\n\n- `BT`：从下到上；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='从下到上布局'/>\n\n- `LR`：从左到右；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='从左到右布局'/>\n\n- `RL`：从右到左。\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='水平布局'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`， **Default**: `UL`\n\n节点对齐方式\n\n- `UL`：左上对齐\n- `UR`：右上对齐\n- `DL`：左下对齐\n- `DR`：右下对齐\n\n### nodesep\n\n> number， **Default**: 50\n\n节点间距（px）。在rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距\n\n### ranksep\n\n> number， **Default**: 50\n\n层间距（px）。在rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`， **Default**: `network-simplex`\n\n为每个节点分配层级的算法，共支持三种算法，分别是：\n\n- `longest-path`： 最长路径算法，使用DFS深度优先搜索，递归查找每个节点的最长路径。优点是计算简单速度快，但会导致长边过多；\n- `tight-tree`： 紧凑树算法，一种优化算法，目的是减少长边的数量。先用最长路径算法`longest-path`计算出初始层级，然后调整松弛边的长度，从而构建可行树。\n- `network-simplex`： 网络单形法，参考算法[A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf)，核心思想是迭代修改节点的层级，缩小松弛边。\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]`\n\n```js\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n### controlPoints\n\n> boolean， **Default**: false\n\n是否保留边的控制点。\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/DendrogramLayout.en.md":"---\ntitle: Dendrogram Layout\norder: 10\n---\n\n## Overview\n\nThe dendrogram layout is suitable for visualizing hierarchical clustering data. Its feature is that all child nodes are laid out on the same level, node size is not considered, and each node is treated as 1px.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='Dendrogram Layout Example'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"Dendrogram Layout Options Illustration\" />\n\n| Property  | Description                                            | Type                                       | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------------------------------ | ------- | -------- |\n| type      | Layout type                                            | `dendrogram`                               | -       | ✓        |\n| direction | Layout direction, [options](#direction)                | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`    |          |\n| nodeSep   | Node spacing, distance between nodes on the same level | number                                     | 20      |          |\n| rankSep   | Rank spacing, distance between different levels        | number                                     | 200     |          |\n| radial    | Whether to enable radial layout, [see below](#radial)  | boolean                                    | false   |          |\n\n### direction\n\nTree layout direction options:\n\n- `TB`: Root at the top, layout downward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB direction'/>\n\n- `BT`: Root at the bottom, layout upward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT direction'/>\n\n- `LR`: Root at the left, layout to the right\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR direction'/>\n\n- `RL`: Root at the right, layout to the left\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL direction'/>\n\n- `H`: Root in the middle, horizontal symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H direction'/>\n\n- `V`: Root in the middle, vertical symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V direction'/>\n\n### radial\n\nWhether to enable radial layout mode. When enabled, nodes are distributed radially around the root node.\n\nIf `radial` is set to `true`, it is recommended to set `direction` to `'LR'` or `'RL'` for best results.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='Radial Layout'/>\n","packages/site/docs/manual/layout/DendrogramLayout.zh.md":"---\ntitle: 生态树 Dendrogram\norder: 10\n---\n\n## 概述\n\n生态树布局适用于层次聚类数据的可视化，其特点是所有子节点布局在同一层级，不考虑节点大小，每个节点被当成 1px 处理。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='生态树布局示例'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"生态树配置项图解\" />\n\n| 属性      | 描述                                           | 类型                                       | 默认值 | 必选 |\n| --------- | ---------------------------------------------- | ------------------------------------------ | ------ | ---- |\n| type      | 布局类型                                       | `dendrogram`                               | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                 | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`   |      |\n| nodeSep   | 节点间距，即同一层级节点之间的距离，单位为像素 | number                                     | 20     |      |\n| rankSep   | 层级间距，即不同层级之间的距离，单位为像素     | number                                     | 200    |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)            | boolean                                    | false  |      |\n\n### direction\n\n树布局的方向，有以下选项：\n\n- `TB`：根节点在上，往下布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB方向'/>\n\n- `BT`：根节点在下，往上布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT方向'/>\n\n- `LR`：根节点在左，往右布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR方向'/>\n\n- `RL`：根节点在右，往左布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL方向'/>\n\n- `H`：根节点在中间，水平对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H方向'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V方向'/>\n\n### radial\n\n是否启用辐射状布局模式。启用后，节点将以根节点为中心呈辐射状分布。\n\n若 `radial` 设置为 `true`，建议将 `direction` 设置为 `'LR'` 或 `'RL'` 以获得最佳效果。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='辐射状布局'/>\n","packages/site/docs/manual/layout/Fishbone.en.md":"---\ntitle: Fishbone Layout\norder: 11\n---\n\n## Overview\n\nFishbone layout is a graphical layout specifically designed for representing hierarchical data. By simulating the shape of a fishbone, it arranges data nodes according to their hierarchy, making the hierarchical relationships of the data clearer and more intuitive. Fishbone layout is especially suitable for datasets that need to show causality, hierarchy, or classification information.\n\n## Use Cases\n\n- Displaying hierarchical data, such as organizational structures or classification systems\n- Showing problem analysis processes, such as fault analysis or quality analysis\n- Displaying decision processes, such as decision trees or factor analysis\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## Options\n\n| Property               | Description                                                                                      | Type                                                                                                                                   | Default  | Required |\n| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- |\n| type                   | Layout type                                                                                      | `fishbone`                                                                                                                             | -        | ✓        |\n| direction              | Layout direction, `RL` (right to left, head on right), `LR` (left to right, head on left)        | `RL` \\| `LR`                                                                                                                           | `RL`     |          |\n| hGap                   | Horizontal gap                                                                                   | number                                                                                                                                 | -        |          |\n| vGap                   | Vertical gap                                                                                     | number                                                                                                                                 | -        |          |\n| getRibSep              | Function to get rib gap                                                                          | (node: NodeData) => number                                                                                                             | () => 60 |          |\n| width                  | Layout width                                                                                     | number                                                                                                                                 | -        |          |\n| height                 | Layout height                                                                                    | number                                                                                                                                 | -        |          |\n| nodeSize               | Node size                                                                                        | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (effective when preLayout is true)                 | boolean                                                                                                                                | -        |          |\n| nodeFilter             | Nodes to participate in this layout                                                              | (node: NodeData) => boolean                                                                                                            | -        |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements (not suitable for pipeline layout) | boolean                                                                                                                                | -        |          |\n\n## Code Example\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Real Case\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone Layout](/en/examples/layout/fishbone/#basic)\n","packages/site/docs/manual/layout/Fishbone.zh.md":"---\ntitle: 鱼骨布局 Fishbone\norder: 11\n---\n\n## 概述\n\n鱼骨布局是一种专门用于表示层次结构数据的图形布局方式。它通过模拟鱼骨的形状，将数据节点按照层次结构排列，使得数据的层次关系更加清晰直观。鱼骨布局特别适用于需要展示因果关系、层次结构或分类信息的数据集。\n\n## 使用场景\n\n- 需要展示层次结构数据，如组织结构、分类体系\n- 需要展示问题分析过程，如故障分析、质量分析\n- 需要展示决策过程，如决策树、影响因素分析\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## 配置项\n\n| 属性                   | 描述                                                       | 类型                                                                                                                                   | 默认值   | 必选 |\n| ---------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type                   | 布局类型                                                   | `fishbone`                                                                                                                             | -        | ✓    |\n| direction              | 排布方向，`RL` 从右到左，鱼头在右；`LR` 从左到右，鱼头在左 | `RL` \\| `LR`                                                                                                                           | `RL`     |      |\n| hGap                   | 水平间距                                                   | number                                                                                                                                 | -        |      |\n| vGap                   | 垂直间距                                                   | number                                                                                                                                 | -        |      |\n| getRibSep              | 获取鱼骨间距                                               | (node: NodeData) => number                                                                                                             | () => 60 |      |\n| width                  | 布局宽度                                                   | number                                                                                                                                 | -        |      |\n| height                 | 布局高度                                                   | number                                                                                                                                 | -        |      |\n| nodeSize               | 节点大小                                                   | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局，当 preLayout 为 true 时生效        | boolean                                                                                                                                | -        |      |\n| nodeFilter             | 参与该布局的节点                                           | (node: NodeData) => boolean                                                                                                            | -        |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局，不适用于流水线布局     | boolean                                                                                                                                | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone布局](/examples/layout/fishbone/#basic)\n","packages/site/docs/manual/layout/ForceAtlas2Layout.en.md":"---\ntitle: ForceAtlas2 Force-directed Layout\norder: 12\n---\n\n## Overview\n\nForceAtlas2 is a force-directed layout algorithm that optimizes node positions by simulating forces in a physical system. This layout is especially suitable for visualizing large-scale network data, effectively revealing relationships and cluster structures among nodes.\n\n## Use Cases\n\n- Social network analysis: Display user relationship networks, with node degree reflecting user influence\n- Knowledge graphs: Show associations between concepts, discover knowledge domains through clustering\n- System architecture diagrams: Show dependencies between system components, highlight core components via hub mode\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## Options\n\n| Property       | Description                                                                                                                                                                   | Type                                | Default  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | -------- |\n| type           | Layout type, must be `force-atlas2`                                                                                                                                           | `force-atlas2`                      | -        | ✓        |\n| maxIteration   | Maximum number of iterations                                                                                                                                                  | number                              | 500      |          |\n| minMovement    | Convergence threshold                                                                                                                                                         | number                              | 0.4      |          |\n| barnesHut      | Whether to enable quadtree acceleration. When enabled, improves performance for large graphs but may affect layout quality. By default, enabled if node count > 250.          | boolean                             | -        |          |\n| dissuadeHubs   | Whether to enable hub mode. If true, nodes with higher in-degree are more likely to be placed at the center than those with high out-degree                                   | boolean                             | false    |          |\n| height         | Layout height. Defaults to container height                                                                                                                                   | number                              | -        |          |\n| kg             | Gravity coefficient. The larger the value, the more concentrated the layout is at the center                                                                                  | number                              | 1        |          |\n| kr             | Repulsion coefficient. Adjusts the compactness of the layout. The larger the value, the looser the layout                                                                     | number                              | 5        |          |\n| ks             | Controls the speed of node movement during iteration                                                                                                                          | number                              | 0.1      |          |\n| ksmax          | Maximum node movement speed during iteration                                                                                                                                  | number                              | 10       |          |\n| mode           | Clustering mode. In `linlog` mode, clusters are more compact                                                                                                                  | `normal` \\| `linlog`                | `normal` |          |\n| nodeSize       | Node size (diameter). Used for repulsion calculation when `preventOverlap` is enabled. If not set, uses `data.size` in node data                                              | Size \\| ((node?: Node) => Size)     | -        |          |\n| nodeSpacing    | Spacing between nodes                                                                                                                                                         | number \\| ((node?: Node) => number) | -        |          |\n| onTick         | Callback for each iteration                                                                                                                                                   | (data: LayoutMapping) => void       | -        |          |\n| preventOverlap | Whether to prevent node overlap. When enabled, layout considers node size to avoid overlap. Node size is specified by `nodeSize` or `data.size` in node data                  | boolean                             | false    |          |\n| prune          | Whether to enable auto-pruning. By default, enabled if node count > 100. Pruning speeds up convergence but may reduce layout quality. Set to false to disable auto-activation | boolean                             | -        |          |\n| tao            | Tolerance for stopping oscillation when layout is near convergence                                                                                                            | number                              | 0.1      |          |\n| width          | Layout width. Defaults to container width                                                                                                                                     | number                              | -        |          |\n| center         | Layout center, format [x, y]. Each node is attracted to this point, gravity controlled by `kg`. If not set, uses canvas center                                                | [number, number]                    | -        |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## Real Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2 Layout](/en/examples/layout/force-directed/#atlas2)\n","packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md":"---\ntitle: ForceAtlas2 力导向布局\norder: 12\n---\n\n## 概述\n\nForceAtlas2 是一种基于力导向的布局算法，它通过模拟物理系统中的力来优化节点位置。该布局特别适用于大规模网络数据的可视化，能够有效地展示节点之间的关系和聚类结构。\n\n## 使用场景\n\n- 社交网络分析：展示用户之间的关系网络，通过节点度数反映用户影响力\n- 知识图谱：展示概念之间的关联关系，通过聚类效果发现知识领域\n- 系统架构图：展示系统组件之间的依赖关系，通过 hub 模式突出核心组件\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                 | 类型                                | 默认值   | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | ---- |\n| type           | 布局类型，必须为 `force-atlas2`                                                                                                                                      | `force-atlas2`                      | -        | ✓    |\n| maxIteration   | 最大迭代次数                                                                                                                                                         | number                              | 500      |      |\n| minMovement    | 收敛阈值                                                                                                                                                             | number                              | 0.4      |      |\n| barnesHut      | 是否开启四叉树加速，开启后可以提升大规模图的布局性能，但可能会影响布局质量。默认情况下为 undefined，当节点数量大于 250 时它将会被激活。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| dissuadeHubs   | 是否开启 hub 模式。若为 true，相比与出度大的节点，入度大的节点将会有更高的优先级被放置在中心位置                                                                     | boolean                             | false    |      |\n| height         | 布局高度，默认使用容器高度                                                                                                                                           | number                              | -        |      |\n| kg             | 重力系数，`kg` 越大，布局越聚集在中心                                                                                                                                | number                              | 1        |      |\n| kr             | 斥力系数，可用于调整布局的紧凑程度。kr 越大，布局越松散                                                                                                              | number                              | 5        |      |\n| ks             | 控制迭代过程中，节点移动的速度                                                                                                                                       | number                              | 0.1      |      |\n| ksmax          | 迭代过程中，最大的节点移动的速度上限                                                                                                                                 | number                              | 10       |      |\n| mode           | 聚类模式，`linlog` 模式下，聚类将更加紧凑                                                                                                                            | `normal` \\| `linlog`                | `normal` |      |\n| nodeSize       | 节点大小（直径）。当开启 `preventOverlap` 时，用于计算节点之间的斥力。如果不设置，则使用节点数据中的 size 属性                                                       | Size \\| ((node?: Node) => Size)     | -        |      |\n| nodeSpacing    | 节点间距                                                                                                                                                             | number \\| ((node?: Node) => number) | -        |      |\n| onTick         | 每一次迭代的回调函数                                                                                                                                                 | (data: LayoutMapping) => void       | -        |      |\n| preventOverlap | 是否防止节点重叠。开启后，布局会考虑节点大小，避免节点重叠                                                                                                           | boolean                             | false    |      |\n| prune          | 是否开启自动剪枝模式。默认情况下为 undefined，当节点数量大于 100 时它将会被激活。注意，剪枝能够提高收敛速度，但可能会降低图的布局质量。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| tao            | 迭代接近收敛时停止震荡的容忍度                                                                                                                                       | number                              | 0.1      |      |\n| width          | 布局宽度，默认使用容器宽度                                                                                                                                           | number                              | -        |      |\n| center         | 布局中心点，用于指定重力的中心，格式为 [x, y]。每个节点都会受到一个指向该中心点的重力，重力大小由 `kg` 参数控制。如果不设置，则使用画布中心点                        | [number, number]                    | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2布局](/examples/layout/force-directed/#atlas2)\n","packages/site/docs/manual/layout/ForceLayout.en.md":"---\ntitle: Force-directed Layout\norder: 13\n---\n\n## Overview\n\nForce-directed layout is a graph layout algorithm based on physical simulation that determines node positions by simulating attraction and repulsion forces between nodes. This layout is particularly suitable for displaying complex relationship networks, such as social networks and knowledge graphs.\n\nThe force-directed layout automatically calculates and adjusts node positions to maintain appropriate distances between connected nodes while minimizing edge crossings. During the layout process, it simulates a physical system where nodes repel each other like charged particles, and edges connect nodes like springs.\n\nKey features of force-directed layout include:\n\n1. **Automatic Arrangement**: No need to manually set node positions, the system automatically finds suitable positions\n2. **Real-time Adjustment**: When you drag a node, other nodes will adjust their positions in real-time\n3. **Flexible Configuration**:\n   - Can adjust attraction and repulsion forces between nodes\n   - Can set edge lengths\n   - Can prevent node overlap\n4. **Animation Effects**: Smooth animations during node movement make changes more natural\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='Force-directed Layout Example'/>\n\n## Core Concepts\n\n### Basic Principles of Force-directed Layout\n\nForce-directed layout is a graph layout algorithm based on physical simulation that models nodes and edges as a physical system:\n\n- Nodes are treated as physical particles\n- Edges are treated as springs\n- The entire system reaches its lowest energy state through physical simulation\n\n### Detailed Core Forces\n\n#### Node Repulsion\n\n- **Physical Model**: Coulomb's Law\n- **Function**: Prevents node overlap and ensures more uniform node distribution, where `factor` and `coulombDisScale` control the overall strength and range of repulsion.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='Repulsion Force'/>\n\n  - k: Repulsion coefficient (`factor` / `coulombDisScale²`)\n  - q1,q2: Node strength (`nodeStrength`)\n  - r: Distance between nodes\n\n#### Edge Attraction\n\n- **Physical Model**: Hooke's Law\n- **Function**: Simulates edge tension, moving nodes along edge directions, where `edgeStrength` and `linkDistance` control edge \"stiffness\" and length.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='Edge Attraction'/>\n\n  - ka: Edge attraction strength (`edgeStrength`)\n  - L: Edge length (`linkDistance`)\n  - r: Actual edge length\n\n#### Centripetal Force\n\n- **Physical Model**: Newton's Universal Law of Gravitation\n- **Function**: Attracts nodes toward the canvas center or cluster centers, where `gravity` and `center` control gravity strength and center point position\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Centripetal Force'/>\n\n  - G: Gravitational constant (`gravity`)\n  - xc: Center point coordinates (`center`)\n  - mass: Node mass (`nodeSize`)\n\n#### Interaction of Three Forces\n\n- **Physical Model**: Force interactions, generating acceleration\n- **Function**: Repulsion, edge attraction, and centripetal force work together, affecting node movement through acceleration superposition, ultimately reaching the lowest energy state.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Force Interactions'/>\n\n### Physical System\n\n#### Node Velocity Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='Node Velocity Formula'/>\n\n  - v: Velocity\n  - a: Acceleration\n  - dt: Time step (`interval`)\n  - damping: Damping coefficient (`damping`)\n\n- **Function**:\n  1. Controls node movement stability\n  2. Damping coefficient prevents system oscillation\n  3. Time step affects displacement per iteration\n\n#### Node Position Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='Node Position Formula'/>\n\n  - x: Node position\n  - v: Node velocity\n  - dt: Time step (`interval`)\n\n- **Function**:\n  1. Updates node position based on velocity\n  2. Ensures motion continuity\n  3. Prevents node overlap through `preventOverlap`\n\n#### Cluster Center Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='Cluster Center Calculation'/>\n\n  - n: Number of nodes in cluster\n  - (xi​,yi​): Position of each node\n\n- **Function**:\n  1. Calculates cluster center\n  2. Centripetal force pulls nodes toward their cluster center\n  3. Cluster center can change dynamically\n\n#### Cluster Strength Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='Cluster Strength Calculation'/>\n\n  - s: Cluster strength (`clusterNodeStrength`)\n  - xc​: Cluster center\n\n- **Function**:\n  1. Controls cluster compactness\n  2. Higher cluster strength means tighter clusters\n  3. Can be dynamically adjusted based on node properties\n\n#### Mass Effect on Forces\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='Mass Effect on Forces'/>\n\n  - a: Acceleration\n  - F: Force (repulsion, edge attraction, centripetal force)\n  - mass: Node mass\n\n- **Function**:\n  1. Nodes with larger mass move less\n  2. Nodes with smaller mass move more\n  3. Mass calculation can be customized through `getMass`\n\n#### Energy Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='Energy Calculation'/>\n\n  - m: Node mass\n  - v: Node velocity\n\n- **Function**:\n  1. Monitors layout convergence\n  2. System stabilizes when energy approaches zero\n\n#### System Convergence Condition\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='System Convergence Condition'/>\n\n- **Function**:\n  1. Controls iteration count\n  2. Stops when movement is below threshold\n  3. Can choose between mean, maximum, or minimum through `distanceThresholdMode`\n\n### Force Interaction Diagram\n\n```mermaid\ngraph TD\n    A[Input] --> B[Initialize Parameters];\n    B --> C[Build Layout Calculation];\n    C --> D[Iterative Calculation];\n    D --> E{Converged?};\n    E -->|Yes| F[Output Layout];\n    E -->|No| G[Calculate Repulsion];\n    G --> H[Calculate Edge Attraction];\n    H --> I[Calculate Centripetal Force];\n    I --> J[Update Velocity];\n    J --> K[Update Position];\n    K --> D;\n```\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/BOu7Rbuz4MoAAAAAQjAAAAgADpdRAQFr/original' alt='Force Simulation Diagram'/>\n\n## Configuration Options\n\nBased on the physical characteristics of force-directed layout, the following configuration options are available:\n\n### Basic Configuration\n\n| Property              | Description                                                                                                                                                                                                                                        | Default Value | Required |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type                  | Layout type                                                                                                                                                                                                                                        | `force`       | ✓        |\n| dimensions            | Layout dimensions, 2 for 2D layout, 3 for 3D layout                                                                                                                                                                                                | 2             |          |\n| width                 | Layout width                                                                                                                                                                                                                                       | Canvas width  |          |\n| height                | Layout height                                                                                                                                                                                                                                      | Canvas height |          |\n| center                | Layout center point                                                                                                                                                                                                                                | Graph center  |          |\n| maxIteration          | Maximum iteration count, if 0 will auto-adjust                                                                                                                                                                                                     | 0             |          |\n| minMovement           | Stop iteration when average movement distance is less than 0.4                                                                                                                                                                                     | 0.4           |          |\n| distanceThresholdMode | Movement distance calculation mode: mean: stop when average movement distance is less than `minMovement`; max: stop when maximum movement distance is less than `minMovement`; min: stop when minimum movement distance is less than `minMovement` | `mean`        |          |\n| maxDistance           | Maximum distance                                                                                                                                                                                                                                   |               |          |\n\n### Force-related Configuration\n\n#### Repulsion Configuration\n\n| Property        | Description                                                                                         | Default Value | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| nodeStrength    | Node force, positive values represent attraction between nodes, negative values represent repulsion | 1000          |          |\n| factor          | Repulsion coefficient, larger values mean stronger repulsion                                        | 1             |          |\n| coulombDisScale | Coulomb coefficient, a factor for repulsion, larger values mean stronger repulsion between nodes    | 0.005         |          |\n\n#### Edge Attraction Configuration\n\n| Property     | Description                                                                                                    | Default Value | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| edgeStrength | Edge force (attraction) strength, fixed force or callback function to dynamically return different edge forces | 500           |          |\n| linkDistance | Edge length, fixed length or callback function to dynamically return different edge lengths                    | 200           |          |\n\n#### Centripetal Force Configuration\n\n| Property           | Description                                                                                                                                                                                                                                                          | Default Value | Required |\n| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| gravity            | Center force strength, the force attracting all nodes to the center. Larger values mean more compact layout                                                                                                                                                          | 10            |          |\n| centripetalOptions | Centripetal force configuration, including center and strength for leaf nodes, isolated nodes, and other nodes. leaf: leaf node centripetal force; single: single node centripetal force; others: other node centripetal force; center: custom center point function | [0, 0]        |          |\n\n#### Clustering Configuration\n\n| Property            | Description                                                                                                                                                                                                                                                                                                                                                   | Default Value | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| clustering          | Whether to cluster all nodes. If true, will use the field specified by nodeClusterBy in node data for clustering. centripetalOptions.single, centripetalOptions.leaf, and centripetalOptions.others will use the value returned by getClusterNodeStrength; leaf and centripetalOptions.center will use the average center of all nodes in the current cluster | `false`       |          |\n| nodeClusterBy       | Specifies the field name in node data for clustering. Takes effect when clustering is true. Automatically generates centripetalOptions, can be used with clusterNodeStrength                                                                                                                                                                                  |               |          |\n| clusterNodeStrength | Used with clustering and nodeClusterBy to specify the strength of the cluster centripetal force                                                                                                                                                                                                                                                               |               |          |\n| leafCluster         | Whether to cluster leaf nodes. If true, centripetalOptions.single will be 100; centripetalOptions.leaf will use the value returned by getClusterNodeStrength; getClusterNodeStrength.center will return the average center of all leaf nodes                                                                                                                  | false         |          |\n\n#### Performance and Optimization Configuration\n\n| Property        | Description                                                                                                                                                                                                                                                               | Default Value | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| damping         | Damping coefficient, range [0, 1]. Larger values mean slower speed decrease                                                                                                                                                                                               | 0.9           |          |\n| maxSpeed        | Maximum movement length per iteration                                                                                                                                                                                                                                     | 200           |          |\n| interval        | Controls the movement speed of each node per iteration                                                                                                                                                                                                                    | 0.02          |          |\n| preventOverlap  | Whether to prevent overlap. Must be used with nodeSize or data.size in node data. Only when data.size is set in the data or nodeSize is configured in the layout with the same value as the node size in the graph, collision detection for node overlap can be performed | true          |          |\n| nodeSize        | Node size (diameter). Used for collision detection to prevent node overlap. Fixed size or callback function to dynamically return node size                                                                                                                               |               |          |\n| nodeSpacing     | Takes effect when preventOverlap is true. Minimum spacing between node edges to prevent overlap. Can be a callback to set different spacing for different nodes                                                                                                           |               |          |\n| collideStrength | Strength of anti-overlap force, range [0, 1]                                                                                                                                                                                                                              | 1             |          |\n\n#### Other Configuration\n\n| Property  | Description                                                                                                                                                                              | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| getMass   | Callback for the mass of each node. The parameter is the node's internal data, and the return value is the mass                                                                          |               |          |\n| getCenter | Callback for the x, y, and strength of the centripetal force for each node. If not specified, no extra centripetal force is applied                                                      |               |          |\n| onTick    | Callback for each iteration                                                                                                                                                              |               |          |\n| monitor   | Callback for monitoring each iteration. energy indicates the convergence energy of the layout. May incur extra computation if configured; if not configured, no computation is performed |               |          |\n\n## Code Examples\n\n### Basic Usage\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Layout width\n    width: 800,\n    // Layout height\n    height: 600,\n  },\n});\n```\n\n### Preventing Node Overlap\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n  },\n});\n```\n\n### Force-directed Layout\n\nThis example demonstrates how to create a basic force-directed graph using force-directed layout.\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Centripetal force\n    gravity: 0.9,\n    // Iteration count\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\nKey configuration explanations:\n\n- `preventOverlap`: Enable node overlap detection\n- `nodeSize`: Set node size\n- `gravity`: Set node centripetal force\n- `iterations`: Set layout calculation precision\n\nYou can also refer to [View Examples](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) for more usage examples.\n","packages/site/docs/manual/layout/ForceLayout.zh.md":"---\ntitle: Force 力导向布局\norder: 13\n---\n\n## 概述\n\n力导向布局是一种基于物理模拟的图布局算法，它通过模拟节点间的引力和斥力来确定节点的位置。这种布局方式特别适合展示复杂的关系网络，如社交网络、知识图谱等。\n\n力导向布局会自动计算并调整节点位置，使得相连的节点保持适当的距离，同时尽量减少边的交叉。布局过程中会模拟物理系统，节点会像带电粒子一样相互排斥，边则像弹簧一样连接节点。\n\n力导向布局的主要特点包括：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的长度\n   - 可以防止节点重叠\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='力导向布局示例'/>\n\n## 核心概念\n\n### Force 力导向布局基本原理\n\n力导向布局是一种基于物理模拟的图布局算法，它将图中的节点和边模拟为物理系统：\n\n- 节点被视为物理粒子\n- 边被视为弹簧\n- 整个系统通过物理模拟达到能量最低状态\n\n### 核心力详解\n\n#### 斥力（Node Repulsion）\n\n- **物理模型**：库伦定律（Coulomb's Law）\n- **作用**：防止节点重叠，让节点分布更均匀，其中 `factor` 和 `coulombDisScale` 控制斥力的总体强度和范围。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='斥力'/>\n\n  - k: 斥力系数（`factor` / `coulombDisScale²`）\n  - q1,q2: 节点强度(`nodeStrength`)\n  - r: 节点间距离\n\n#### 边拉力（Edge Attraction）\n\n- **物理模型**：胡克定律（Hooke's Law）\n- **作用**：模拟边的拉力，使节点沿着边的方向移动，其中 `edgeStrength` 和 `linkDistance` 控制边的“硬度”和长度。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='边拉力'/>\n\n  - ka: 边拉力强度（`edgeStrength`）\n  - L: 边的长度（`linkDistance`）\n  - r: 实际边长度\n\n#### 向心力（Gravity）\n\n- **物理模型**：牛顿万有引力定律（Newton's Universal Law of Gravitational）\n- **作用**：使节点向画布中心或者聚类中心聚集，其中 `gravity` 和 `center` 控制重力强度和中心点位置\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='向心力'/>\n\n  - G: 万有引力常数（`gravity`）\n  - xc: 中心点坐标（`center`）\n  - mass: 节点质量（`nodeSize`）\n\n#### 三种力的相互作用\n\n- **物理模型**：力的相互作用，产生加速度\n- **作用**：斥力、边拉力、向心力共同作用，通过加速度叠加影响节点运动，最终达到能量最低状态。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='力的相互作用'/>\n\n### 物理系统\n\n#### 节点运动速度公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='节点运动速度公式'/>\n\n  - v: 速度\n  - a: 加速度\n  - dt: 时间步长（`interval`）\n  - damping: 阻尼系数（`damping`）\n\n- **作用**：\n  1. 控制节点移动的稳定性\n  2. 阻尼系数防止系统震荡\n  3. 时间步长影响每次迭代的位移\n\n#### 节点位置公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='节点位置公式'/>\n\n  - x: 节点位置\n  - v: 节点速度\n  - dt: 时间步长（`interval`）\n\n- **作用**：\n  1. 根据速度更新节点位置\n  2. 确保运动连续性\n  3. 通过 `preventOverlap` 防止节点重叠\n\n#### 聚类中心计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='聚类中心计算'/>\n\n  - n: 聚类内节点数量\n  - (xi​,yi​): 每个节点的位置\n\n- **作用**：\n  1. 计算聚类中心\n  2. 向心力将节点拉向所属聚类中心\n  3. 聚类中心可动态变化\n\n#### 聚类强度计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='聚类强度计算'/>\n\n  - s: 聚类强度（`clusterNodeStrength`）\n  - xc​: 聚类中心\n\n- **作用**：\n  1. 控制聚类的紧密程度\n  2. 聚类强度越大，聚类越紧凑\n  3. 可根据节点属性动态调整\n\n#### 质量对力的影响\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='质量对力的影响'/>\n\n  - a: 加速度\n  - F: 力（斥力、边拉力、向心力）\n  - mass: 节点质量\n\n- **作用**：\n  1. 质量大的节点移动较小\n  2. 质量小的节点移动较大\n  3. 通过 `getMass` 可自定义质量计算\n\n#### 能量计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='能量计算'/>\n\n  - m: 节点质量\n  - v: 节点速度\n\n- **作用**：\n  1. 监控布局收敛情况\n  2. 能量趋近于零时系统趋于稳定\n\n#### 系统收敛条件\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='系统收敛条件'/>\n\n- **作用**：\n  1. 控制迭代次数\n  2. 移动量小于阈值时停止\n  3. 通过 `distanceThresholdMode` 可选择平均值、最大值或最小值\n\n### 力相互作用图\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2lI1RruANXoAAAAAAAAAAAAADpdRAQFr/original' alt='力作用模拟图'/>\n\n## 配置项\n\n根据上述力导向布局的物理特性，有以下配置项：\n\n### 基础配置\n\n| 属性                  | 描述                                                                                                                                                         | 默认值   | 必选 |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ---- |\n| type                  | 布局类型                                                                                                                                                     | `force`  | ✓    |\n| dimensions            | 布局维度，2表示2D布局，3表示3D布局                                                                                                                           | 2        |      |\n| width                 | 布局宽度                                                                                                                                                     | 画布宽度 |      |\n| height                | 布局高度                                                                                                                                                     | 画布高度 |      |\n| center                | 布局的中心点                                                                                                                                                 | 图中心   |      |\n| maxIteration          | 最大迭代次数，若为 0 则将自动调整                                                                                                                            | 0        |      |\n| minMovement           | 当平均移动距离小于0.4时停止迭代                                                                                                                              | 0.4      |      |\n| distanceThresholdMode | 移动距离的计算模式：mean: 平均移动距离小于 `minMovement` 时停止迭代；max: 最大移动距离小于时 `minMovement` 时停止迭代；min: 最小移动距离小于时 `minMovement` | `mean`   |      |\n| maxDistance           | 最大距离                                                                                                                                                     |          |      |\n\n### 力相关配置\n\n#### 斥力配置\n\n| 属性            | 描述                                                               | 默认值 | 必选 |\n| --------------- | ------------------------------------------------------------------ | ------ | ---- |\n| nodeStrength    | 节点作用力，正数代表节点之间的引力作用，负数代表节点之间的斥力作用 | 1000   |      |\n| factor          | 斥力系数，数值越大，斥力越大                                       | 1      |      |\n| coulombDisScale | 库伦系数，斥力的一个系数，数字越大，节点之间的斥力越大             | 0.005  |      |\n\n#### 边拉力配置\n\n| 属性         | 描述                                                               | 默认值 | 必选 |\n| ------------ | ------------------------------------------------------------------ | ------ | ---- |\n| edgeStrength | 边的作用力（引力）大小，固定作用力或回调函数动态返回不同边的作用力 | 500    |      |\n| linkDistance | 边的长度，固定长度或回调函数动态返回不同边的长度                   | 200    |      |\n\n#### 向心力配置\n\n| 属性               | 描述                                                                                                                                                         | 默认值 | 必选 |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ---- |\n| gravity            | 向中心力大小，指所有节点被吸引到 center 的力。数字越大，布局越紧凑                                                                                           | 10     |      |\n| centripetalOptions | 向心力配置，包括叶子节点、离散点、其他节点的向心中心及向心力大小。leaf: 叶子节点向心力；single: 单点向心力；others: 其他节点向心力；center: 自定义中心点函数 | [0, 0] |      |\n\n#### 聚类配置\n\n| 属性                | 描述                                                                                                                                                                                                                                                                                                      | 默认值  | 必选 |\n| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---- |\n| clustering          | 是否需要全部节点聚类，若为 `true`，将使用 `nodeClusterBy` 配置的节点数据中的字段作为聚类依据。 `centripetalOptions.single`、`centripetalOptions.leaf`、`centripetalOptions.others` 将使用 `getClusterNodeStrength` 返回值；`leaf`、`centripetalOptions.center` 将使用当前节点所属聚类中所有节点的平均中心 | `false` |      |\n| nodeClusterBy       | 指定节点数据中的字段名称作为节点聚类的依据，`clustering` 为 true 时生效，自动生成 `centripetalOptions`，可配合 `clusterNodeStrength` 使用                                                                                                                                                                 |         |      |\n| clusterNodeStrength | 配合 `clustering` 和 `nodeClusterBy` 使用，指定聚类向心力的大小                                                                                                                                                                                                                                           |         |      |\n| leafCluster         | 是否需要叶子节点聚类，若为 `true`，则 `centripetalOptions.single` 将为 100；`centripetalOptions.leaf` 将使用 `getClusterNodeStrength` 返回值；`getClusterNodeStrength.center` 将为叶子节点返回当前所有叶子节点的平均中心                                                                                  | false   |      |\n\n#### 性能与优化配置\n\n| 属性            | 描述                                                                                                                                                                                           | 默认值 | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| damping         | 阻尼系数，取值范围 [0, 1]。数字越大，速度降低得越慢                                                                                                                                            | 0.9    |      |\n| maxSpeed        | 一次迭代的最大移动长度                                                                                                                                                                         | 200    |      |\n| interval        | 控制每个迭代节点的移动速度                                                                                                                                                                     | 0.02   |      |\n| preventOverlap  | 是否防止重叠，必须配合下面属性 `nodeSize` 或节点数据中的 `data.size` 属性，只有在数据中设置了 `data.size` 或在该布局中配置了与当前图节点大小相同的 `nodeSize` 值，才能够进行节点重叠的碰撞检测 | true   |      |\n| nodeSize        | 节点大小（直径）。用于防止节点重叠时的碰撞检测，固定大小或者回调函数动态返回节点大小                                                                                                           |        |      |\n| nodeSpacing     | `preventOverlap` 为 `true` 时生效, 防止重叠时节点边缘间距的最小值。可以是回调函数, 为不同节点设置不同的最小间距                                                                                |        |      |\n| collideStrength | 防止重叠的力强度，范围 [0, 1]                                                                                                                                                                  | 1      |      |\n\n#### 其他配置\n\n| 属性      | 描述                                                                                                                                                                                                | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| getMass   | 获取节点质量的回调函数，入参为节点内部流转数据，用于计算节点质量大小                                                                                                                                |        |      |\n| getCenter | 每个节点中心力的 x、y、强度的回调函数，若不指定，则没有额外中心力                                                                                                                                   |        |      |\n| onTick    | 每一次迭代的回调函数                                                                                                                                                                                |        |      |\n| monitor   | 每个迭代的监控信息回调，energy 表示布局的收敛能量。若配置可能带来额外的计算能量性能消耗，不配置则不计算。入参为迭代监控信息 `{ energy: number; nodes: Node[]; edges: Edge[]; iterations: number; }` |        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 布局宽度\n    width: 800,\n    // 布局高度\n    height: 600,\n  },\n});\n```\n\n### 防止节点重叠\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n  },\n});\n```\n\n### 力导向布局\n\n该示例展示了如何使用力导向布局创建一个基础的力导向图。\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 向心力\n    gravity: 0.9,\n    // 迭代次数\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\n主要配置说明：\n\n- `preventOverlap`: 开启节点重叠检测\n- `nodeSize`: 设置节点大小\n- `gravity`: 设置节点向心力\n- `iterations`: 设置布局计算的精确程度\n\n还可以参考 [查看示例](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) 获取更多用法。\n","packages/site/docs/manual/layout/FruchtermanLayout.en.md":"---\ntitle: Fruchterman Force-directed Layout\norder: 14\n---\n\n## Overview\n\nThe Fruchterman layout is a force-directed layout based on the algorithm from [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf). By flexibly configuring parameters to simulate physical forces, the layout automatically reaches a stable equilibrium state with minimal energy. It supports both basic uniform distribution and cluster layouts. See more Fruchterman force-directed layout [examples](/en/examples#layout-fruchterman) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts).\n\n## Use Cases\n\n- Basic uniform distribution: Suitable for displaying network graphs with evenly distributed nodes and clear overall structure, such as network topology and knowledge graphs.\n- Cluster layout: Suitable for visualizing data with internal aggregation or grouping, such as community structure display and association group analysis.\n\n## Options\n\n| Property     | Description                                                                                                                                                                                        | Type                                                                                                       | Default          | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------- | -------- |\n| type         | Layout type                                                                                                                                                                                        | `'fruchterman'`                                                                                            | -                | ✓        |\n| height       | Layout height                                                                                                                                                                                      | `number`                                                                                                   | container height |          |\n| width        | Layout width                                                                                                                                                                                       | `number`                                                                                                   | container width  |          |\n| maxIteration | Maximum number of iterations                                                                                                                                                                       | `number`                                                                                                   | 500              |          |\n| minMovement  | Convergence threshold                                                                                                                                                                              | `number`                                                                                                   | 0.4              |          |\n| gravity      | Central force, i.e., the force attracting all nodes to the [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915). The larger the value, the more compact the layout | `number`                                                                                                   | 10               |          |\n| speed        | Node movement speed per iteration. Too high a speed may cause strong oscillation                                                                                                                   | `number`                                                                                                   | 5                |          |\n| onTick       | Callback for each iteration                                                                                                                                                                        | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -                |          |\n\n### Cluster Layout\n\n| Property       | Description                                                                               | Type      | Default     | Required |\n| -------------- | ----------------------------------------------------------------------------------------- | --------- | ----------- | -------- |\n| clustering     | Whether to use cluster layout                                                             | `boolean` | `false`     |          |\n| nodeClusterBy  | Field name in node data for clustering, effective when `clustering` is true               | `string`  | `'cluster'` |          |\n| clusterGravity | Gravity within clusters, affects cluster compactness, effective when `clustering` is true | `number`  | 10          |          |\n\n## Example Code\n\n### Basic Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### Cluster Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/FruchtermanLayout.zh.md":"---\ntitle: Fruchterman 力导向布局\norder: 14\n---\n\n## 概述\n\nFruchterman 布局是基于 [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf) 算法实现的一种力导向布局，通过灵活的参数配置模拟物理作用，使整个布局自动达到能量最小的稳定平衡状态，支持基础均匀分布和聚类布局。参考更多 Fruchterman 力导向布局[样例](/examples#layout-fruchterman)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts)\n\n## 使用场景\n\n- 基础均匀分布: 适用于展示节点均匀分布，整体结构清晰的网络关系图, 比如网络拓扑、知识图谱。\n- 聚类布局: 适用于具有内部聚合特性或分组的数据可视化展示, 比如社区结构展示、关联组分析。\n\n## 配置项\n\n| 属性         | 描述                                                                                                                                           | 类型                                                                                                       | 默认值   | 必选 |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type         | 布局类型                                                                                                                                       | `'fruchterman'`                                                                                            | -        | ✓    |\n| height       | 布局的高度                                                                                                                                     | `number`                                                                                                   | 容器高度 |      |\n| width        | 布局的宽度                                                                                                                                     | `number`                                                                                                   | 容器宽度 |      |\n| maxIteration | 最大迭代次数                                                                                                                                   | `number`                                                                                                   | 500      |      |\n| minMovement  | 收敛阈值                                                                                                                                       | `number`                                                                                                   | 0.4      |      |\n| gravity      | 中心力大小，指所有节点被吸引到 [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915) 的力。数字越大，布局越紧凑 | `number`                                                                                                   | 10       |      |\n| speed        | 每次迭代节点移动的速度。速度太快可能会导致强烈震荡                                                                                             | `number`                                                                                                   | 5        |      |\n| onTick       | 每一次迭代的回调函数                                                                                                                           | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -        |      |\n\n### 聚类布局\n\n| 属性           | 描述                                                                       | 类型      | 默认值      | 必选 |\n| -------------- | -------------------------------------------------------------------------- | --------- | ----------- | ---- |\n| clustering     | 是否按照聚类布局                                                           | `boolean` | `false`     |      |\n| nodeClusterBy  | 聚类布局依据的节点数据 `data` 中的字段名，在 `clustering` 为 `true` 时生效 | `string`  | `'cluster'` |      |\n| clusterGravity | 聚类内部的重力大小，影响聚类的紧凑程度，在 `clustering` 为 `true` 时生效   | `number`  | 10          |      |\n\n## 示例代码\n\n### 基本布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### 聚类布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/GridLayout.en.md":"---\ntitle: Grid Layout\norder: 15\n---\n\n## Overview\n\nThe grid layout arranges nodes in a grid pattern, suitable for scenarios where nodes need to be arranged neatly. This layout supports automatic calculation of the number of rows and columns, or you can specify them manually. It also supports preventing node overlap.\n\n## Use Cases\n\n- Visualizing data in a matrix or table format\n\n## Online Demo\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## Options\n\n| Property              | Description                                                                                                                     | Type                                             | Default   | Required |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | -------- |\n| type                  | Layout type                                                                                                                     | `grid`                                           | -         | ✓        |\n| begin                 | Grid start position (top-left corner), default is `[0, 0]`                                                                      | [number, number]                                 | [0, 0]    |          |\n| cols                  | Number of columns. If undefined, the algorithm calculates it automatically based on node count, layout space, and rows (if set) | number                                           | undefined |          |\n| rows                  | Number of rows. If undefined, the algorithm calculates it automatically based on node count, layout space, and cols (if set)    | number                                           | 10        |          |\n| width                 | Layout area width. In G6, the container width is used as the default value                                                      | number                                           | 300       |          |\n| height                | Layout area height. In G6, the container height is used as the default value                                                    | number                                           | 300       |          |\n| condense              | If false, uses all available canvas space; if true, uses the minimum canvas space                                               | boolean                                          | false     |          |\n| nodeSize              | Node size (diameter), used for collision detection when preventing overlap                                                      | Size \\| ((nodeData: Node) => Size)               | -         |          |\n| nodeSpacing           | Node spacing, used to adjust the gap between nodes                                                                              | ((node?: Node) => number) \\| number              | -         |          |\n| position              | Specify the row and column for each node                                                                                        | (node?: Node) => { row?: number; col?: number; } | undefined |          |\n| preventOverlap        | Whether to prevent node overlap. Requires nodeSize or size property in node data                                                | boolean                                          | false     |          |\n| preventOverlapPadding | Padding when preventing overlap. Effective when preventOverlap is true                                                          | number                                           | 10        |          |\n| sortBy                | Sort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting              | string                                           | undefined |          |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\nWhether to prevent overlap\n\nMust be used with nodeSize or the size property in node data. Only when data has data.size or nodeSize is set in the layout, collision detection for node overlap can be performed.\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\nPadding when preventing overlap. Effective when preventOverlap is true.\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\nSort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting. In G6, the container width is used as the default value for grid layout width. When used alone, the default is 300.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Custom Configuration\n\nYou can customize the grid layout in various ways:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // Start layout from [50, 50]\n    cols: 4, // 4 columns\n    rows: 6, // 6 rows\n    width: 400, // Layout area width\n    height: 600, // Layout area height\n    preventOverlap: true, // Prevent node overlap\n    nodeSize: 30, // Node size\n    condense: true, // Use minimum space\n    sortBy: 'value', // Sort by value property\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // Property for sorting\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Specify Node Position\n\nYou can specify the position for specific nodes using the `position` property:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // Specify position for specific nodes\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // Top-left\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // Top-right\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // Bottom-left\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // Bottom-right\n      return undefined; // Other nodes are auto-arranged\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Real Cases\n\n- [Grid Layout](/en/examples/layout/grid/#basic)\n","packages/site/docs/manual/layout/GridLayout.zh.md":"---\ntitle: 网格布局 Grid\norder: 15\n---\n\n## 概述\n\n网格布局将节点按照网格形式排列，适用于需要整齐排列节点的场景。该布局支持自动计算行列数，也可以手动指定行列数，并支持防止节点重叠。\n\n## 使用场景\n\n- 在数据可视化中需要展示矩阵或表格形式的数据关系\n\n## 在线体验\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## 配置项\n\n| 属性                  | 描述                                                                                                                             | 类型                                             | 默认值    | 必选 |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | ---- |\n| type                  | 布局类型                                                                                                                         | `grid`                                           | -         | ✓    |\n| begin                 | 网格开始位置（左上角），默认为 `[0, 0]`                                                                                          | [number, number]                                 | [0, 0]    |      |\n| cols                  | 网格的列数，为 undefined 时算法根据节点数量、布局空间、rows（若指定）自动计算                                                    | number                                           | undefined |      |\n| rows                  | 网格的行数，为 undefined 时算法根据节点数量、布局空间、cols（若指定）自动计算                                                    | number                                           | 10        |      |\n| width                 | 布局区域宽度，在 G6 中使用当前容器的宽度作为默认值                                                                               | number                                           | 300       |      |\n| height                | 布局区域高度，在 G6 中使用当前容器的高度作为默认值                                                                               | number                                           | 300       |      |\n| condense              | 为 false 时表示利用所有可用画布空间，为 true 时表示利用最小的画布空间                                                            | boolean                                          | false     |      |\n| nodeSize              | 节点大小（直径），用于防止节点重叠时的碰撞检测                                                                                   | Size \\| ((nodeData: Node) => Size)               | -         |      |\n| nodeSpacing           | 节点间距，用于调整节点之间的间隔                                                                                                 | ((node?: Node) => number) \\| number              | -         |      |\n| position              | 指定每个节点所在的行和列                                                                                                         | (node?: Node) => { row?: number; col?: number; } | undefined |      |\n| preventOverlap        | 是否防止节点重叠，需要配合 nodeSize 或节点数据中的 size 属性使用                                                                 | boolean                                          | false     |      |\n| preventOverlapPadding | 避免重叠时节点的间距 padding，preventOverlap 为 true 时生效                                                                      | number                                           | 10        |      |\n| sortBy                | 指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心 | string                                           | undefined |      |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\n是否防止重叠\n\n必须配合下面属性 nodeSize 或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\n避免重叠时节点的间距 padding，preventOverlap 为 true 时生效\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\n指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心\n\n在 G6 中使用当前容器的宽度作为 grid 布局 width 的默认值。单独使用此布局时默认值为 300\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 自定义配置\n\n可以通过多种方式自定义网格布局：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // 从坐标 [50, 50] 开始布局\n    cols: 4, // 指定 4 列\n    rows: 6, // 指定 6 行\n    width: 400, // 布局区域宽度\n    height: 600, // 布局区域高度\n    preventOverlap: true, // 防止节点重叠\n    nodeSize: 30, // 节点大小\n    condense: true, // 使用最小空间\n    sortBy: 'value', // 按 value 属性排序\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // 用于排序的属性\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 指定节点位置\n\n可以通过 `position` 属性为特定节点指定位置：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // 为特定节点指定位置\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // 左上角\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // 右上角\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // 左下角\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // 右下角\n      return undefined; // 其他节点自动布局\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [Grid布局](/examples/layout/grid/#basic)\n","packages/site/docs/manual/layout/IndentedLayout.en.md":"---\ntitle: Indented Tree\norder: 16\n---\n\n# Indented Tree Layout\n\n## Overview\n\nIndented tree layout represents the hierarchy of tree nodes through indentation in the horizontal direction. Each element occupies a row or column, commonly used in file directory structures, organizational charts, and other scenarios. This layout provides a clear structure for displaying hierarchical relationships.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented Tree Layout'/>\n\n## Use Cases\n\n- File directory structure visualization\n- Organizational charts\n- Classification system display\n- Tree-like data where hierarchical relationships need to be emphasized\n\n## Configuration Items\n\n> IndentedLayout supports common layout configuration items and specific configuration items, as shown below.\n\n| Property               | Description                                                         | Type                            | Default    | Required |\n| ---------------------- | ------------------------------------------------------------------- | ------------------------------- | ---------- | -------- |\n| type                   | Layout type, must be 'indented'                                     | 'indented'                      | -          | ✓        |\n| direction              | Layout direction, see details below                                 | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |          |\n| indent                 | Column spacing, fixed value or function                             | number \\| (d?: Node) => number  | 20         |          |\n| getWidth               | Get each node's width, effective when direction='H'                 | (d?: Node) => number            | -          |          |\n| getHeight              | Get each node's height                                              | (d?: Node) => number            | -          |          |\n| getSide                | Node placement on left/right side of root, overrides direction='H'  | (d?: Node) => 'left' \\| 'right' | -          |          |\n| dropCap                | Whether the first child of each node starts on the next line        | boolean                         | true       |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (when preLayout=true) | boolean                         | false      |          |\n| nodeFilter             | Nodes participating in this layout                                  | (node: NodeData) => boolean     | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements       | boolean                         | false      |          |\n| enableWorker           | Whether to run layout in WebWorker                                  | boolean                         | -          |          |\n| iterations             | Number of iterations for iterative layout                           | number                          | -          |          |\n\n### Complex Type Explanations\n\n- **direction**\n\n  - `'LR'`: Root node on the left, layout to the right\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`: Root node on the right, layout to the left\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`: Root node in the middle, horizontal symmetric layout\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - Fixed value: Consistent indentation for all levels\n  - Function: (d?: Node) => number, customize indentation based on node\n  - Example:\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - Used to customize each node's width/height, often for content adaptation\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - Specifies which side of the root node a node should be placed, only effective when direction='H'\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## Example Code\n\n> For more examples, see [Online Demo](https://g6.antv.antgroup.com/en/examples/layout/indented)\n\n### Automatic Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### Right Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'LR'\n```\n\n### Left Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'RL'\n```\n\n### Custom Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### No Line Break for First Child Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","packages/site/docs/manual/layout/IndentedLayout.zh.md":"---\ntitle: 缩进树 Indented\norder: 16\n---\n\n## 概述\n\nIndented（缩进树）布局是一种通过水平方向的缩进量来表示树节点层级的布局方式。每个元素占据一行或一列，常用于文件目录结构、组织架构等场景。该布局结构清晰，便于展示层级关系。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented 缩进树布局示意图'/>\n\n## 使用场景\n\n- 文件目录结构可视化\n- 组织架构树\n- 分类体系展示\n- 需要突出层级关系的树状数据\n\n## 配置项\n\n> IndentedLayout 支持通用布局配置项和专有配置项，详见下表。\n\n| 属性                   | 描述                                                 | 类型                            | 默认值     | 必选 |\n| ---------------------- | ---------------------------------------------------- | ------------------------------- | ---------- | ---- |\n| type                   | 布局类型，需为 'indented'                            | 'indented'                      | -          | ✓    |\n| direction              | 布局方向，根节点在左/右/中间，详见下方说明           | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |      |\n| indent                 | 列间间距，支持固定值或函数                           | number \\| (d?: Node) => number  | 20         |      |\n| getWidth               | 获取每个节点宽度，仅 direction='H' 时生效            | (d?: Node) => number            | -          |      |\n| getHeight              | 获取每个节点高度                                     | (d?: Node) => number            | -          |      |\n| getSide                | 节点排布在根节点的左/右侧，设置后 direction='H' 失效 | (d?: Node) => 'left' \\| 'right' | -          |      |\n| dropCap                | 每个节点的第一个子节点是否换行                       | boolean                         | true       |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（preLayout=true 时生效）      | boolean                         | false      |      |\n| nodeFilter             | 参与该布局的节点                                     | (node: NodeData) => boolean     | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                   | boolean                         | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                          | boolean                         | -          |      |\n| iterations             | 迭代布局的迭代次数                                   | number                          | -          |      |\n\n### 复杂类型说明\n\n- **direction**\n\n  - `'LR'`：根节点在左，向右布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`：根节点在右，向左布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`：根节点在中间，水平对称布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - 固定数值：所有层级缩进一致\n  - 函数：(d?: Node) => number，可根据节点自定义缩进\n  - 示例：\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - 用于自定义每个节点的宽度/高度，常用于自适应内容\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - 指定节点在根节点的哪一侧，仅 direction='H' 时生效\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## 示例代码\n\n> 更多示例可参考 [在线 Demo](https://g6.antv.antgroup.com/examples/layout/indented)\n\n### 子节点自动分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### 子节点右侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'LR'\n```\n\n### 子节点左侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'RL'\n```\n\n### 自定义子节点分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### 首子节点不换行\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","packages/site/docs/manual/layout/MdsLayout.en.md":"---\ntitle: MDS High-dimensional Data Dimensionality Reduction Layout\norder: 17\n---\n\n# MDS High-dimensional Data Dimensionality Reduction Layout\n\n## Overview\n\nMDS (Multidimensional Scaling) is a classic dimensionality reduction algorithm. In G6, the MDS layout constructs a distance matrix between nodes and restores their relative distances in high-dimensional space as much as possible in 2D space. It is suitable for graph visualization scenarios that show similarity, distance, or structural relationships between nodes.\n\n## Use Cases\n\n- Data dimensionality reduction visualization\n- Displaying distance relationships between nodes\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## Options\n\n| Option           | Description                           | Type              | Default       | Required |\n| :--------------- | :------------------------------------ | :---------------- | :------------ | :------- |\n| **type**         | Layout type                           | `mds`             | -             | Yes      |\n| **center**       | Center position of the layout         | `[number,number]` | canvas center | No       |\n| **linkDistance** | Ideal length of edges (spring length) | `number`          | 200           | No       |\n\n**center**\n\nThe center coordinates of the layout. All nodes will be symmetrically distributed around this point.\n\n**linkDistance**\n\n> number Default: 50\n\nThe ideal distance between nodes. The larger the value, the more dispersed the nodes.\n\n## Code Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/MdsLayout.zh.md":"---\ntitle: 高维数据降维布局 MDS\norder: 17\n---\n\n## 概述\n\nMDS（多维尺度分析，Multidimensional Scaling）是一种经典的降维算法。在 G6 中，MDS 布局通过构造节点间的距离矩阵，在二维空间中尽可能还原它们在高维空间中的相对距离。适用于展示节点之间相似度、距离或结构关系的图可视化场景。\n\n## 使用场景\n\n- 数据降维可视化\n- 展示节点之间的距离关系\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## 配置项\n\n| 配置项           | 描述                               | 类型              | 默认值   | 必选 |\n| :--------------- | :--------------------------------- | :---------------- | :------- | :--- |\n| **type**         | 布局类型                           | `mds`             | -        | 是   |\n| **center**       | 布局的中心位置                     | `[number,number]` | 画布中心 | 否   |\n| **linkDistance** | 边的理想长度（弹簧未受力时的长度） | `number`          | 200      | 否   |\n\n**center**\n\n布局的中心点坐标，所有节点会围绕该点对称分布。\n\n**linkDistance**\n\n> number Default: 50\n\n节点之间的理想距离，越大则节点间距离越分散。\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/MindmapLayout.en.md":"---\ntitle: Mindmap Tree\norder: 18\n---\n\n## Overview\n\nThe mindmap tree layout is suitable for hierarchical layouts of tree structures, supporting expansion on both left and right sides. Nodes at the same depth will be placed on the same layer. Note: the layout **does** take node size into account. See more mindmap layout [examples](/en/examples#layout-mindmap) or [source code](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"Mindmap tree options diagram\" />\n\n| Property  | Description                                                                                             | Type                                | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------- | -------- |\n| type      | Layout type                                                                                             | `mindmap`                           | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                 | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`    |          |\n| getHeight | Function to calculate the height of each node                                                           | (d?: Node) => number                |         | ✓        |\n| getWidth  | Function to calculate the width of each node                                                            | (d?: Node) => number                |         | ✓        |\n| getVGap   | Vertical gap for each node. Note: the actual vertical gap between two nodes is twice the vgap           | (d?: Node) => number                |         |          |\n| getHGap   | Horizontal gap for each node. Note: the actual horizontal gap between two nodes is twice the hgap       | (d?: Node) => number                |         |          |\n| getSide   | Set whether the node is placed on the left or right of the root. Only effective when `direction` is `H` | (d?: Node) => string                |         |          |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\nTree layout direction\n\n- `'H'`: horizontal — The children of the root node are divided into two parts and placed on the left and right sides of the root node. You can pass the `getSide` method to specify the left/right distribution logic for each node. If not provided, the first half will be placed on the right, and the second half on the left by default.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='Horizontal layout'/>\n\n- `'LR' | 'TB'`: Children are placed on the right side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `'RL'`: Children are placed on the left side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `BT`: Children are placed on the right side of the root node, then the entire graph is rotated 180° along the X axis.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='Vertical layout'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\nWidth of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\nHeight of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\nHorizontal gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\nVertical gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\nSet whether the node is placed on the left or right of the root. Note: only effective when `direction` is `H`. If not set, the first half of the children will be placed on the right, and the second half on the left by default. See [getSide auto calculation logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### Suitable Scenarios\n\n- Data lineage graph: `direction='H'` is suitable for rendering upstream and downstream lineage of a specified node, with upstream on the left and downstream on the right of the central node.\n- Mind map: Build custom mind map components.\n","packages/site/docs/manual/layout/MindmapLayout.zh.md":"---\ntitle: 脑图树 Mindmap\norder: 18\n---\n\n## 概述\n\n脑图树布局适用于树状结构的层次化布局，支持左右两侧展开，深度相同的节点将会被放置在同一层。需要注意：布局**会**考虑节点的大小。参考更多脑图布局[样例](/examples#layout-mindmap)或[源码](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"脑图树配置项图解\" />\n\n| 属性      | 描述                                                                                                  | 类型                                | 默认值 | 必选 |\n| --------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                              | `mindmap`                           | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                        | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`   |      |\n| getHeight | 计算每个节点的高度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getWidth  | 计算每个节点的宽度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getVGap   | 每个节点的垂直间隙，注意实际两个节点间的垂直间隙是2倍的vgap                                           | (d?: Node) => number                |        |      |\n| getHGap   | 每个节点的水平间隙，注意实际两个节点间的水平间隙是2倍的hgap                                           | (d?: Node) => number                |        |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在`H`布局方向上生效 | (d?: Node) => string                |        |      |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\n树布局的方向\n\n- `'H'`：horizontal（水平）—— 根节点的子节点分成两部分横向放置在根节点左右两侧。可传入`getSide`方法指定每个节点的左右分布逻辑，不传则默认将前半部分放置在右侧，后半部分放置在左侧。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='水平布局'/>\n\n- `'LR' | 'TB'`：将子节点排布在根节点的右侧；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='竖直布局'/>\n\n- `'RL'`：将子节点排布在根节点的左侧；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='竖直布局'/>\n\n- `BT`：将子节点排布在根节点右侧，然后将整个图沿X轴旋转180°；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='竖直布局'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在`direction`为`H`时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考[getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### 布局适用场景\n\n- 数据血缘图：`direction='H'`很适合渲染血缘图中查看指定节点的上下游血缘的场景，上游分布在中心节点的左侧，下游分布在右侧；\n- 思维导图：构建自定义的思维导图组件。\n","packages/site/docs/manual/layout/RadialLayout.en.md":"---\ntitle: Radial Layout\norder: 19\n---\n\n## Overview\n\nRadial layout is a graph layout algorithm that arranges nodes in concentric circles by layers. It is commonly used to display hierarchical relationships, community structures, and more. This layout supports advanced features such as node overlap prevention and group sorting, making it suitable for visualizing various network structures.\n\n## Use Cases\n\n- Displaying hierarchical structures (e.g., organizational charts, family trees)\n- Community structure analysis\n- Scenarios that need to highlight the central node and its radiating relationships\n- Complex networks requiring node grouping and sorting\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // other configurations...\n});\n```\n\n## Options\n\n| Property                   | Description                                                     | Type                                             | Default  | Required |\n| -------------------------- | --------------------------------------------------------------- | ------------------------------------------------ | -------- | -------- |\n| type                       | Layout type                                                     | string                                           | `radial` | ✓        |\n| center                     | Center coordinates                                              | [number, number]                                 | -        |          |\n| focusNode                  | Radiating center node                                           | string \\| Node \\| null                           | null     |          |\n| height                     | Canvas height                                                   | number                                           | -        |          |\n| width                      | Canvas width                                                    | number                                           | -        |          |\n| nodeSize                   | Node size (diameter)                                            | number \\| number[] \\| ((nodeData: Node) => Size) | -        |          |\n| nodeSpacing                | Minimum node spacing (effective when preventing overlap)        | number \\| (nodeData: Node) => number             | 10       |          |\n| linkDistance               | Edge length                                                     | number                                           | 50       |          |\n| unitRadius                 | Radius per circle; when null, automatically computed from space | number \\| null                                   | 100      |          |\n| maxIteration               | Maximum number of iterations                                    | number                                           | 1000     |          |\n| maxPreventOverlapIteration | Max iterations for overlap prevention                           | number                                           | 200      |          |\n| preventOverlap             | Whether to prevent node overlap                                 | boolean                                          | false    |          |\n| sortBy                     | Field or sorting function for nodes in the same layer           | string \\| ((nodeData: Node) => number \\| string) | -        |          |\n| sortStrength               | Sorting strength for nodes in the same layer                    | number                                           | 10       |          |\n| strictRadial               | Strictly place nodes in the same layer on the same ring         | boolean                                          | true     |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\nResult:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"Basic Radial Layout\" style=\"max-width: 600px;\" />\n\n## Real Cases\n\n- [Basic Radial Layout](/en/examples/layout/radial/#basic)\n- [Strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#strict-prevent-overlap)\n- [Non-strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#non-strict-prevent-overlap)\n- [Cluster Sorting](/en/examples/layout/radial/#cluster-sort)\n","packages/site/docs/manual/layout/RadialLayout.zh.md":"---\ntitle: 径向布局 Radial\norder: 19\n---\n\n## 概述\n\n径向（Radial）布局是一种将节点以同心圆方式分层排列的图布局算法，常用于展示层级关系、社群结构等。该布局支持节点防重叠、分组排序等高级特性，适用于多种网络结构的可视化。\n\n## 使用场景\n\n- 展示层级结构（如组织架构、家谱等）\n- 社群结构分析\n- 需要突出中心节点及其辐射关系的场景\n- 需要节点分组、排序的复杂网络\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // 其他配置...\n});\n```\n\n## 配置项\n\n| 属性                       | 描述                                         | 类型                                             | 默认值   | 必选 |\n| -------------------------- | -------------------------------------------- | ------------------------------------------------ | -------- | ---- |\n| type                       | 布局类型                                     | string                                           | `radial` | ✓    |\n| center                     | 圆心坐标                                     | [number, number]                                 | -        |      |\n| focusNode                  | 辐射中心节点                                 | string \\| Node \\| null                           | null     |      |\n| height                     | 画布高度                                     | number                                           | -        |      |\n| width                      | 画布宽度                                     | number                                           | -        |      |\n| nodeSize                   | 节点大小（直径）                             | number \\| number[] \\| ((nodeData: Node) => Size) | -        |      |\n| nodeSpacing                | 节点最小间距（防重叠时生效）                 | number \\| (nodeData: Node) => number             | 10       |      |\n| linkDistance               | 边长度                                       | number                                           | 50       |      |\n| unitRadius                 | 每圈半径；为 null 时按布局空间自动计算       | number \\| null                                   | 100      |      |\n| maxIteration               | 最大迭代次数                                 | number                                           | 1000     |      |\n| maxPreventOverlapIteration | 防重叠最大迭代次数                           | number                                           | 200      |      |\n| preventOverlap             | 是否防止节点重叠                             | boolean                                          | false    |      |\n| sortBy                     | 同层节点排序字段或排序函数                   | string \\| ((nodeData: Node) => number \\| string) | -        |      |\n| sortStrength               | 同层节点排序强度                             | number                                           | 10       |      |\n| strictRadial               | 是否严格每层节点在同一圆环上（防重叠时生效） | boolean                                          | true     |      |\n\n## 代码示例\n\n### 基本用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\n效果如下：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"基本 Radial 辐射布局\" style=\"max-width: 600px;\" />\n\n## 实际案例\n\n- [基本 Radial 辐射布局](/examples/layout/radial/#basic)\n- [防止节点重叠的严格辐射布局](/examples/layout/radial/#strict-prevent-overlap)\n- [防止节点重叠的非严格辐射布局](/examples/layout/radial/#non-strict-prevent-overlap)\n- [排序聚类](/examples/layout/radial/#cluster-sort)\n","packages/site/docs/manual/layout/RandomLayout.en.md":"---\ntitle: Random Layout\norder: 20\n---\n\n## Overview\n\n**Random Layout** is a layout method based on simple rules. Its core logic is to generate random coordinates for each node within a specified layout area (defined by the layout center, width, and height). The coordinates are completely random, and there is no node collision prevention.\n\n## Use Cases\n\nThe use cases for random layout are very limited. It is only recommended for the following scenarios:\n\n- **Initial Data Display**:\n\n  During early development, when debugging data loading logic or quickly verifying data structure, random layout can be used for preliminary validation.\n\nFor final business delivery, it is recommended to use layouts that better reflect business value, such as [AntVDagreLayout](/en/manual/layout/antv-dagre-layout), [ForceLayout](/en/manual/layout/force-layout), or [custom layouts](/en/manual/layout/custom-layout).\n\n## Basic Usage\n\nAll other configurations use defaults (the layout width and height default to the entire canvas container).\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## Options\n\n| Property | Description   | Type                                         | Default                                   | Required |\n| -------- | ------------- | -------------------------------------------- | ----------------------------------------- | -------- |\n| type     | Layout type   | random                                       | -                                         | ✓        |\n| center   | Layout center | [number, number] \\| [number, number, number] | [`layout width` / 2, `layout height` / 2] |          |\n| height   | Layout height | number                                       | canvas height                             |          |\n| width    | Layout width  | number                                       | canvas width                              |          |\n\n## Example\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/RandomLayout.zh.md":"---\ntitle: 随机布局 Random\norder: 20\n---\n\n## 概述\n\n**随机布局（Random Layout）** 是一种基于简单规则的布局方式，其核心逻辑是为每个节点在指定布局区域（由布局中心点、宽度和高度定义）内生成随机坐标（完全随机，无节点防碰撞）。\n\n## 使用场景\n\n随机布局的使用场景非常局限，只推荐以下场景使用：\n\n- **数据初步展示**:\n\n  在开发初期调试数据加载逻辑或需要快速验证数据结构的情况下，可使用随机布局先行验证\n\n业务最终交付推荐使用更能体现业务价值的布局方式，比如 [AntVDagreLayout](/manual/layout/antv-dagre-layout) 、[ForceLayout](/manual/layout/force-layout) 或者[自定义布局](/manual/layout/custom-layout)等。\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## 配置项\n\n| 属性   | 描述       | 类型                                         | 默认值                           | 必选 |\n| ------ | ---------- | -------------------------------------------- | -------------------------------- | ---- |\n| type   | 布局类型   | random                                       | -                                | ✓    |\n| center | 布局的中心 | [number, number] \\| [number, number, number] | [`布局宽度` / 2, `布局高度` / 2] |      |\n| height | 布局的高度 | number                                       | 画布高度                         |      |\n| width  | 布局的宽度 | number                                       | 画布宽度                         |      |\n\n## 示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/Snake.en.md":"---\ntitle: Snake Layout\norder: 21\n---\n\n## Overview\n\nSnake Layout is a special type of graph layout that can more efficiently display long chain structures in a limited space. Note that the graph data must ensure that nodes are linearly arranged from the source node to the sink node, forming a clear path.\n\nNodes are arranged in an S-shape: the first node is at the start of the first row, subsequent nodes are arranged to the right in the first row until the end. At the end of the row, the next row's nodes are arranged from right to left. This process repeats until all nodes are placed.\n\n## Use Cases\n\nSuitable for scenarios that require compact presentation of linear relationships:\n\n- **Long process visualization**\n\n  Perfect for scenarios with many process steps, such as approval flows, production line procedures, logistics routes, etc.\n\n- **Hierarchical structures in limited space**\n\n  When the hierarchy is too long but the canvas is limited, rows can be folded to save space. For example, API call dependencies (client → gateway → serviceA → serviceB → database, snake layout compresses 5 layers into 2 rows), or file directory trees (deeply nested folder structures, e.g., src/components/utils/helpers/..., using snake layout to fold subdirectories horizontally).\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## Options\n\n> If the layout has specific properties, they are listed below. For common layout options, see [Base Layout Options](/en/manual/layout/base-layout)\n\n| Property                | Description                                                 | Type                                               | Default                                                    | Required |\n| ----------------------- | ----------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- | -------- |\n| type                    | Layout type                                                 | snake                                              | -                                                          | ✓        |\n| [clockwise](#clockwise) | Whether nodes are arranged clockwise                        | boolean                                            | true                                                       |          |\n| colGap                  | Gap size between columns                                    | number                                             | Automatically calculated by canvas width and total columns |          |\n| cols                    | Number of columns                                           | number                                             | 5                                                          |          |\n| nodeSize                | Node size                                                   | Size \\| ((node: NodeData) => Size)                 | -                                                          |          |\n| padding                 | Padding, i.e., distance from layout area to canvas boundary | number \\| number[]                                 | 0                                                          |          |\n| rowGap                  | Gap size between rows                                       | number                                             | Automatically calculated by canvas height and total rows   |          |\n| sortBy                  | Node sorting method                                         | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | Default is the path order in the graph                     |          |\n\n### clockwise\n\n- When arranged clockwise, nodes start from the top left, the first row is arranged left to right, the second row right to left, and so on, forming an S-shaped path.\n- When arranged counterclockwise, nodes start from the top right, the first row is arranged right to left, the second row left to right, and so on, forming a reversed S-shaped path.\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/Snake.zh.md":"---\ntitle: 蛇形布局 Snake\norder: 21\n---\n\n## 概览\n\n蛇形布局（Snake Layout）是一种特殊的图形布局方式，能够在较小的空间内更有效地展示长链结构。需要注意的是，其图数据需要确保节点按照从源节点到汇节点的顺序进行线性排列，形成一条明确的路径。\n\n节点按 S 字型排列，第一个节点位于第一行的起始位置，接下来的节点在第一行向右排列，直到行末尾。到达行末尾后，下一行的节点从右向左反向排列。这个过程重复进行，直到所有节点排列完毕。\n\n## 使用场景\n\n适合需要紧凑呈现线性关系的场景：\n\n- **长流程可视化**\n\n  完美适配流程步骤过多的场景，如审批流程、生产线工序、物流运输路径等。\n\n- **有限空间内的层级结构**\n\n  层级结构过长但画布受限，需通过折叠行节省空间，比如 API 调用依赖（客户端 → 网关 → 服务A → 服务B → 数据库，蛇形布局将 5 层压缩为 2 行）、文件目录树（深度嵌套的文件夹结构，如 src/components/utils/helpers/... ，用蛇形布局横向折叠子目录）。\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## 配置项\n\n> 如果布局有其特定的属性，我们将在下面列出。对于所有布局的通用属性，见[布局通用配置项](/manual/layout/base-layout)\n\n| 属性                    | 描述                               | 类型                                               | 默认值                                 | 必选 |\n| ----------------------- | ---------------------------------- | -------------------------------------------------- | -------------------------------------- | ---- |\n| type                    | 布局类型                           | snake                                              | -                                      | ✓    |\n| [clockwise](#clockwise) | 节点排布方向是否顺时针             | boolean                                            | true                                   |      |\n| colGap                  | 节点列之间的间隙大小               | number                                             | 默认将根据画布宽度和节点总列数自动计算 |      |\n| cols                    | 节点列数                           | number                                             | 5                                      |      |\n| nodeSize                | 节点尺寸                           | Size \\| ((node: NodeData) => Size)                 | -                                      |      |\n| padding                 | 内边距，即布局区域与画布边界的距离 | number \\| number[]                                 | 0                                      |      |\n| rowGap                  | 节点行之间的间隙大小               | number                                             | 默认将根据画布高度和节点总行数自动计算 |      |\n| sortBy                  | 节点排序方法                       | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | 默认按照在图中的路径顺序进行展示       |      |\n\n### clockwise\n\n- 在顺时针排布时，节点从左上角开始，第一行从左到右排列，第二行从右到左排列，依次类推，形成 S 型路径。\n\n- 在逆时针排布时，节点从右上角开始，第一行从右到左排列，第二行从左到右排列，依次类推，形成反向 S 型路径。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/custom-layout.en.md":"---\ntitle: Custom Layout\norder: 22\n---\n\n## Overview\n\nIn G6, layouts are divided into two types: 'iterative layout' and 'non-iterative layout'. An iterative layout refers to a layout algorithm that iterates multiple times until convergence, while a non-iterative layout refers to a layout algorithm that executes only once.\n\n## Implement Layout\n\n### Non-Iterative Layout\n\nImplementing a non-iterative layout is relatively straightforward; you only need to implement the `execute` method in `BaseLayout`. Below is a simple implementation of a custom layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\nIn the code above, we implemented a simple layout algorithm that arranges nodes along a diagonal line starting from the top-left corner.\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=info}\n\nThe `execute` method returns a GraphData object, which only needs to contain the basic information of the elements (such as id, source, target) and the properties added by the layout (such as x, y, control points of edges, etc.), and does not need to contain other unnecessary information.\nIf you only need to layout the nodes, you can return only the node information and do not need to return the edge information.\n:::\n\n### Iterative Layout\n\nThe implementation of an iterative layout also requires inheriting from `BaseLayout`, but in addition to `execute`, you also need to implement the `tick` and `stop` methods. The `tick` method is used to iterate the layout to a specified number of rounds, and the `stop` method is used to stop the layout iteration.\n\nIn addition, in iterative layouts, you need to call `options.onTick` each time the layout iterates to trigger the graph update.\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\nBelow is a simple implementation of an iterative layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\nIn this example, we have implemented a simple iterative layout algorithm that toggles the x-coordinate of the nodes between 50 and 150 every 200 milliseconds and arranges them in order along the y-axis according to the sequence of the nodes.\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## Register Layout\n\nYou can register through the `register` method provided by G6. For more details, please refer to [Register Layout](/en/manual/core-concept/layout#register-layout)\n\n## Configure Layout\n\nThe type and parameters of the layout can be configured in `options.layout`. For more details, please refer to [Configure Layout](/en/manual/core-concept/layout#configure-layout)\n","packages/site/docs/manual/layout/custom-layout.zh.md":"---\ntitle: 自定义布局\norder: 22\n---\n\n## 概述\n\nG6 中布局分为`迭代布局`和`非迭代布局`两种，迭代布局是指布局算法会迭代多次直到收敛，非迭代布局是指布局算法只执行一次。\n\n## 实现布局\n\n### 非迭代布局\n\n实现一个非迭代布局相对简单，只需要实现 `BaseLayout` 中的 `execute` 方法即可，下面是一个简单的自定义布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\n在上面的代码中，我们实现了一个简单的布局算法，将节点从左上角沿对角线排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=提示}\n`execute` 方法返回的是一个 GraphData 对象，里面仅需要包含元素的基本信息（如 id、source、target）以及布局新增的属性（如 x、y、边的控制点等），不需要包含其他无用的信息。\n如果仅需要对节点进行布局，可以只返回节点信息，不需要返回边的信息。\n:::\n\n### 迭代布局\n\n迭代布局的实现同样需要继承 `BaseLayout`，但是除 `execute` 外还需要实现 `tick` 和 `stop` 方法，`tick` 方法用于将布局迭代到指定轮次，`stop` 方法用于停止布局迭代。\n\n此外，迭代布局中需要在每次迭代调用 `options.onTick` 以触发图的更新。\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\n下面是一个简单的迭代布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\n在这个例子中，我们实现了一个简单的迭代布局算法，每 200ms 将节点的 x 坐标在 50 和 150 之间切换，并按照节点顺序在 y 方向上排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## 注册布局\n\n通过 G6 提供的 register 方法注册即可，详见[注册布局](/manual/layout/overview#注册布局)\n\n## 配置布局\n\n可在 `options.layout` 中配置布局的类型和参数，详见[配置布局](/manual/layout/overview#配置布局)\n","packages/site/docs/manual/layout/overview.en.md":"---\ntitle: Layout Overview\norder: 0\n---\n\n## Overview\n\nGraph layout refers to the process of arranging elements in a graph according to certain rules, such as force-directed layout based on charge elasticity models, grid layout with sequential arrangement, and tree layout based on hierarchical structures.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Layout Types\n\nG6 provides a variety of layout algorithms, allowing users to choose the appropriate one based on their needs:\n\n- [AntVDagreLayout](/en/manual/layout/antv-dagre-layout): Custom layout based on dagre\n- [CircularLayout](/en/manual/layout/circular-layout): Circular layout\n- [ComboCombinedLayout](/en/manual/layout/combo-combined-layout): Layout suitable for combinations\n- [ConcentricLayout](/en/manual/layout/concentric-layout): Concentric layout\n- [D3Force3DLayout](/en/manual/layout/d3-force3-d-layout): [3D Force-directed](https://github.com/vasturiano/d3-force-3d) layout\n- [D3ForceLayout](/en/manual/layout/d3-force-layout): Force-directed layout based on [D3](https://d3js.org/d3-force)\n- [DagreLayout](/en/manual/layout/dagre-layout): [dagre](https://github.com/dagrejs/dagre) layout\n- [FishboneLayout](/en/manual/layout/fishbone): Fishbone layout\n- [ForceAtlas2Layout](/en/manual/layout/force-atlas2-layout): [ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) layout\n- [ForceLayout](/en/manual/layout/force-layout): Force-directed layout\n- [FruchtermanLayout](/en/manual/layout/fruchterman-layout): [Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) layout\n- [GridLayout](/en/manual/layout/grid-layout): Grid layout\n- [MDSLayout](/en/manual/layout/mds-layout): High-dimensional data dimensionality reduction layout\n- [RadialLayout](/en/manual/layout/radial-layout): Radial layout\n- [RandomLayout](/en/manual/layout/random-layout): Random layout\n- [SnakeLayout](/en/manual/layout/snake): Snake layout\n- [CompactBoxLayout](/en/manual/layout/compact-box-layout): Compact tree layout\n- [DendrogramLayout](/en/manual/layout/dendrogram-layout): Dendrogram layout\n- [MindmapLayout](/en/manual/layout/mindmap-layout): Mindmap layout\n- [IndentedLayout](/en/manual/layout/indented-layout): Indented tree layout\n\nAmong them, `CompactBox Layout`, `Dendrogram Layout`, `Mindmap Layout`, and `Indented Layout` are types of tree layouts suitable for tree-structured graphs.\n\n## Register Layout\n\nYou can directly use built-in layouts, but if you want to use other layouts, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## Configure Layout\n\nThe `layout` configuration item can specify the graph's layout algorithm, for example:\n\n```typescript\n{\n  layout: {\n    // Specify the layout algorithm to use\n    type: 'force',\n    // Configuration items for the layout algorithm\n    gravity: 10\n    // ...\n  }\n}\n```\n\nYou can also use `graph.setLayout` to update the layout configuration after the graph is instantiated.\n\nStarting from `5.1`, layout docs align their shared fields with `@antv/layout`. Besides each layout's own algorithm parameters, you should also pay attention to common options such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`.\n\n## Layout Acceleration\n\nG6 provides accelerated versions for some layout algorithms, including executing layout algorithms in Web Workers, providing [WASM](https://webassembly.org/) versions of layout algorithms, and GPU-accelerated layout algorithms. They can be used as follows:\n\n### Execute Layout Algorithms in Web Workers\n\nExcept for tree layouts, all built-in layout algorithms in G6 support execution in Web Workers. Simply set `enableWorker` to `true`:\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### Use WASM Version Layout Algorithms\n\nCurrently supported WASM version layout algorithms include: `Fruchterman Layout`, `ForceAtlas Layout`, `Force Layout`, `Dagre Layout`.\n\nFirst, install `@antv/layout-wasm`:\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\nInitialize threads:\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... other configurations\n  },\n});\n```\n\n### Use GPU-Accelerated Layout\n\nCurrently supported GPU-accelerated layout algorithms include: `Fruchterman Layout`, `GForce Layout`.\n\nFirst, install `@antv/layout-gpu`:\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... other configurations\n  },\n});\n```\n\n## Execute Layout\n\nUsually, after calling `graph.render()`, G6 will automatically execute the layout algorithm.\n\nIf you need to manually execute the layout algorithm, G6 provides the following APIs:\n\n- [layout](/api/layout#graphlayoutlayoutoptions): Execute layout algorithm\n- [setLayout](/api/layout#graphsetlayoutlayout): Set layout algorithm\n- [stopLayout](/api/layout#graphstoplayout): Stop layout algorithm\n\n## Custom Layout\n\nIf the built-in layout algorithms cannot meet your needs, you can customize layout algorithms. For details, please refer to [Custom Layout](/manual/layout/custom-layout).\n\nIf you are migrating layout configuration from G6 `5.0` to `5.1`, see [Upgrade from 5.0 to 5.1 (Layout)](/en/manual/whats-new/upgrade-to-5-1).\n","packages/site/docs/manual/layout/overview.zh.md":"---\ntitle: 布局总览\norder: 0\n---\n\n## 概述\n\n图布局是指将图中的元素按照一定的规则进行排列的过程，例如基于电荷弹性模型的力导向布局、逐次排布的网格布局、基于层次结构的树布局等。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 布局类型\n\nG6 提供了多种布局算法，用户可以根据自己的需求选择合适的布局算法：\n\n- [AntVDagreLayout](/manual/layout/antv-dagre-layout)：基于 dagre 定制的布局\n- [CircularLayout](/manual/layout/circular-layout)：环形布局\n- [ComboCombinedLayout](/manual/layout/combo-combined-layout)：适用于存在组合的布局\n- [ConcentricLayout](/manual/layout/concentric-layout)：同心圆布局\n- [D3Force3DLayout](/manual/layout/d3-force3-d-layout)：[3D 力导向](https://github.com/vasturiano/d3-force-3d)布局\n- [D3ForceLayout](/manual/layout/d3-force-layout)：基于 [D3](https://d3js.org/d3-force) 的力导向布局\n- [DagreLayout](/manual/layout/dagre-layout)：[dagre](https://github.com/dagrejs/dagre) 布局\n- [FishboneLayout](/manual/layout/fishbone)：鱼骨布局\n- [ForceAtlas2Layout](/manual/layout/force-atlas2-layout)：[ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) 布局\n- [ForceLayout](/manual/layout/force-layout)：力导向布局\n- [FruchtermanLayout](/manual/layout/fruchterman-layout)：[Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) 布局\n- [GridLayout](/manual/layout/grid-layout)：网格布局\n- [MDSLayout](/manual/layout/mds-layout)：高维数据降维算法布局\n- [RadialLayout](/manual/layout/radial-layout)：径向布局\n- [RandomLayout](/manual/layout/random-layout)：随机布局\n- [SnakeLayout](/manual/layout/snake)：蛇形布局\n- [CompactBoxLayout](/manual/layout/compact-box-layout): 紧凑树布局\n- [DendrogramLayout](/manual/layout/dendrogram-layout): 树状布局\n- [MindmapLayout](/manual/layout/mindmap-layout): 思维导图布局\n- [IndentedLayout](/manual/layout/indented-layout): 缩进树布局\n\n其中 `CompactBox Layout`、`Dendrogram Layout`、`Mindmap Layout`、`Indented Layout` 是树布局的一种，适用于树状结构的图。\n\n## 注册布局\n\n你可以直接使用内置布局，如果想要使用其他布局，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## 配置布局\n\n通过 `layout` 配置项可以指定图的布局算法，例如：\n\n```typescript\n{\n  layout: {\n    // 指定要使用的布局算法\n    type: 'force',\n    // 布局算法的配置项\n    gravity: 10\n    // ...\n  }\n}\n```\n\n也可在图实例化之后使用 `graph.setLayout` 来更新布局配置。\n\n5.1 开始，布局文档中的通用字段已与 `@antvis/layout` 对齐。除了各布局自己的算法参数外，也建议同时关注 `width`、`height`、`center`、`enableWorker`、`node`、`edge` 等公共配置。\n\n## 布局加速\n\nG6 对一些布局算法提供了加速版本，包括：在 Web Worker 中执行布局算法、提供 [WASM](https://webassembly.org/) 版本的布局算法、GPU 加速的布局算法等。可按照下列方式使用：\n\n### 在 Web Worker 中执行布局算法\n\n除树布局外，G6 的所有内置布局算法都支持在 Web Worker 中执行。只需将 `enableWorker` 设置为 `true` 即可：\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### 使用 WASM 版本布局算法\n\n目前支持 WASM 版本的布局算法有：`Fruchterman Layout` `ForceAtlas Layout` `Force Layout` `Dagre Layout`。\n\n首先安装 `@antv/layout-wasm`：\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\n初始化线程：\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... 其他配置\n  },\n});\n```\n\n### 使用 GPU 加速布局\n\n目前支持 GPU 加速的布局算法有：`Fruchterman Layout` `GForce Layout`。\n\n首先安装 `@antv/layout-gpu`：\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他配置\n  },\n});\n```\n\n## 执行布局\n\n通常，在调用 `graph.render()` 后，G6 会自动执行布局算法。\n\n如果需要手动执行布局算法，G6 提供了以下 API：\n\n- [layout](/api/layout#graphlayoutlayoutoptions)：执行布局算法\n- [setLayout](/api/layout#graphsetlayoutlayout)：设置布局算法\n- [stopLayout](/api/layout#graphstoplayout)：停止布局算法\n\n## 自定义布局\n\n如果内置布局算法无法满足需求，可以自定义布局算法，具体请参考[自定义布局](/manual/layout/custom-layout)。\n\n如果你正在从 G6 `5.0` 的布局配置迁移到 `5.1`，可继续阅读 [从 5.0 升级到 5.1（布局）](/manual/whats-new/upgrade-to-5-1)。\n","packages/site/docs/manual/plugin/Background.en.md":"---\ntitle: Background\norder: 1\n---\n\n## Overview\n\nSupport setting a background image for the canvas to make the canvas more hierarchical and narrative.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Setting a unified brand background color or image for charts\n- Distinguishing different functional areas through the background\n- Enhancing the visual hierarchy and aesthetics of charts\n\n## Basic Usage\n\nBelow is a simple example of initializing the Background plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // Specify an identifier for the plugin for dynamic updates\n      backgroundColor: '#f0f2f5', // Set background color\n      backgroundImage: 'url(https://example.com/bg.png)', // Set background image\n    },\n  ],\n});\n```\n\n## Configuration Options\n\nThe configuration options for the Background plugin inherit all CSS style properties ([CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)), so you can use any valid CSS property to configure the background. Here are some common configurations:\n\n| Property           | Description                   | Type   | Default Value     | Required |\n| ------------------ | ----------------------------- | ------ | ----------------- | -------- |\n| type               | Plugin type                   | string | `background`      | ✓        |\n| key                | Unique identifier for updates | string | -                 |          |\n| width              | Background width              | string | `100%`            |          |\n| height             | Background height             | string | `100%`            |          |\n| backgroundColor    | Background color              | string | -                 |          |\n| backgroundImage    | Background image              | string | -                 |          |\n| backgroundSize     | Background size               | string | `cover`           |          |\n| backgroundPosition | Background position           | string | -                 |          |\n| backgroundRepeat   | Background repeat             | string | -                 |          |\n| opacity            | Background opacity            | string | -                 |          |\n| transition         | Transition animation          | string | `background 0.5s` |          |\n| zIndex             | Stacking order                | string | -1                |          |\n\n> Note: The `zIndex` is set to -1 by default to prevent the background from covering other plugin DOM elements, such as grid lines.\n\n## Code Examples\n\n### Basic Background Color\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Using a Background Image\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Gradient Background\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Updating the Background\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// Subsequent updates\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## FAQs\n\n### 1. Background conflicts with other plugins?\n\nBy default, the `zIndex` of the background plugin is set to `-1` to ensure it is below other elements. If there are still conflicts, you can adjust the `zIndex` value:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // Lower z-index to avoid conflicts\n    },\n  ],\n});\n```\n","packages/site/docs/manual/plugin/Background.zh.md":"---\ntitle: 背景 Background\norder: 1\n---\n\n## 概述\n\n支持为图画布设置一个背景图片，让画布更有层次感、叙事性。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 为图表设置统一的品牌背景色或图片\n- 通过背景区分不同的功能区域\n- 增强图表的视觉层次感和美观度\n\n## 基本用法\n\n以下是一个简单的 Background 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // 为插件指定标识符，方便动态更新\n      backgroundColor: '#f0f2f5', // 设置背景色\n      backgroundImage: 'url(https://example.com/bg.png)', // 设置背景图\n    },\n  ],\n});\n```\n\n## 配置项\n\nBackground 插件的配置项继承了所有 CSS 样式属性（[CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration)），因此你可以使用任何合法的 CSS 属性来配置背景。以下是一些常用配置：\n\n| 属性               | 描述                         | 类型   | 默认值            | 必选 |\n| ------------------ | ---------------------------- | ------ | ----------------- | ---- |\n| type               | 插件类型                     | string | `background`      | ✓    |\n| key                | 插件唯一标识符，用于后续更新 | string | -                 |      |\n| width              | 背景宽度                     | string | `100%`            |      |\n| height             | 背景高度                     | string | `100%`            |      |\n| backgroundColor    | 背景颜色                     | string | -                 |      |\n| backgroundImage    | 背景图片                     | string | -                 |      |\n| backgroundSize     | 背景尺寸                     | string | `cover`           |      |\n| backgroundPosition | 背景位置                     | string | -                 |      |\n| backgroundRepeat   | 背景重复方式                 | string | -                 |      |\n| opacity            | 背景透明度                   | string | -                 |      |\n| transition         | 过渡动画                     | string | `background 0.5s` |      |\n| zIndex             | 层叠顺序                     | string | -1                |      |\n\n> 注意：`zIndex` 默认为 -1，这是为了避免背景覆盖其他插件的 DOM 元素，如网格线。\n\n## 代码示例\n\n### 基础背景色\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 使用背景图片\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 渐变背景\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新背景\n\n```js\n// 初始化时配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// 后续更新\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## 常见问题\n\n### 1. 背景与其他插件冲突？\n\n默认情况下，背景插件的 `zIndex` 设为 `-1`，以确保它位于其他元素之下。如果仍有冲突，可以调整 `zIndex` 值：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // 降低 z-index 避免冲突\n    },\n  ],\n});\n```\n","packages/site/docs/manual/plugin/BubbleSets.en.md":"---\ntitle: BubbleSets\norder: 2\n---\n\n## Overview\n\nThe BubbleSets plugin represents sets and their relationships by creating bubble shapes, helping users intuitively understand logical relationships such as intersections and unions between sets. It is a tool to enhance data visualization effects, especially suitable for displaying complex data set relationships.\n\n## Use Cases\n\nThe BubbleSets plugin is mainly suitable for the following scenarios:\n\n- Displaying relationships between sets (e.g., intersections, unions)\n- Enhancing the expressive ability of data visualization\n- Identifying specific sets of nodes or edges in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the BubbleSets plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // List of node IDs to be enclosed\n      label: true, // Whether to display labels\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## Configuration Options\n\n| Property                 | Description                                                                              | Type                                                           | Default Value | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| type                     | Plugin type                                                                              | string                                                         | `bubble-sets` | ✓        |\n| key                      | Unique identifier for the plugin for subsequent updates                                  | string                                                         | -             |          |\n| members                  | Member elements, including nodes and edges, [example](#members)                          | string[]                                                       | -             | ✓        |\n| avoidMembers             | Elements to avoid, not included when drawing contours (currently supports setting nodes) | string[]                                                       | -             |          |\n| label                    | Whether to display labels                                                                | boolean                                                        | true          |          |\n| labelPlacement           | Label position                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |          |\n| labelBackground          | Whether to display background                                                            | boolean                                                        | false         |          |\n| labelPadding             | Label padding                                                                            | number \\| number[]                                             | 0             |          |\n| labelCloseToPath         | Whether the label is close to the contour, [example](#labelclosetopath)                  | boolean                                                        | true          |          |\n| labelAutoRotate          | Whether the label rotates with the contour, [example](#labelautorotate)                  | boolean                                                        | true          |          |\n| labelOffsetX             | Label x-axis offset                                                                      | number                                                         | 0             |          |\n| labelOffsetY             | Label y-axis offset                                                                      | number                                                         | 0             |          |\n| labelMaxWidth            | Maximum width of the text, automatically ellipsized if exceeded                          | number                                                         | -             |          |\n| maxRoutingIterations     | Maximum number of iterations for calculating paths between members                       | number                                                         | 100           |          |\n| maxMarchingIterations    | Maximum number of iterations for calculating contours                                    | number                                                         | 20            |          |\n| pixelGroup               | Number of pixels per potential area group, used to improve speed                         | number                                                         | 4             |          |\n| edgeR0                   | Edge radius parameter R0                                                                 | number                                                         | -             |          |\n| edgeR1                   | Edge radius parameter R1                                                                 | number                                                         | -             |          |\n| nodeR0                   | Node radius parameter R0                                                                 | number                                                         | -             |          |\n| nodeR1                   | Node radius parameter R1                                                                 | number                                                         | -             |          |\n| morphBuffer              | Morph buffer size                                                                        | number                                                         |               |          |\n| threshold                | Threshold                                                                                | number                                                         | -             |          |\n| memberInfluenceFactor    | Member influence factor                                                                  | number                                                         | -             |          |\n| edgeInfluenceFactor      | Edge influence factor                                                                    | number                                                         | -             |          |\n| nonMemberInfluenceFactor | Non-member influence factor                                                              | number                                                         | -             |          |\n| virtualEdges             | Whether to use virtual edges                                                             | boolean                                                        | -             |          |\n\n### members\n\nMember elements, including nodes and edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\nExample: Do not let the label stick to the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\nExample: Do not let the label rotate with the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Usage Examples\n\n### Basic BubbleSets\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom BubbleSets Style\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visualization effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/BubbleSets.zh.md":"---\ntitle: 气泡集 BubbleSets\norder: 2\n---\n\n## 概述\n\nBubbleSets 插件通过创建气泡形状来表示集合及其关系，帮助用户直观地理解集合间的交集、并集等逻辑关系。它是一种增强数据可视化效果的工具，特别适用于展示复杂的数据集合关系。\n\n## 使用场景\n\nBubbleSets 插件主要适用于以下场景：\n\n- 展示集合间的关系（如交集、并集）\n- 增强数据可视化的表达能力\n- 在复杂网络图中标识特定节点或边的集合\n\n## 基本用法\n\n以下是一个简单的 BubbleSets 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // 需要包裹的节点 ID 列表\n      label: true, // 是否显示标签\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## 配置项\n\n| 属性                     | 描述                                                             | 类型                                                           | 默认值        | 必选 |\n| ------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | ---- |\n| type                     | 插件类型                                                         | string                                                         | `bubble-sets` | ✓    |\n| key                      | 插件唯一标识符，用于后续更新                                     | string                                                         | -             |      |\n| members                  | 成员元素，包括节点和边，[示例](#members)                         | string[]                                                       | -             | ✓    |\n| avoidMembers             | 需要避开的元素，在绘制轮廓时不会包含这些元素（目前支持设置节点） | string[]                                                       | -             |      |\n| label                    | 是否显示标签                                                     | boolean                                                        | true          |      |\n| labelPlacement           | 标签位置                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |      |\n| labelBackground          | 是否显示背景                                                     | boolean                                                        | false         |      |\n| labelPadding             | 标签内边距                                                       | number \\| number[]                                             | 0             |      |\n| labelCloseToPath         | 标签是否贴合轮廓，[示例](#labelclosetopath)                      | boolean                                                        | true          |      |\n| labelAutoRotate          | 标签是否跟随轮廓旋转，[示例](#labelautorotate)                   | boolean                                                        | true          |      |\n| labelOffsetX             | 标签 x 轴偏移量                                                  | number                                                         | 0             |      |\n| labelOffsetY             | 标签 y 轴偏移量                                                  | number                                                         | 0             |      |\n| labelMaxWidth            | 文本的最大宽度，超出会自动省略                                   | number                                                         | -             |      |\n| maxRoutingIterations     | 计算成员之间路径的最大迭代次数                                   | number                                                         | 100           |      |\n| maxMarchingIterations    | 计算轮廓的最大迭代次数                                           | number                                                         | 20            |      |\n| pixelGroup               | 每个潜在区域组的像素数，用于提高速度                             | number                                                         | 4             |      |\n| edgeR0                   | 边的半径参数 R0                                                  | number                                                         | -             |      |\n| edgeR1                   | 边的半径参数 R1                                                  | number                                                         | -             |      |\n| nodeR0                   | 节点的半径参数 R0                                                | number                                                         | -             |      |\n| nodeR1                   | 节点的半径参数 R1                                                | number                                                         | -             |      |\n| morphBuffer              | 形态缓冲区大小                                                   | number                                                         |               |      |\n| threshold                | 阈值                                                             | number                                                         | -             |      |\n| memberInfluenceFactor    | 成员影响因子                                                     | number                                                         | -             |      |\n| edgeInfluenceFactor      | 边影响因子                                                       | number                                                         | -             |      |\n| nonMemberInfluenceFactor | 非成员影响因子                                                   | number                                                         | -             |      |\n| virtualEdges             | 是否使用虚拟边                                                   | boolean                                                        | -             |      |\n\n### members\n\n成员元素，包括节点和边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\n示例：不让 label 贴合轮廓\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\n示例：不让label标签跟随轮廓旋转\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 使用示例\n\n### 基础 BubbleSets\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义 BubbleSets 样式\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Contextmenu.en.md":"---\ntitle: Contextmenu\norder: 3\n---\n\n## Overview\n\nThe context menu, also known as the right-click menu, is a menu that appears when a user clicks on a specific area. It supports triggering custom events before and after clicking. Through the context menu, specific element operations can be integrated, making it convenient to control a particular item when needed.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Various interactions with elements: viewing nodes, viewing edges, deleting nodes, etc.\n\n## Basic Usage\n\nBelow is a simple example of initializing the Contextmenu plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // Enable right-click menu only on nodes, by default all elements are enabled\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: 'View Details', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('Display node details');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property       | Description                                                                                                               | Type                                                                              | Default Value    | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | -------- |\n| className      | Additional class name for the menu DOM                                                                                    | string                                                                            | `g6-contextmenu` |          |\n| trigger        | How to trigger the right-click menu: `contextmenu` for right-click, `click` for click                                     | `click` \\| `contextmenu`                                                          | `contextmenu`    |          |\n| offset         | Offset of the menu display in X and Y directions                                                                          | [number, number]                                                                  | [4, 4]           |          |\n| onClick        | Callback method triggered after the menu is clicked, [example](#onclick)                                                  | (value: string, target: HTMLElement, current: Element) => void                    | -                |          |\n| getItems       | Returns the list of menu items, supports `Promise` type return value. It is a shortcut configuration for `getContent`     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |          |\n| getContent     | Returns the content of the menu, supports `Promise` type return value, can also use `getItems` for shortcut configuration | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |          |\n| loadingContent | Menu content used when `getContent` returns a `Promise`                                                                   | HTMLElement \\| string                                                             | -                |          |\n| enable         | Whether it is available, determines whether the right-click menu is supported by parameters, by default all are available | boolean \\| (event: IElementEvent) => boolean                                      | true             |          |\n\n### Item\n\nEach menu item (Item) contains the following properties:\n\n| Property | Description                          | Type     | Required |\n| -------- | ------------------------------------ | -------- | -------- |\n| name     | Name displayed for the menu item     | `string` | ✓        |\n| value    | Value corresponding to the menu item | `string` | ✓        |\n\n### onClick\n\nThis function is triggered after clicking a menu item, and the function has three parameters:\n\n- value: Corresponds to the value of the menu item\n- target: The DOM node of the menu item container\n- current: The element that triggered the menu item, for example, if it is a node, you can use `current` to get the node information (id), or to modify the element\n\n## Code Examples\n\n### Basic Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + value + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: 'View Details', value: 'detail' },\n          { name: 'Delete', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### Edge Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: 'Change Start Point', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('Execute change start point operation here');\n      },\n      // Enable right-click menu only on edges\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### Asynchronous Loading of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // Enable right-click menu only on nodes\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Dynamic Control of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: 'Delete Node',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: 'Move Edge',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Contextmenu.zh.md":"---\ntitle: 上下文菜单 Contextmenu\norder: 3\n---\n\n## 概述\n\n上下文菜单（Contextmenu），也被称为右键菜单，是当用户在某个特定区域上点击后出现的一个菜单。支持在点击前后，触发自定义事件。通过上下文菜单，可以将一些具体元素的操作集成在其中，方便对某一项来进行需要时的单独控制。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 元素的各种交互：查看节点、查看边、删除节点等等交互操作\n\n## 基本用法\n\n以下是一个简单的 Contextmenu 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // 只在节点上开启右键菜单，默认全部元素都开启\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: '查看详情', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('展示节点详情');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                            | 类型                                                                              | 默认值           | 必选 |\n| -------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | ---- |\n| className      | 给菜单的 DOM 追加的类名                                                         | string                                                                            | `g6-contextmenu` |      |\n| trigger        | 如何触发右键菜单：`contextmenu` 表示右键触发，`click` 表示点击触发              | `click` \\| `contextmenu`                                                          | `contextmenu`    |      |\n| offset         | 菜单显式 X、Y 方向的偏移量                                                      | [number, number]                                                                  | [4, 4]           |      |\n| onClick        | 当菜单被点击后，触发的回调方法，[示例](#onclick)                                | (value: string, target: HTMLElement, current: Element) => void                    | -                |      |\n| getItems       | 返回菜单的项目列表，支持 `Promise` 类型的返回值。是 `getContent` 的快捷配置     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |      |\n| getContent     | 返回菜单的内容，支持 `Promise` 类型的返回值，也可以使用 `getItems` 进行快捷配置 | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |      |\n| loadingContent | 当 `getContent` 返回一个 `Promise` 时，使用的菜单内容                           | HTMLElement \\| string                                                             | -                |      |\n| enable         | 是否可用，通过参数判断是否支持右键菜单，默认是全部可用                          | boolean \\| (event: IElementEvent) => boolean                                      | true             |      |\n\n### Item\n\n每个菜单项目 (Item) 包含以下属性：\n\n| 属性  | 描述             | 类型     | 必选 |\n| ----- | ---------------- | -------- | ---- |\n| name  | 菜单项显示的名字 | `string` | ✓    |\n| value | 菜单项对应的值   | `string` | ✓    |\n\n### onClick\n\n点击菜单项后会触发该函数，函数有三个参数：\n\n- value: 对应菜单项的 value\n- target: 对应菜单项容器的 dom 节点\n- current: 对应触发菜单项的元素，例如是节点则可以通过 `current` 来获取到节点的信息(id)等，或者来对元素进行修改\n\n## 代码示例\n\n### 基础右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '查看详情', value: 'detail' },\n          { name: '删除', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### 边的右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: '变更起点', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('这里执行变更起点操作');\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### 异步加载菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 动态控制菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: '删除节点',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: '移动边',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/EdgeBundling.en.md":"---\ntitle: EdgeBundling\norder: 4\n---\n\n## Overview\n\nEdge bundling is a graph visualization technique used to reduce visual clutter in complex network graphs and to reveal high-level patterns and structures in the graph. Its purpose is to bundle adjacent edges together.\n\nThe edge bundling plugin provided in G6 is based on the implementation of the [FEDB (Force-Directed Edge Bundling for Graph Visualization)](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf) paper: modeling edges as flexible springs that can attract each other and bundling them through a self-organizing process.\n\n## Use Cases\n\nThe edge bundling plugin is mainly suitable for the following scenarios:\n\n- Reducing visual clutter in complex network graphs\n- Revealing high-level patterns and structures in the graph\n- Improving the readability and aesthetics of large-scale graph data\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeBundling plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property        | Description                                                                                                                                                                                            | Type   | Default Value   | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | --------------- | -------- |\n| type            | Plugin type, used to identify the plugin as an edge bundling plugin                                                                                                                                    | string | `edge-bundling` | ✓        |\n| key             | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                      | string | -               |          |\n| bundleThreshold | Edge compatibility threshold, determines which edges should be bundled together, the larger the value, the fewer edges are bundled, [example](#bundlethreshold)                                        | number | 0.6             |          |\n| cycles          | Number of simulation cycles, controls the number of execution rounds of the edge bundling simulation                                                                                                   | number | 6               |          |\n| divisions       | Initial number of cut points, in subsequent cycles, the number of cut points will gradually increase according to divRate, affecting the degree of edge subdivision                                    | number | 1               |          |\n| divRate         | Growth rate of cut points, determines the growth rate of cut points in each cycle                                                                                                                      | number | 2               |          |\n| iterations      | Specifies the number of iterations executed in the first cycle, in subsequent cycles, the number of iterations will gradually decrease according to iterRate, affecting the accuracy of the simulation | number | 90              |          |\n| iterRate        | Iteration decrement rate, controls the reduction ratio of iterations in each cycle                                                                                                                     | number | 2/3             |          |\n| K               | Edge strength, affects the attraction and repulsion between edges, [example](#k)                                                                                                                       | number | 0.1             |          |\n| lambda          | Initial step size, in subsequent cycles, the step size will double increment, affecting the magnitude of node movement during edge bundling                                                            | number | 0.1             |          |\n\n### bundleThreshold\n\nEdge compatibility threshold, determines which edges should be bundled together. The larger the value, the fewer edges are bundled, and vice versa.\n\n- A lower bundleThreshold value (e.g., 0.4) will cause more edges to be bundled together, forming a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // Lower edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge compatibility threshold\">\n\n- A higher bundleThreshold value (e.g., 0.8) will cause fewer edges to be bundled together, maintaining more independent edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge compatibility threshold\">\n\n### K\n\nEdge strength, affects the attraction and repulsion between edges. A higher K value will make the attraction between edges stronger, resulting in a tighter bundling effect.\n\n- A lower K value (e.g., 0.05) will make the attraction between edges weaker, resulting in a weaker bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // Lower edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge strength\">\n\n- A higher K value (e.g., 0.2) will make the attraction between edges stronger, resulting in a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // Higher edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge strength\">\n\n## Code Examples\n\n### Basic Edge Bundling\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['edge-bundling'],\n});\n```\n\n### Custom Styles\n\nYou can customize the parameters of edge bundling as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n      cycles: 8, // More simulation cycles\n      K: 0.2, // Stronger edge strength\n    },\n  ],\n});\n```\n\n### Dynamic Update of Edge Bundling\n\nUse the key identifier to dynamically update edge bundling properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// Subsequent dynamic update\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // Update edge compatibility threshold\n  cycles: 10, // Update number of simulation cycles\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/EdgeBundling.zh.md":"---\ntitle: 边绑定 EdgeBundling\norder: 4\n---\n\n## 概述\n\n边绑定（Edge Bundling）是一种图可视化技术，用于减少复杂网络图中的视觉混乱，并展示图中的高级别模式和结构。其目的是将相邻的边捆绑在一起。\n\nG6 中提供的边绑定插件是基于 [FEDB（Force-Directed Edge Bundling for Graph Visualization）](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf)论文的实现：将边建模为可以相互吸引的柔性弹簧，通过自组织的方式进行捆绑。\n\n## 使用场景\n\n边绑定插件主要适用于以下场景：\n\n- 减少复杂网络图中的视觉混乱\n- 揭示图中的高级别模式和结构\n- 提高大规模图数据的可读性和美观性\n\n## 基本用法\n\n以下是一个简单的 EdgeBundling 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性            | 描述                                                                                               | 类型   | 默认值          | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------- | ------ | --------------- | ---- |\n| type            | 插件类型，用于标识该插件为边捆绑插件                                                               | string | `edge-bundling` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                   | string | -               |      |\n| bundleThreshold | 边兼容性阈值，该值决定了哪些边应该被绑定在一起，值越大，绑定的边越少，[示例](#bundlethreshold)     | number | 0.6             |      |\n| cycles          | 模拟周期数，控制边捆绑模拟的执行轮数                                                               | number | 6               |      |\n| divisions       | 初始切割点数，在后续的周期中，切割点数将根据 divRate 逐步递增，影响边的细分程度                    | number | 1               |      |\n| divRate         | 切割点数增长率，决定了每一轮周期中切割点数的增长幅度                                               | number | 2               |      |\n| iterations      | 指定在第一个周期中执行的迭代次数，在后续的周期中，迭代次数将根据 iterRate 逐步递减，影响模拟的精度 | number | 90              |      |\n| iterRate        | 迭代次数递减率，控制每一轮周期中迭代次数的减少比例                                                 | number | 2\\/3            |      |\n| K               | 边的强度，影响边之间的吸引力和排斥力，[示例](#k)                                                   | number | 0.1             |      |\n| lambda          | 初始步长，在后续的周期中，步长将双倍递增，影响边捆绑过程中节点移动的幅度                           | number | 0.1             |      |\n\n### bundleThreshold\n\n边兼容性阈值，该值决定了哪些边应该被绑定在一起。值越大，绑定的边越少，反之则绑定的边越多。\n\n- 较低的 bundleThreshold 值（如 0.4）会使更多的边被绑定在一起，形成更明显的捆绑效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // 较低的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边兼容性阈值\">\n\n- 较高的 bundleThreshold 值（如 0.8）会使较少的边被绑定在一起，保持更多的独立边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 较高的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边兼容性阈值\">\n\n### K\n\n边的强度，影响边之间的吸引力和排斥力。较高的 K 值会使边之间的吸引力更强，从而形成更紧密的捆绑效果。\n\n- 较低的 K 值（如 0.05）会使边之间的吸引力较弱，边的捆绑效果较弱。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // 较低的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边强度\">\n\n- 较高的 K 值（如 0.2）会使边之间的吸引力较强，边的捆绑效果更明显。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // 较高的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边强度\">\n\n## 代码示例\n\n### 基础边绑定\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['edge-bundling'],\n});\n```\n\n### 自定义样式\n\n您可以根据需要自定义边绑定的参数：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 更高的边兼容性阈值\n      cycles: 8, // 更多模拟周期\n      K: 0.2, // 更强的边强度\n    },\n  ],\n});\n```\n\n### 动态更新边绑定\n\n使用 key 标识符可以在运行时动态更新边绑定属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // 更新边兼容性阈值\n  cycles: 10, // 更新模拟周期数\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/EdgeFilterLens.en.md":"---\ntitle: EdgeFilterLens\norder: 5\n---\n\n## Overview\n\nThe Edge Filter Lens plugin allows you to keep the edges of interest within the lens range, while other edges will not be displayed in that range. This is an important visualization exploration tool that can help users focus on edge relationships in specific areas.\n\n## Use Cases\n\n- Need to focus on viewing edge relationships in local areas\n- Highlight connections between specific nodes in complex networks\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeFilterLens plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // Follow mouse movement\n      r: 60, // Set lens radius\n      nodeType: 'both', // Edge display condition\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                                                                                                                                                                                 | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                  | `edge-filter-lens`                          | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                                                                                                                                                                                           | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the lens:<br/>- `pointermove`: The lens always follows the mouse movement <br/>- `click`: Move the lens to the click position when clicking on the canvas <br/>- `drag`: Move the lens by dragging                                                                                                                                                                           | `pointermove` \\| `click` \\| `drag`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the lens                                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                  | 60                                          |          |\n| maxR           | Maximum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to scale the lens radius: `wheel`: Scale the lens radius by the wheel                                                                                                                                                                                                                                                                                                                | `wheel`                                                                                                                                                                 | -                                           |          |\n| nodeType       | Edge display condition:<br/> - `both`: The edge is displayed only when both the source and target nodes are in the lens <br/> - `source`: The edge is displayed only when the source node is in the lens<br/> - `target`: The edge is displayed only when the target node is in the lens <br/> - `either`: The edge is displayed as long as either the source or target node is in the lens | `both` \\| `source` \\| `target` \\| `either`                                                                                                                              | `both`                                      |          |\n| filter         | Filter out elements that are never displayed in the lens                                                                                                                                                                                                                                                                                                                                    | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                       | () => true                                  |          |\n| style          | Style of the lens, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                          | object                                                                                                                                                                  |                                             |          |\n| nodeStyle      | Style of nodes in the lens                                                                                                                                                                                                                                                                                                                                                                  | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: false }`                          |          |\n| edgeStyle      | Style of edges in the lens                                                                                                                                                                                                                                                                                                                                                                  | [EdgeStyle](/en/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/en/manual/data#边数据edgedata)) => [EdgeStyle](/en/manual/element/edge/base-edge#style))   | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                                                                                                                                                                                           | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nStyle properties of the circular lens.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#fff`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | 1             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.8           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the lens:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Edge Filter Lens](/en/examples/plugin/edge-filter-lens/#basic)\n","packages/site/docs/manual/plugin/EdgeFilterLens.zh.md":"---\ntitle: 边过滤镜 EdgeFilterLens\norder: 5\n---\n\n## 概述\n\n边过滤镜插件可以将关注的边保留在过滤镜范围内，其他边将在该范围内不显示。这是一个重要的可视化探索工具，可以帮助用户聚焦于特定区域的边关系。\n\n## 使用场景\n\n- 需要聚焦查看局部区域的边关系\n- 在复杂网络中突出显示特定节点之间的连接\n\n## 基本用法\n\n以下是一个简单的 EdgeFilterLens 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // 跟随鼠标移动\n      r: 60, // 设置透镜半径\n      nodeType: 'both', // 边的显示条件\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                                                                       | 类型                                                                                                                                                           | 默认值               | 必选 |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                                                                                   | string                                                                                                                                                         | `edge-filter-lens`   | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                                                                                           | string                                                                                                                                                         | -                    |      |\n| trigger        | 移动透镜的方式：<br/>- `pointermove`：透镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动透镜到点击位置 <br/>- `drag`：通过拖拽方式移动透镜                                                                                                                | `pointermove` \\| `click` \\| `drag`                                                                                                                             | `pointermove`        |      |\n| r              | 透镜的半径                                                                                                                                                                                                                                                 | number                                                                                                                                                         | 60                   |      |\n| maxR           | 透镜的最大半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 画布宽高最小值的一半 |      |\n| minR           | 透镜的最小半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 0                    |      |\n| scaleRBy       | 缩放透镜半径的方式：`wheel`：通过滚轮缩放透镜的半径                                                                                                                                                                                                        | `wheel`                                                                                                                                                        | -                    |      |\n| nodeType       | 边显示的条件：<br/> - `both`：只有起始节点和目标节点都在透镜中时，边才会显示 <br/> - `source`：只有起始节点在透镜中时，边才会显示<br/> - `target`：只有目标节点在透镜中时，边才会显示 <br/> - `either`：只要起始节点或目标节点有一个在透镜中时，边就会显示 | `both` \\| `source` \\| `target` \\| `either`                                                                                                                     | `both`               |      |\n| filter         | 过滤出始终不在透镜中显示的元素                                                                                                                                                                                                                             | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                              | () => true           |      |\n| style          | 透镜的样式，[配置项](#style)                                                                                                                                                                                                                               | object                                                                                                                                                         |                      |      |\n| nodeStyle      | 在透镜中节点的样式                                                                                                                                                                                                                                         | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: false }`   |      |\n| edgeStyle      | 在透镜中边的样式                                                                                                                                                                                                                                           | [EdgeStyle](/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/manual/data#边数据edgedata)) => [EdgeStyle](/manual/element/edge/base-edge#style))   | `{ label: true }`    |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                                                                                           | boolean                                                                                                                                                        | true                 |      |\n\n### style\n\n圆形透镜的样式属性。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#fff` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | 1      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.8    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义透镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [边过滤镜](/examples/plugin/edge-filter-lens/#basic)\n","packages/site/docs/manual/plugin/Fisheye.en.md":"---\ntitle: Fisheye\norder: 6\n---\n\n## Overview\n\nThe Fisheye plugin is designed for focus+context exploration scenarios. It can magnify the area of interest while ensuring that the context and the relationship between the context and the focus center are not lost. It is an important visualization exploration tool.\n\n## Use Cases\n\n- Highlight certain areas during presentations\n- Magnify details locally without losing the overall view\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fisheye plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // Move fisheye by dragging\n      d: 1.5, // Set distortion factor\n      r: 120, // Set fisheye radius\n      showDPercent: true, // Show distortion degree\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                   | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                   | string                                                                                                                                                                  | `fisheye`                                   | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                             | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the fisheye:<br/>- `pointermove`: The fisheye always follows the mouse movement <br/>- `click`: Move the fisheye to the click position when clicking on the canvas <br/>- `drag`: Move the fisheye by dragging | `pointermove` \\| `drag` \\| `click`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the fisheye                                                                                                                                                                                                         | number                                                                                                                                                                  | 120                                         |          |\n| maxR           | Maximum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | 0                                           |          |\n| d              | Distortion factor                                                                                                                                                                                                             | number                                                                                                                                                                  | 1.5                                         |          |\n| maxD           | Maximum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 5                                           |          |\n| minD           | Minimum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to adjust the fisheye radius:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                                     | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| scaleDBy       | Method to adjust the fisheye distortion factor:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                          | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| showDPercent   | Whether to show the distortion factor value in the fisheye                                                                                                                                                                    | boolean                                                                                                                                                                 | true                                        |          |\n| style          | Style of the fisheye, [configuration options](#style)                                                                                                                                                                         | object                                                                                                                                                                  | -                                           |          |\n| nodeStyle      | Style of nodes in the fisheye                                                                                                                                                                                                 | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                             | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nCircular style properties for configuring the appearance of the fisheye.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#ccc`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | -             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.1           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n### Zoom Control\n\n`scaleRBy` and `scaleDBy` can be used to control the adjustment method of the fisheye's radius and distortion factor respectively:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // Adjust radius by wheel\n      scaleRBy: 'wheel',\n      // Adjust distortion factor by dragging\n      scaleDBy: 'drag',\n      // Set range for radius and distortion factor\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\nNote: When `trigger`, `scaleRBy`, and `scaleDBy` are all set to `'drag'`, the priority order is `trigger` > `scaleRBy` > `scaleDBy`, and only the highest priority configuration item will bind the drag event. Similarly, if `scaleRBy` and `scaleDBy` are both set to `'wheel'`, only `scaleRBy` will bind the wheel event.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the fisheye:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Fisheye.zh.md":"---\ntitle: 鱼眼放大镜 Fisheye\norder: 6\n---\n\n## 概述\n\n鱼眼放大镜插件是为 focus+context 的探索场景设计的，它能够在放大关注区域的同时，保证上下文以及上下文与关注中心的关系不丢失，是一个重要的可视化探索工具。\n\n## 使用场景\n\n- 在演示过程中需要突出展示某些区域内容\n- 需要局部放大查看细节时，同时又不想失去整体视图\n\n## 基本用法\n\n以下是一个简单的 Fisheye 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // 通过拖拽移动鱼眼\n      d: 1.5, // 设置畸变因子\n      r: 120, // 设置鱼眼半径\n      showDPercent: true, // 显示畸变程度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                          | 类型                                                                                                                                                           | 默认值                 | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                      | string                                                                                                                                                         | `fisheye`              | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                              | string                                                                                                                                                         | -                      |      |\n| trigger        | 用于控制鱼眼放大镜的移动方式，支持以下三种配置：<br/>- `pointermove`：鱼眼放大镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动鱼眼放大镜到点击位置 <br/>- `drag`：通过拖拽方式移动鱼眼放大镜 | `pointermove` \\| `drag` \\| `click`                                                                                                                             | `pointermove`          |      |\n| r              | 鱼眼放大镜半径                                                                                                                                                                                | number                                                                                                                                                         | 120                    |      |\n| maxR           | 鱼眼放大镜可调整的最大半径                                                                                                                                                                    | number                                                                                                                                                         | 画布宽高的最小值的一半 |      |\n| minR           | 鱼眼放大镜可调整的最小半径                                                                                                                                                                    | number                                                                                                                                                         | 0                      |      |\n| d              | 畸变因子                                                                                                                                                                                      | number                                                                                                                                                         | 1.5                    |      |\n| maxD           | 鱼眼放大镜可调整的最大畸变因子                                                                                                                                                                | number                                                                                                                                                         | 5                      |      |\n| minD           | 鱼眼放大镜可调整的最小畸变因子                                                                                                                                                                | number                                                                                                                                                         | 0                      |      |\n| scaleRBy       | 调整鱼眼放大镜范围半径的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| scaleDBy       | 调整鱼眼放大镜畸变因子的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| showDPercent   | 是否在鱼眼放大镜中显示畸变因子数值                                                                                                                                                            | boolean                                                                                                                                                        | true                   |      |\n| style          | 鱼眼放大镜样式，[配置项](#style)                                                                                                                                                              | object                                                                                                                                                         | -                      |      |\n| nodeStyle      | 在鱼眼放大镜中的节点样式                                                                                                                                                                      | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: true }`      |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                              | boolean                                                                                                                                                        | true                   |      |\n\n### style\n\n圆形样式属性，用于配置鱼眼放大镜的外观。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#ccc` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | -      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.1    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n### 缩放控制\n\n通过 `scaleRBy` 和 `scaleDBy` 可以分别控制鱼眼放大镜的半径和畸变因子的调整方式：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // 通过滚轮调整半径\n      scaleRBy: 'wheel',\n      // 通过拖拽调整畸变因子\n      scaleDBy: 'drag',\n      // 设置半径和畸变因子的范围\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\n注意：当 `trigger`、`scaleRBy` 和 `scaleDBy` 同时设置为 `'drag'` 时，优先级顺序为 `trigger` > `scaleRBy` > `scaleDBy`，只会为优先级最高的配置项绑定拖拽事件。同理，如果 `scaleRBy` 和 `scaleDBy` 同时设置为 `'wheel'`，只会为 `scaleRBy` 绑定滚轮事件。\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### 自定义样式\n\n可以自定义鱼眼放大镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Fullscreen.en.md":"---\ntitle: Fullscreen\norder: 7\n---\n\n## Overview\n\nThe Fullscreen plugin allows users to expand the graph visualization content to the entire screen, providing a broader view and a better immersive experience.\n\n## Use Cases\n\nThe Fullscreen plugin is mainly suitable for the following scenarios:\n\n- Provide a broader view for viewing complex graph data\n- Enhance immersive experience, focusing on graph visualization content\n- Display graph data in presentations or reports\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fullscreen plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n      onEnter: () => {\n        console.log('Entered fullscreen mode');\n      },\n      onExit: () => {\n        console.log('Exited fullscreen mode');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property | Description                                                                                                      | Type                                 | Default Value | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ------------- | -------- |\n| type     | Plugin type                                                                                                      | string                               | `fullscreen`  | ✓        |\n| key      | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                | string                               | -             |          |\n| autoFit  | Whether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen | boolean                              | true          |          |\n| trigger  | Method to trigger fullscreen, [example](#trigger)                                                                | { request?: string; exit?: string; } | -             |          |\n| onEnter  | Callback after entering fullscreen                                                                               | () => void                           | -             |          |\n| onExit   | Callback after exiting fullscreen                                                                                | () => void                           | -             |          |\n\n### trigger\n\nThe trigger property is used to control the method of triggering fullscreen. It supports two configuration methods:\n\n#### Shortcut Key Configuration\n\nUse keyboard shortcuts to trigger fullscreen and exit fullscreen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n    },\n  ],\n});\n```\n\n#### Custom Trigger\n\nControl fullscreen by calling the request and exit methods.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\nWhether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen.\n\n- When set to true, the canvas will automatically resize to fit the entire screen.\n- When set to false, the canvas size remains unchanged.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\nThis method is used to enter fullscreen mode programmatically. It can be called on the plugin instance to expand the graph visualization to the entire screen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\nThis method is used to exit fullscreen mode programmatically. It can be called on the plugin instance to revert the graph visualization back to its original size.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Fullscreen.zh.md":"---\ntitle: 全屏展示 Fullscreen\norder: 7\n---\n\n## 概述\n\n全屏展示插件允许用户将图可视化内容扩展到整个屏幕，提供更广阔的视图和更好的沉浸式体验。\n\n## 使用场景\n\n全屏展示插件主要适用于以下场景：\n\n- 提供更广阔的视图，便于查看复杂图数据\n- 增强沉浸式体验，专注于图可视化内容\n- 在演示或报告中展示图数据\n\n## 基本用法\n\n以下是一个简单的 Fullscreen 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n      onEnter: () => {\n        console.log('进入全屏模式');\n      },\n      onExit: () => {\n        console.log('退出全屏模式');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性    | 描述                                                 | 类型                                 | 默认值       | 必选 |\n| ------- | ---------------------------------------------------- | ------------------------------------ | ------------ | ---- |\n| type    | 插件类型                                             | string                               | `fullscreen` | ✓    |\n| key     | 插件的唯一标识，可用于获取插件实例或更新插件选项     | string                               | -            |      |\n| autoFit | 是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸 | boolean                              | true         |      |\n| trigger | 触发全屏的方式，[示例](#trigger)                     | { request?: string; exit?: string; } | -            |      |\n| onEnter | 进入全屏后的回调                                     | () => void                           | -            |      |\n| onExit  | 退出全屏后的回调                                     | () => void                           | -            |      |\n\n### trigger\n\ntrigger 属性用于控制触发全屏的方式。它支持两种配置方式：\n\n#### 快捷键配置\n\n使用键盘快捷键来触发全屏和退出全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n    },\n  ],\n});\n```\n\n#### 自定义触发\n\n通过调用 request 和 exit 方法来控制全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\n是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸。\n\n- 设置为 true 时，画布会自动调整大小以适应整个屏幕。\n- 设置为 false 时，画布大小保持不变。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\n这个方法可以让你通过代码进入全屏模式。调用插件实例上的这个方法，就能把图形内容扩展到整个屏幕。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\n这个方法可以让你通过代码退出全屏模式。调用插件实例上的这个方法，就能把图形内容恢复到原来的大小。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/GridLine.en.md":"---\ntitle: GridLine\norder: 8\n---\n\n## Overview\n\nThe GridLine plugin provides visual auxiliary lines for the canvas, helping users precisely position and align graphic elements. It is an indispensable tool in graphic drawing.\n\n## Use Cases\n\nThe GridLine plugin is mainly suitable for the following scenarios:\n\n- Assisting users in precise drawing and element alignment\n- Providing visual references to enhance spatial awareness\n- Building a structured reference system when designing and editing graphics\n\n## Basic Usage\n\nBelow is a simple example of initializing the GridLine plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // Specify a unique identifier for dynamic updates\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## Configuration Options\n\n| Property        | Description                                                                                         | Type                                              | Default     | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------- | -------- |\n| type            | Plugin type                                                                                         | string                                            | `grid-line` | ✓        |\n| key             | Unique identifier for the plugin, used to get the plugin instance or update plugin options          | string                                            | -           |          |\n| border          | Whether to display the border                                                                       | boolean                                           | true        |          |\n| borderLineWidth | Border line width                                                                                   | number                                            | 1           |          |\n| borderStroke    | Border color, see [CSS border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color) | string                                            | `#eee`      |          |\n| borderStyle     | Border style, see [CSS border-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style) | string                                            | `solid`     |          |\n| follow          | Whether to follow canvas movements                                                                  | boolean \\| {translate ?: boolean, zoom?: boolean} | false       |          |\n| lineWidth       | Grid line width                                                                                     | number \\| string                                  | 1           |          |\n| size            | Grid unit size in pixels                                                                            | number                                            | 20          |          |\n| stroke          | Grid line color                                                                                     | string                                            | `#eee`      |          |\n\n### follow\n\nThe `follow` property controls whether the grid lines follow the canvas transformations. It supports two configuration methods:\n\n1. **Boolean Configuration**: When set to `true`, the grid lines follow both canvas translation and zoom; when set to `false`, they remain static.\n\n```js\n// Enable both translation and zoom following\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **Object Configuration**: Allows more precise control over the grid line following behavior.\n\n```js\n// Follow translation only, not zoom\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // Follow translation\n        zoom: false, // Do not follow zoom\n      },\n    },\n  ],\n});\n\n// Follow zoom only, not translation\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // Do not follow translation\n        zoom: true, // Follow zoom\n      },\n    },\n  ],\n});\n```\n\nWhen grid lines follow zoom, they maintain a relative position to the canvas content, making alignment references more precise. Following translation allows the grid to move with the canvas content, enhancing the visual experience of spatial continuity.\n\n## Code Examples\n\n### Basic Grid Line\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid-line'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### Custom Style\n\nYou can customize the grid line style as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid unit\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Follow Movement\n\nEnabling the follow option allows the grid to move with the canvas, enhancing user experience:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n```\n\nTry dragging/zooming the canvas to observe the grid following effect:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamic Grid Update\n\nUse the key identifier to dynamically update grid properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// Subsequent dynamic updates\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // Update grid size\n  stroke: '#ff4d4f', // Update grid color\n});\n```\n\n## Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","packages/site/docs/manual/plugin/GridLine.zh.md":"---\ntitle: 网格线 GridLine\norder: 8\n---\n\n## 概述\n\n网格线插件为画布提供可视化辅助线，帮助用户精确定位和对齐图形元素，是图形绘制中不可或缺的辅助工具。\n\n## 使用场景\n\n网格线插件主要适用于以下场景：\n\n- 辅助用户精确绘图和元素对齐\n- 提供视觉参考，增强空间感知\n- 在设计和编辑图形时构建结构化的参考系统\n\n## 基本用法\n\n以下是一个简单的 GridLine 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // 指定唯一标识符，便于后续动态更新\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## 配置项\n\n| 属性            | 描述                                                                                                     | 类型                                               | 默认值      | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------- | ---- |\n| type            | 插件类型                                                                                                 | string                                             | `grid-line` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                         | string                                             | -           |      |\n| border          | 是否显示边框                                                                                             | boolean                                            | true        |      |\n| borderLineWidth | 边框线宽                                                                                                 | number                                             | 1           |      |\n| borderStroke    | 边框颜色，详细属性参考 [CSS border-color](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-color) | string                                             | `#eee`      |      |\n| borderStyle     | 边框样式，详细属性参考 [CSS border-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-style) | string                                             | `solid`     |      |\n| follow          | 是否跟随画布移动                                                                                         | boolean \\｜ {translate ?: boolean, zoom?: boolean} | false       |      |\n| lineWidth       | 网格线宽度                                                                                               | number \\| string                                   | 1           |      |\n| size            | 网格单元大小，单位为像素                                                                                 | number                                             | 20          |      |\n| stroke          | 网格线颜色                                                                                               | string                                             | `#eee`      |      |\n\n### follow\n\n`follow` 属性用于控制网格线是否跟随画布的变换操作。它支持两种配置方式：\n\n1. **布尔值配置**：当设置为 `true` 时，网格线会同时跟随画布的平移和缩放；设置为 `false` 时则保持静态。\n\n```js\n// 同时启用跟随平移和缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **对象配置**：可以更精细地控制网格线的跟随行为。\n\n```js\n// 仅跟随平移，不跟随缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // 跟随平移\n        zoom: false, // 不跟随缩放\n      },\n    },\n  ],\n});\n\n// 仅跟随缩放，不跟随平移\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // 不跟随平移\n        zoom: true, // 跟随缩放\n      },\n    },\n  ],\n});\n```\n\n当网格线跟随缩放时，它会保持与画布内容的相对位置关系，使得对齐参考更加精准。跟随平移则让网格随着画布内容一起移动，增强空间连续性的视觉体验。\n\n## 代码示例\n\n### 基础网格线\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid-line'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义网格线的样式：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格单元\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 跟随移动\n\n启用 follow 选项可以让网格跟随画布移动，增强用户体验：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n```\n\n试着拖拽/缩放画布，观察网格的跟随效果：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新网格\n\n使用 key 标识符可以在运行时动态更新网格属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // 更新网格大小\n  stroke: '#ff4d4f', // 更新网格颜色\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","packages/site/docs/manual/plugin/History.en.md":"---\ntitle: History\norder: 9\n---\n\n## Overview\n\nThis plugin is used to implement the **Undo** and **Redo** functions in graph editing. By recording the historical state stack of user operations, it supports backtracking or restoring operations during graph interactions. The plugin provides users with comprehensive configuration options and APIs.\n\n## Usage Scenarios\n\nThe history plugin is suitable for all scenarios involving graph editing.\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## Basic Usage\n\nAdd this plugin in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['history'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property         | Description                                                                                                                                                                                                   | Type                                                           | Default Value | Required |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| afterAddCommand  | Called after a command is added to the `Undo/Redo` queue. `revert` is `true` for undo operations and `false` for redo operations                                                                              | (cmd: [Command](#command), revert: boolean) => void            | -             |          |\n| beforeAddCommand | Called before a command is added to the `Undo/Redo` queue. If this method returns `false`, the command will not be added to the queue. `revert` is `true` for undo operations and `false` for redo operations | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -             |          |\n| executeCommand   | Callback function when executing a command                                                                                                                                                                    | (cmd: [Command](#command)) => void                             | -             |          |\n| stackSize        | Maximum length of history records to be recorded                                                                                                                                                              | number                                                         | 0 (unlimited) |          |\n\n### Parameter Type Description\n\n#### `Command`\n\n```typescript\n// Single history command\ninterface Command {\n  current: CommandData; // Current data\n  original: CommandData; // Original data\n  animation: boolean; // Whether to enable animation\n}\n// Single history command data\ninterface CommandData {\n  add: GraphData; // Added data\n  update: GraphData; // Updated data\n  remove: GraphData; // Removed data\n}\n// Graph data\ninterface GraphData {\n  nodes?: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data\n  combos?: ComboData[]; // Combo data\n}\n```\n\n## API\n\nThe history plugin provides the following APIs for users to use as needed. For how to call plugin methods, please refer to the [Plugin Overview Document](/en/manual/plugin/overview#calling-plugin-methods)\n\n### History.canRedo()\n\nDetermines whether a **redo** operation can be performed. If there are records in the redo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanRedo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('Redo operation can be performed');\n} else {\n  console.log('Redo stack is empty, cannot redo');\n}\n```\n\n### History.canUndo()\n\nDetermines whether an **undo** operation can be performed. If there are records in the undo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanUndo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('Undo operation can be performed');\n} else {\n  console.log('Undo stack is empty, cannot undo');\n}\n```\n\n### History.clear()\n\nClears the history records, including the undo and redo stacks.\n\n```typescript\nclear(): void;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('History records cleared');\n```\n\n### History.on()\n\nListens to history events, allowing users to execute custom logic when specific events occur.\n\n```typescript\non(event: Loosen<HistoryEvent>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\nParameter Type Description:\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // When a command is undone\n    REDO = 'redo', // When a command is redone\n    CANCEL = 'cancel', // When a command is canceled\n    ADD = 'add', // When a command is added to the queue\n    CLEAR = 'clear', // When the history queue is cleared\n    CHANGE = 'change', // When the history queue changes\n  }\n  ```\n\n- Command\n\n  Please refer to the previous [Command](#parameter-type-description) type description\n\nExample:\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('Undo operation executed');\n});\n```\n\n### History.redo()\n\nPerforms a **redo** operation and returns the plugin instance. If the redo stack is empty, no operation is performed.\n\n```typescript\nredo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('Redo operation executed');\n```\n\n### History.undo()\n\nPerforms an **undo** operation and returns the plugin instance. If the undo stack is empty, no operation is performed.\n\n```typescript\nundo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('Undo operation executed');\n```\n\n### History.undoAndCancel()\n\nPerforms an undo operation without recording it in the history and returns the plugin instance. Note that this operation will clear the **redo** stack.\n\n```typescript\nundoAndCancel(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('Undo and cancel operation executed');\n```\n\n## History Modes\n\nThis plugin supports two history modes:\n\n### Default Mode\n\nIn default mode, every time a **render** is triggered (for example, after updating element data, the user actively executes the `graph.draw()` method to trigger rendering), the plugin records the data **before** and **after** rendering and stacks it as an operation record.\n\n### Custom Mode\n\n#### Scenario Description\n\nIn actual needs, a user's graph editing operation may involve **multiple renders**. For example, in one editing operation, first display nodes A and B, then display the connection from A to B. This involves two renders (i.e., the user needs to perform `graph.draw()` twice). In this scenario, the default mode will stack two history records, which are:\n\n- Display nodes A and B\n- Display the connection from A to B\n\nObviously, in actual business, one operation should only require one undo.\n\nBut here, when undoing this operation, the user needs to call the `undo` method twice, which means two undos are required.\n\n#### Scenario Support\n\nTo support such scenarios, G6 provides a batch controller (`BatchController`, [refer to the source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)), which is provided in the graph instance context.\n\nThe history plugin implements custom operation records based on this batch controller. The code example is as follows:\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // Start batch operation\ngraph.addNodeData(...); // Display nodes A and B\ngraph.draw(); // First render trigger\ngraph.addEdgeData(...); // Display the connection from A to B\ngraph.draw(); // Second render trigger\ngraph.context.batch.endBatch(); // End batch operation\n```\n\nIn the example:\n\n- By calling the `startBatch` method of the batch controller instance, the history plugin is informed that batch operations are now being performed. Before the batch operation ends, no matter how many renders are triggered, no history records should be stacked (the history plugin will record the change data for each render trigger).\n- After completing the last data change, call the `endBatch()` method. The history plugin listens for the completion of the batch operation and stacks this batch operation as a history record.\n\nFinally, the user only needs to perform one `undo` to undo.\n\n## Code Examples\n\nBelow are some common cases with corresponding code references.\n\n### Undo and Redo Button States\n\nIn actual business scenarios, you may need to customize the toolbar of the canvas, which involves the enable and disable states of the undo and redo buttons.\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\nIn the example, by listening to the `HistoryEvent.CHANGE` event, which is triggered when the history queue changes, it is determined in real-time whether undo and redo operations can be performed.\n\n### Determine Whether a Command is Allowed to Enter the Queue\n\nHere is a simple scenario: only the operation of removing elements is allowed to enter the history queue.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\nIn the example, the configuration option [beforeAddCommand](#beforeAddCommand) is used to determine whether there are elements removed in `cmd.current.remove`.\n","packages/site/docs/manual/plugin/History.zh.md":"---\ntitle: 历史记录 History\norder: 9\n---\n\n## 概述\n\n该插件用于实现图编辑的 **撤销（Undo）** 和 **重做（Redo）** 功能，通过记录用户操作的历史状态堆栈，支持在图交互过程中进行回溯或恢复操作。该插件为用户提供了完善的配置项和 API 。\n\n## 使用场景\n\n历史记录插件适用于所有涉及到图编辑的场景。\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一插件：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['history'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性             | 描述                                                                                                                                                                | 类型                                                           | 默认值      | 必选 |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------- | ---- |\n| afterAddCommand  | 当一个命令被添加到 `Undo/Redo` 队列后被调用。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作                                                           | (cmd: [Command](#command), revert: boolean) => void            | -           |      |\n| beforeAddCommand | 当一个命令被添加到 `Undo/Redo` 队列前被调用，如果该方法返回 `false`，那么这个命令将不会被添加到队列中。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作 | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -           |      |\n| executeCommand   | 执行命令时的回调函数                                                                                                                                                | (cmd: [Command](#command)) => void                             | -           |      |\n| stackSize        | 最多记录该数据长度的历史记录                                                                                                                                        | number                                                         | 0（不限制） |      |\n\n### 参数类型说明\n\n#### `Command`\n\n```typescript\n// 单条历史记录命令\ninterface Command {\n  current: CommandData; // 当前数据\n  original: CommandData; // 原始数据\n  animation: boolean; // 是否开启动画\n}\n// 单条历史记录命令数据\ninterface CommandData {\n  add: GraphData; // 新增的数据\n  update: GraphData; // 更新的数据\n  remove: GraphData; // 移除的数据\n}\n// 图数据\ninterface GraphData {\n  nodes?: NodeData[]; // 节点数据\n  edges?: EdgeData[]; // 边数据\n  combos?: ComboData[]; // Combo 数据\n}\n```\n\n## API\n\nhistory 插件提供了以下 API 供用户按需使用，调用插件方法的方式请参考 [插件总览文档](/manual/plugin/overview#调用插件方法)\n\n### History.canRedo()\n\n判断是否可以进行**重做**操作。如果重做堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanRedo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('可以进行重做操作');\n} else {\n  console.log('重做堆栈为空，无法重做');\n}\n```\n\n### History.canUndo()\n\n判断是否可以进行**撤销**操作。如果撤销堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanUndo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('可以进行撤销操作');\n} else {\n  console.log('撤销堆栈为空，无法撤销');\n}\n```\n\n### History.clear()\n\n清空历史记录，包括撤销和重做堆栈。\n\n```typescript\nclear(): void;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('历史记录已清空');\n```\n\n### History.on()\n\n监听历史记录事件，允许用户在特定事件发生时执行自定义逻辑。\n\n```typescript\non(event: Loosen/<HistoryEvent/>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\n参数类型说明：\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // 当命令被撤销时\n    REDO = 'redo', // 当命令被重做时\n    CANCEL = 'cancel', // 当命令被取消时\n    ADD = 'add', // 当命令被添加到队列时\n    CLEAR = 'clear', // 当历史队列被清空时\n    CHANGE = 'change', // 当历史队列发生变化时\n  }\n  ```\n\n- Command\n\n  请参考前面的 [Command](#参数类型说明) 类型说明\n\n示例：\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('执行了撤销操作');\n});\n```\n\n### History.redo()\n\n执行**重做**操作，并返回插件实例。如果重做堆栈为空，则不执行任何操作。\n\n```typescript\nredo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('执行了重做操作');\n```\n\n### History.undo()\n\n执行**撤销**操作，并返回插件实例。如果撤销堆栈为空，则不执行任何操作。\n\n```typescript\nundo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('执行了撤销操作');\n```\n\n### History.undoAndCancel()\n\n执行撤销操作且不计入历史记录，并返回插件实例。注意，执行该操作会清空**重做**栈。\n\n```typescript\nundoAndCancel(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('执行了撤销并取消操作');\n```\n\n## 历史记录模式\n\n该插件支持两种历史记录模式：\n\n### 默认模式\n\n默认模式下，每一次触发**渲染后**（比如更新元素数据后，用户主动执行 `graph.draw()` 方法触发渲染），插件会把**渲染前**和**渲染后**的数据记录下来并作为一次操作记录入栈。\n\n### 自定义模式\n\n#### 场景描述\n\n实际需求中，用户的一次图编辑操作可能涉及到**多次渲染**，比如，一次编辑操作中，首先把节点 A、B 展示出来，然后展示 A->B 的连线，这里就涉及到两次渲染（即用户需要进行两次 `graph.draw()` ），这种场景下，默认模式会入栈两次历史记录，分别是：\n\n- 展示节点 A 和 B\n- 展示 A->B 的连线\n\n显然，实际业务中，一次操作，也应该只需一次撤销。\n\n但这里在撤销本次操作时，用户需要调用两次 `undo` 方法，也就是需要进行两次撤销。\n\n#### 场景支持\n\n为了支持这样的场景，G6 提供了一个批量控制器（ `BatchController`，[可参考源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)），在图实例上下文中提供了这个批量控制器实例。\n\n历史记录插件则基于这个批量控制器，来实现自定义操作记录，代码示例如下：\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // 开始批量操作\ngraph.addNodeData(...); // 把节点 A、B 展示出来\ngraph.draw(); // 第一次触发渲染\ngraph.addEdgeData(...); // 把 A->B 连线展示出来\ngraph.draw(); // 第二次触发渲染\ngraph.context.batch.endBatch(); // 结束批量操作\n```\n\n示例中：\n\n- 通过调用批量控制器实例的 `startBatch` 方法，告诉历史记录插件，现在开始进行批量操作，在批量操作没有结束前，不管触发多少次渲染，都不能进行历史记录入栈（历史记录插件会把每次触发渲染的变更数据记录下来）\n- 在完成最后一次数据变更后，调用 `endBatch()` 方法，历史记录插件监听到批量操作完成，则把本次批量操作作为一次历史记录入栈\n\n最终，用户只需要进行一次 `undo` 即可撤销。\n\n## 代码示例\n\n下面列举一些常见的案例，并给出相应的代码参考\n\n### 撤销、重做按钮状态\n\n实际业务场景中，可能需要自定义画布的工具栏，也就涉及到撤销和重做按钮的启禁用状态\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\n示例中通过监听 `HistoryEvent.CHANGE` 事件，这个事件在历史队列发生变化时会触发，每次发生变化后，实时判断当前是否可以进行撤销和重做操作\n\n### 判断是否允许命令进入队列\n\n这里实现一个简单的场景：只有移除元素的操作才允许进入历史记录队列\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\n示例中通过配置项 [beforeAddCommand](#beforeAddCommand) 来实现，判断 `cmd.current.remove` 里面是否存在被移除的元素\n","packages/site/docs/manual/plugin/Hull.en.md":"---\ntitle: Hull\norder: 10\n---\n\n## Overview\n\nHull is used to process and represent the convex or concave polygon bounding box of a set of points. It can wrap a set of nodes in a minimal geometric shape, helping users better understand and analyze datasets.\n\n- **Convex Hull**: This is a convex polygon that contains all the points and has no indentations.\n- **Concave Hull**: This is a concave polygon that also contains all the points but may have indentations. The degree of indentation is controlled by the concavity parameter.\n\n## Usage Scenarios\n\nThe hull plugin is mainly applicable to the following scenarios:\n\n- Wrapping node collections in data visualization\n- Providing visual references to enhance spatial awareness\n- Identifying the collection relationship of specific nodes in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the Hull plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // Specify a unique identifier for subsequent dynamic updates\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n      concavity: Infinity, // Default to convex hull\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## Configuration Options\n\n| Property         | Description                                                                                              | Type                                               | Default Value | Required |\n| ---------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type             | Plugin type                                                                                              | string                                             | `hull`        | ✓        |\n| key              | Unique identifier for the plugin, used for subsequent updates                                            | string                                             | -             |          |\n| members          | Elements within the Hull, including nodes and edges                                                      | string[]                                           | -             | ✓        |\n| concavity        | Concavity, the larger the value, the smaller the concavity; default is Infinity representing Convex Hull | number                                             | Infinity      |          |\n| corner           | Corner type, options are `rounded` \\| `smooth` \\| `sharp`                                                | string                                             | `rounded`     |          |\n| padding          | Padding                                                                                                  | number                                             | `10`          |          |\n| label            | Whether to display the label                                                                             | boolean                                            | true          |          |\n| labelPlacement   | Label position                                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`      |          |\n| labelBackground  | Whether to display the background                                                                        | boolean                                            | false         |          |\n| labelPadding     | Label padding                                                                                            | number \\| number[]                                 | 0             |          |\n| labelCloseToPath | Whether the label is close to the hull                                                                   | boolean                                            | true          |          |\n| labelAutoRotate  | Whether the label rotates with the hull, effective only when closeToPath is true                         | boolean                                            | true          |          |\n| labelOffsetX     | X-axis offset                                                                                            | number                                             | 0             |          |\n| labelOffsetY     | Y-axis offset                                                                                            | number                                             | 0             |          |\n| labelMaxWidth    | Maximum width of the text, exceeding will automatically ellipsis                                         | number                                             | 0             |          |\n\nFor complete label styles, see [this link](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nThe concavity attribute is used to control the concavity of the Hull. When set to Infinity, a convex hull is generated; otherwise, a concave hull is generated.\n\n```js\n// Convex hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // Convex hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// Concave hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // Concave hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hull\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style of the Hull as needed, such as adjusting color, transparency, and other properties.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visual effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Hull.zh.md":"---\ntitle: 轮廓包围 Hull\norder: 10\n---\n\n## 概述\n\n轮廓包围（Hull）用于处理和表示一组点的凸多边形或凹多边形包围盒。它可以将一组节点包裹在一个最小的几何形状中，帮助用户更好地理解和分析数据集。\n\n- **凸包（Convex Hull）**：这是一个凸多边形，它包含所有的点，并且没有任何凹陷。\n- **凹包（Concave Hull）**：这是一个凹多边形，它同样包含所有的点，但是可能会有凹陷。凹包的凹陷程度由 concavity 参数控制。\n\n## 使用场景\n\n轮廓包围插件主要适用于以下场景：\n\n- 数据可视化中的节点集合包裹\n- 提供视觉参考，增强空间感知\n- 在复杂网络图中标识特定节点的集合关系\n\n## 基本用法\n\n以下是一个简单的 Hull 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // 指定唯一标识符，便于后续动态更新\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n      concavity: Infinity, // 默认为凸包\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## 配置项\n\n| 属性             | 描述                                                       | 类型                                               | 默认值    | 必选 |\n| ---------------- | ---------------------------------------------------------- | -------------------------------------------------- | --------- | ---- |\n| type             | 插件类型                                                   | string                                             | `hull`    | ✓    |\n| key              | 插件唯一标识符，用于后续更新                               | string                                             | -         |      |\n| members          | Hull 内的元素，包括节点和边                                | string[]                                           | -         | ✓    |\n| concavity        | 凹度，数值越大凹度越小；默认为 Infinity 代表为 Convex Hull | number                                             | Infinity  |      |\n| corner           | 拐角类型，可选值为 `rounded` \\| `smooth` \\| `sharp`        | string                                             | `rounded` |      |\n| padding          | 内边距                                                     | number                                             | `10`      |      |\n| label            | 是否显示标签                                               | boolean                                            | true      |      |\n| labelPlacement   | 标签位置                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`  |      |\n| labelBackground  | 是否显示背景                                               | boolean                                            | false     |      |\n| labelPadding     | 标签内边距                                                 | number \\| number[]                                 | 0         |      |\n| labelCloseToPath | 标签是否贴合轮廓                                           | boolean                                            | true      |      |\n| labelAutoRotate  | 标签是否跟随轮廓旋转，仅在 closeToPath 为 true 时生效      | boolean                                            | true      |      |\n| labelOffsetX     | x 轴偏移量                                                 | number                                             | 0         |      |\n| labelOffsetY     | y 轴偏移量                                                 | number                                             | 0         |      |\n| labelMaxWidth    | 文本的最大宽度，超出会自动省略                             | number                                             | 0         |      |\n\n完整的标签样式见[此链接](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nconcavity 属性用于控制 Hull 的凹度。当设置为 Infinity 时，生成的是凸包；否则会生成凹包。\n\n```js\n// 凸包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // 凸包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// 凹包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // 凹包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础 Hull\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义 Hull 的样式，例如调整颜色、透明度等属性。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n```\n\n```\n","packages/site/docs/manual/plugin/Legend.en.md":"---\ntitle: Legend\norder: 11\n---\n\n## Overview\n\nThe Legend plugin is used to display classification information of elements in the graph, supporting the display of classification information for nodes, edges, and combos. Through the legend, users can quickly perceive the classification information of related elements in the graph and quickly locate elements by clicking on the corresponding legend items, improving user browsing efficiency.\n\n## Usage Scenarios\n\nThis plugin is mainly used for:\n\n- Quickly classifying elements through the legend\n- Quickly highlighting and locating corresponding elements through the legend\n\n## Basic Usage\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property          | Description                                                                                                                                                                                    | Type                                                                                        | Default Value | Required |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type              | Plugin type                                                                                                                                                                                    | string                                                                                      | `legend`      | ✓        |\n| key               | Unique identifier for the plugin, used for subsequent updates                                                                                                                                  | string                                                                                      | -             |          |\n| trigger           | How the legend item triggers the corresponding item highlight: <br/>- `hover`: Triggered when the mouse enters the legend item <br/>- `click`: Triggered when the mouse clicks the legend item | `hover` \\| `click`                                                                          | `hover`       |          |\n| position          | Relative position of the legend on the canvas, [optional values](#cardinalplacement)                                                                                                           | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`      |          |\n| container         | Container to which the legend is mounted, if not provided, it is mounted to the container where the Graph is located                                                                           | HTMLElement \\| string                                                                       | -             |          |\n| className         | Legend canvas class name, not effective when an external container is passed                                                                                                                   | string                                                                                      | -             |          |\n| containerStyle    | Style of the legend container, not effective when an external container is passed                                                                                                              | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| nodeField         | Node classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| edgeField         | Edge classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| comboField        | Combo classification identifier                                                                                                                                                                | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| orientation       | Layout direction of legend items: <br/>- `horizontal`: Horizontal direction <br/>- `vertical`: Vertical direction                                                                              | `horizontal` \\| `vertical`                                                                  | 'horizontal'  |          |\n| layout            | Layout method: <br/>- `flex`: Flexible layout <br/>- `grid`: Grid layout                                                                                                                       | `flex` \\| `grid`                                                                            | `flex`        |          |\n| showTitle         | Whether to display the title                                                                                                                                                                   | boolean                                                                                     | false         |\n| titleText         | Title content                                                                                                                                                                                  | string                                                                                      | \"\"            |\n| x                 | Relative horizontal position of the legend on the canvas, higher priority than position                                                                                                        | number                                                                                      | -             |          |\n| y                 | Relative vertical position of the legend on the canvas, higher priority than position                                                                                                          | number                                                                                      | -             |          |\n| width             | Width of the legend                                                                                                                                                                            | number                                                                                      | 240           |          |\n| height            | Height of the legend                                                                                                                                                                           | number                                                                                      | 160           |          |\n| itemSpacing       | Spacing between the text of the legend item and the corresponding marker                                                                                                                       | number                                                                                      | 4             |          |\n| rowPadding        | Spacing between each row in the legend                                                                                                                                                         | number                                                                                      | 10            |          |\n| colPadding        | Spacing between each column in the legend                                                                                                                                                      | number                                                                                      | 10            |          |\n| itemMarkerSize    | Size of the legend item marker                                                                                                                                                                 | number                                                                                      | 16            |          |\n| itemLabelFontSize | Font size of the legend item text                                                                                                                                                              | number                                                                                      | 16            |          |\n| gridCol           | Maximum number of columns allowed for legend items when width permits                                                                                                                          | number                                                                                      | -             |          |\n| gridRow           | Maximum number of rows allowed for legend items when height permits                                                                                                                            | number                                                                                      | -             |          |\n\n### CardinalPlacement\n\nThe `position` property supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side near the top\n- `'left-bottom'`: Left side near the bottom\n- `'right-top'`: Right side near the top\n- `'right-bottom'`: Right side near the bottom\n\n## Code Examples\n\n### Basic Legend\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n### Custom Legend Position\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // You can quickly specify the position through position\n      // position: \"top-left\",\n      // Or you can more flexibly control the position of the legend through x, y\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### Custom Legend Item Layout\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // Control to display only one row\n      gridRow: 1,\n      // Control to display 10 columns in one row, a page button will be displayed when the column width is insufficient\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Setting orientation is ineffective?\n\n`orientation` mainly controls the direction of the layout, and the specific display of **multiple columns in one row** or **multiple rows in one column** is mainly controlled by `gridRow` and `gridCol`. For example, if you want it to look like a vertical legend item, you can configure it like this:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // Control to display 1 column in one row\n      gridCol:1,\n      // Control to display up to 20 rows\n      gridRow: 20,\n    },\n  ],\n```\n\nThis way, it becomes a legend with only one column, conforming to the visual vertical arrangement.\n\n### 2. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// Update legend position\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Legend.zh.md":"---\ntitle: 图例 Legend\norder: 11\n---\n\n## 概述\n\n图例（Legend）插件用于展示图中元素的分类信息，支持节点、边、组合的分类信息展示。通过图例，用户可以快速感知到图中相关元素的分类信息，也可以通过点击对应图例项来快速定位到元素，提高用户的浏览效率。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 通过图例快速对元素进行分类\n- 通过图例快速高亮定位到对应元素\n\n## 基本用法\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性              | 描述                                                                                                  | 类型                                                                                        | 默认值       | 必选 |\n| ----------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type              | 插件类型                                                                                              | string                                                                                      | `legend`     | ✓    |\n| key               | 插件唯一标识符，用于后续更新                                                                          | string                                                                                      | -            |      |\n| trigger           | 图例项触发对应项高亮的方式：<br/>- `hover`：鼠标移入图例项时触发 <br/>- `click`：鼠标点击图例项时触发 | `hover` \\| `click`                                                                          | `hover`      |      |\n| position          | 图例在画布中的相对位置，[可选值](#cardinalplacement)                                                  | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`     |      |\n| container         | 图例挂载的容器，无则挂载到 Graph 所在容器                                                             | HTMLElement \\| string                                                                       | -            |      |\n| className         | 图例画布类名，传入外置容器时不生效                                                                    | string                                                                                      | -            |      |\n| containerStyle    | 图例的容器样式，传入外置容器时不生效                                                                  | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| nodeField         | 节点分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| edgeField         | 边分类标识                                                                                            | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| comboField        | 组合分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| orientation       | 图例项的布局方向：<br/>- `horizontal`：水平方向 <br/>- `vertical`：垂直方向                           | `horizontal` \\| `vertical`                                                                  | 'horizontal' |      |\n| layout            | 布局方式：<br/>- `flex`：弹性布局 <br/>- `grid`：网格布局                                             | `flex` \\| `grid`                                                                            | `flex`       |      |\n| showTitle         | 是否显示标题                                                                                          | boolean                                                                                     | false        |\n| titleText         | 标题内容                                                                                              | string                                                                                      | \"\"           |\n| x                 | 图例在画布中的相对的横向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| y                 | 图例在画布中的相对的纵向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| width             | 图例的宽度                                                                                            | number                                                                                      | 240          |      |\n| height            | 图例的高度                                                                                            | number                                                                                      | 160          |      |\n| itemSpacing       | 图例项的文本和对应标记之间的间距                                                                      | number                                                                                      | 4            |      |\n| rowPadding        | 图例中每行之间的间距                                                                                  | number                                                                                      | 10           |      |\n| colPadding        | 图例中每列之间的间距                                                                                  | number                                                                                      | 10           |      |\n| itemMarkerSize    | 图例项标记的大小                                                                                      | number                                                                                      | 16           |      |\n| itemLabelFontSize | 图例项文本的字体大小                                                                                  | number                                                                                      | 16           |      |\n| gridCol           | 图例项在宽度允许情况下的最大列数                                                                      | number                                                                                      | -            |      |\n| gridRow           | 图例项在高度允许情况下的最大行数                                                                      | number                                                                                      | -            |      |\n\n### CardinalPlacement\n\n`position` 属性支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n## 代码示例\n\n### 基础图例\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n### 自定义图例位置\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // 可以通过 position 快捷的来指定位置\n      // position: \"top-left\",\n      // 也可以通过x,y来更加灵活的控制图例的位置\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### 自定义图例项布局\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // 控制只显示一行\n      gridRow: 1,\n      // 控制一行显示10列，当列宽不足时会显示翻页按钮\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 设置了 orientation 无效？\n\n`orientation`主要控制布局的方向，具体展示**一行多列**还是**一列多行**，主要通过 `gridRow` 以及`gridCol`来控制，例如想要看起来像是竖向的图例项，则可以通过这样配置:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // 控制一行显示1列\n      gridCol:1,\n      // 控制显示最多20行\n      gridRow: 20,\n    },\n  ],\n```\n\n这样就变成了只有一列的图例，符合视觉上的竖向排列。\n\n### 2. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// 更新图例位置\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Minimap.en.md":"---\ntitle: Minimap\norder: 12\n---\n\n## Overview\n\nThe main function of the Minimap is to provide users with an overall layout of the current graph content in the form of a thumbnail, allowing quick positioning of graph operation locations.\n\n**⚠️ Note**, The Minimap plugin is currently incompatible with React Node rendering mechanism. When using Minimap functionality, it is recommended to implement node rendering through [built-in nodes](/en/manual/element/node/overview) or [custom nodes](/en/manual/element/node/custom-node).\n\n## Usage Scenarios\n\nThe Minimap plugin is mainly applicable to the following scenarios:\n\n- Providing a global view for quick area positioning\n- Navigation and interaction assistance, allowing quick positioning to the target location through the minimap\n\n## Basic Usage\n\nBelow is a simple example of initializing the Minimap plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                             | Type                                                                                                                                                                                                   | Default Value  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- |\n| type           | Plugin type                                                                                                             | string                                                                                                                                                                                                 | `minimap`      | ✓        |\n| key            | Unique identifier for the plugin, used for subsequent updates                                                           | string                                                                                                                                                                                                 | -              |          |\n| className      | Class name of the thumbnail canvas, not effective when an external container is passed                                  | string                                                                                                                                                                                                 |                |          |\n| container      | Container to which the thumbnail is mounted, if not provided, it is mounted to the container where the Graph is located | HTMLElement \\| string                                                                                                                                                                                  |                |          |\n| containerStyle | Style of the thumbnail container, not effective when an external container is passed                                    | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| delay          | Delay update time (milliseconds) for performance optimization                                                           | number                                                                                                                                                                                                 | 128            |          |\n| filter         | Filter for filtering out elements that do not need to be displayed                                                      | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |          |\n| maskStyle      | Style of the mask                                                                                                       | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| padding        | Padding                                                                                                                 | number \\| number[]                                                                                                                                                                                     | 10             |          |\n| position       | Position of the thumbnail relative to the canvas                                                                        | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |          |\n| renderer       | Renderer, default is Canvas renderer                                                                                    | IRenderer                                                                                                                                                                                              |                |          |\n| shape          | Method for generating element thumbnails                                                                                | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |          |\n| size           | Width and height                                                                                                        | [number, number]                                                                                                                                                                                       | [240, 160]     |          |\n\n### containerStyle\n\nSet the style of the thumbnail container, not effective when an external container is passed. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value    | Required |\n| ------------ | -------------------------- | ------ | ---------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd` | ✓        |\n| background   | Container background color | string | `#fff`           | ✓        |\n| borderRadius | Container border radius    | string | -                |          |\n| boxShadow    | Container shadow effect    | string | -                |          |\n| padding      | Container padding          | string | -                |          |\n| margin       | Container margin           | string | -                |          |\n| opacity      | Opacity                    | string | -                |          |\n\n### maskStyle\n\nSpecify the style of the mask. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value        | Required |\n| ------------ | -------------------------- | ------ | -------------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd`     | ✓        |\n| background   | Container background color | string | `rgba(0, 0, 0, 0.1)` | ✓        |\n| borderRadius | Container border radius    | string | -                    | -        |\n| boxShadow    | Container shadow effect    | string | -                    | -        |\n| padding      | Container padding          | string | -                    | -        |\n| margin       | Container margin           | string | -                    | -        |\n| opacity      | Opacity                    | string | -                    | -        |\n\n### position\n\nPosition of the thumbnail relative to the canvas, the thumbnail position configuration supports array form and preset value form.\n\n- Array form [number, number] represents relative position, with a value range of 0~1. For example: [0, 0] represents the top left corner of the canvas, [1, 1] represents the bottom right corner of the canvas.\n- Preset value form is used to set the fixed position of the thumbnail on the canvas, optional values are: `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // Modify the position of the minimap here\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\nSet the width and height of the minimap, default value is [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // Set the width and height of the minimap\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Minimap.zh.md":"---\ntitle: 小地图 Minimap\norder: 12\n---\n\n## 概述\n\nMinimap（小地图）的主要作用是为用户提供以缩略图形式展示当前图内容的整体布局，可以快速定位图操作位置。\n\n**⚠️ 需要注意**，Minimap 插件当前不兼容 React Node 渲染机制，在需要使用 Minimap 功能的场景中，建议通过 [内置节点](/manual/element/node/overview) 或者[自定义节点](/manual/element/node/custom-node) 实现节点渲染。\n\n## 使用场景\n\nMinimap（小地图）插件主要适用于以下场景：\n\n- 提供全局视野，快速定位区域\n- 导航与交互辅助，通过操作小地图可以快速定位到目标位置\n\n## 基本用法\n\n以下是一个简单的 Minimap 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                        | 类型                                                                                                                                                                                                   | 默认值         | 必选 |\n| -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ---- |\n| type           | 插件类型                                    | string                                                                                                                                                                                                 | `minimap`      | ✓    |\n| key            | 插件唯一标识符，用于后续更新                | string                                                                                                                                                                                                 | -              |      |\n| className      | 缩略图画布类名，传入外置容器时不生效        | string                                                                                                                                                                                                 |                |      |\n| container      | 缩略图挂载的容器，无则挂载到 Graph 所在容器 | HTMLElement \\| string                                                                                                                                                                                  |                |      |\n| containerStyle | 缩略图的容器样式，传入外置容器时不生效      | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| delay          | 延迟更新时间(毫秒)，用于性能优化            | number                                                                                                                                                                                                 | 128            |      |\n| filter         | 过滤器，用于过滤不必显示的元素              | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |      |\n| maskStyle      | 遮罩的样式                                  | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| padding        | 内边距                                      | number \\| number[]                                                                                                                                                                                     | 10             |      |\n| position       | 缩略图相对于画布的位置                      | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |      |\n| renderer       | 渲染器，默认使用 Canvas 渲染器              | IRenderer                                                                                                                                                                                              |                |      |\n| shape          | 元素缩略图形的生成方法                      | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |      |\n| size           | 宽度和高度                                  | [number, number]                                                                                                                                                                                       | [240, 160]     |      |\n\n### containerStyle\n\n设置缩略图的容器样式，传入外置容器时不生效。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值           | 必选 |\n| ------------ | ------------ | ------ | ---------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd` | ✓    |\n| background   | 容器背景颜色 | string | `#fff`           | ✓    |\n| borderRadius | 容器圆角大小 | string | -                |      |\n| boxShadow    | 容器阴影效果 | string | -                |      |\n| padding      | 容器内边距   | string | -                |      |\n| margin       | 容器外边距   | string | -                |      |\n| opacity      | 透明度       | string | -                |      |\n\n### maskStyle\n\n指定遮罩的样式。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值               | 必选 |\n| ------------ | ------------ | ------ | -------------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd`     | ✓    |\n| background   | 容器背景颜色 | string | `rgba(0, 0, 0, 0.1)` | ✓    |\n| borderRadius | 容器圆角大小 | string | -                    | -    |\n| boxShadow    | 容器阴影效果 | string | -                    | -    |\n| padding      | 容器内边距   | string | -                    | -    |\n| margin       | 容器外边距   | string | -                    | -    |\n| opacity      | 透明度       | string | -                    | -    |\n\n### position\n\n缩略图相对于画布的位置，缩略图位置配置支持数组形式和预设值形式。\n\n- 数组形式 [number, number] 表示相对位置，取值范围为 0~1。举例：[0, 0] 代表画布左上角，[1, 1] 代表画布右下角。\n- 预设值形式用于设定缩略图所在画布固定方位，可选值有：`left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // 这里进行修改minimap所在位置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\n设置小地图的宽度和高度，默认值为 [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // minimap的宽度和高度的设置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Snapline.en.md":"---\ntitle: Snapline\norder: 13\n---\n\n## Overview\n\nThe Snapline plugin provides intelligent alignment guidelines for the canvas, automatically displaying guide lines when moving nodes and supporting automatic snapping. It helps users achieve precise alignment and is an important tool for improving efficiency and accuracy in graphic editing.\n\n## Use Cases\n\nThe Snapline plugin is mainly suitable for the following scenarios:\n\n- When manually adjusting node positions and precise alignment with other nodes is needed\n- When dragging multiple nodes while maintaining their alignment relationships\n- When creating standardized graphic layouts to ensure consistency in node spacing and positioning\n- When improving node layout efficiency through automatic snapping functionality\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // Specify unique identifier\n      tolerance: 5, // Alignment snap threshold\n      offset: 20, // Guide line extension distance\n      autoSnap: true, // Enable automatic snapping\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## Options\n\n| Property            | Description                                                                                                                                                                                            | Type                                      | Default                 | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ----------------------- | -------- |\n| type                | Plugin type                                                                                                                                                                                            | string                                    | `'snapline'`            | ✓        |\n| key                 | Plugin unique identifier                                                                                                                                                                               | string                                    | -                       |          |\n| tolerance           | The alignment accuracy, that is, when the distance between the moved node and the target position is less than tolerance, the alignment line is displayed                                              | number                                    | 5                       |          |\n| offset              | The extension distance of the snapline                                                                                                                                                                 | number                                    | 20                      |          |\n| autoSnap            | Whether to enable automatic snapping                                                                                                                                                                   | boolean                                   | true                    |          |\n| shape               | Specifies which shape on the element to use as the reference shape:<br/>- `'key'`: uses the key shape of the element as the reference shape<br/>- `Function`: receives the element and returns a shape | string \\| ((node: Node) => DisplayObject) | `'key'`                 |          |\n| verticalLineStyle   | Vertical snapline style                                                                                                                                                                                | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| horizontalLineStyle | Horizontal snapline style                                                                                                                                                                              | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| filter              | Filter nodes that do not need to participate in alignment                                                                                                                                              | (node: Node) => boolean                   | `() => true`            |          |\n\n### shape\n\nThe `shape` property specifies the reference shape for elements and supports the following configurations:\n\n```js\n// Use the key shape as reference\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// Use custom function to return reference shape\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### Snapline Style Configuration\n\n| Property       | Description             | Type                                     | Default     |\n| -------------- | ----------------------- | ---------------------------------------- | ----------- |\n| stroke         | Line color              | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | Overall opacity         | number \\| string                         | 1           |\n| strokeOpacity  | Stroke opacity          | number \\| string                         | 1           |\n| lineWidth      | Line width              | number \\| string                         | 1           |\n| lineCap        | Line end style          | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | Line join style         | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | Dash line configuration | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | Dash line offset        | number                                   | 0           |\n| shadowBlur     | Shadow blur             | number                                   | 0           |\n| shadowColor    | Shadow color            | string                                   | -           |\n| shadowOffsetX  | Shadow X offset         | number                                   | 0           |\n| shadowOffsetY  | Shadow Y offset         | number                                   | 0           |\n| cursor         | Mouse cursor style      | string                                   | `'default'` |\n| zIndex         | Rendering level         | number                                   | 0           |\n\nExample configuration:\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## Code Examples\n\n### Basic Snapline\n\nThe simplest usage:\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### Custom Configuration\n\nYou can customize the snapline behavior according to your needs:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // Larger snap range\n      offset: 30, // Longer extension lines\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // Filter nodes by id, exclude from alignment\n    },\n  ],\n});\n```\n\n## Live Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Snapline.zh.md":"---\ntitle: 对齐线 Snapline\norder: 13\n---\n\n## 概述\n\n对齐线插件为画布提供智能对齐参考线，在移动节点时自动显示辅助线并支持自动吸附，帮助用户实现精确对齐，是图形编辑中提升效率和精确度的重要工具。\n\n## 使用场景\n\n对齐线插件主要适用于以下场景：\n\n- 手动调整节点位置时,需要与其他节点精确对齐\n- 拖拽移动多个节点时,保持它们之间的对齐关系\n- 制作规范的图形布局时,确保节点间距和位置的一致性\n- 通过自动吸附功能提高节点排版效率\n\n## 基本用法\n\n以下是一个简单的 Snapline 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // 指定唯一标识符\n      tolerance: 5, // 对齐吸附阈值\n      offset: 20, // 对齐线延伸距离\n      autoSnap: true, // 启用自动吸附\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## 配置项\n\n| 属性                | 描述                                                                                                                    | 类型                                                                                                                            | 默认值                  | 必选 |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type                | 插件类型                                                                                                                | string                                                                                                                          | `'snapline'`            | ✓    |\n| key                 | 插件唯一标识符                                                                                                          | string                                                                                                                          | -                       |      |\n| tolerance           | 对齐精度，即触发对齐的距离阈值                                                                                          | number                                                                                                                          | 5                       |      |\n| offset              | 对齐线头尾的延伸距离                                                                                                    | number                                                                                                                          | 20                      |      |\n| autoSnap            | 是否启用自动吸附                                                                                                        | boolean                                                                                                                         | true                    |      |\n| shape               | 指定元素的参照图形：<br/>- `'key'`: 使用元素的主图形作为参照图形<br/>- `Function`: 传入函数时接收元素对象，返回一个图形 | string \\| ((node: Node) => DisplayObject)                                                                                       | `'key'`                 |      |\n| verticalLineStyle   | 垂直对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| horizontalLineStyle | 水平对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| filter              | 过滤不需要参与对齐的节点                                                                                                | (node: Node) => boolean                                                                                                         | `() => true`            |      |\n\n### shape\n\n`shape` 属性用于指定元素的参照图形，支持以下配置方式：\n\n```js\n// 使用主图形作为参照\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// 使用自定义函数返回参照图形\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### 对齐线样式配置\n\n| 配置项         | 说明            | 类型                                     | 默认值      |\n| -------------- | --------------- | ---------------------------------------- | ----------- |\n| stroke         | 线条颜色        | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | 整体透明度      | number \\| string                         | 1           |\n| strokeOpacity  | 描边透明度      | number \\| string                         | 1           |\n| lineWidth      | 线宽度          | number \\| string                         | 1           |\n| lineCap        | 线段端点样式    | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | 线段连接处样式  | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | 虚线配置        | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | 虚线偏移量      | number                                   | 0           |\n| shadowBlur     | 阴影模糊程度    | number                                   | 0           |\n| shadowColor    | 阴影颜色        | string                                   | -           |\n| shadowOffsetX  | 阴影 X 方向偏移 | number                                   | 0           |\n| shadowOffsetY  | 阴影 Y 方向偏移 | number                                   | 0           |\n| cursor         | 鼠标样式        | string                                   | `'default'` |\n| zIndex         | 渲染层级        | number                                   | 0           |\n\n示例配置\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## 代码示例\n\n### 基础对齐线\n\n最简单的使用方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### 自定义配置\n\n可以根据需要自定义对齐线的行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // 更大的吸附范围\n      offset: 30, // 更长的延伸线\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // 根据id过滤节点，不参与对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Timebar.en.md":"---\ntitle: Timebar\norder: 14\n---\n\n## Overview\n\nThe Timebar plugin is an important tool for exploring time-series data. It can display the time distribution of data in the form of a timeline or trend chart, and supports interactions such as time interval filtering and dynamic playback, helping users better understand the changes in data over time.\n\n## Use Cases\n\n- Need to display and analyze the time distribution of time-series data\n- Need to filter and explore graph data through the time dimension\n- Need to dynamically display the process of data changing over time\n\n## Basic Usage\n\nBelow is a simple example of initializing the Timebar plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // Time data\n      width: 450, // Timebar width\n      height: 60, // Timebar height\n      position: 'bottom', // Position\n      loop: false, // Whether to loop playback\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                              | Type                                               | Default Value | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type           | Plugin type                                                                                                                                                                              | string                                             | `timebar`     | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                        | string                                             | -             |          |\n| className      | Additional class name for the toolbar DOM                                                                                                                                                | string                                             | `g6-timebar`  |          |\n| x              | X position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| y              | Y position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| width          | Timebar width                                                                                                                                                                            | number                                             | 450           |          |\n| height         | Timebar height                                                                                                                                                                           | number                                             | 60            |          |\n| position       | Timebar position                                                                                                                                                                         | `bottom` \\| `top`                                  | `bottom`      |          |\n| padding        | Padding                                                                                                                                                                                  | number \\| number[]                                 | 10            |          |\n| data           | Time data                                                                                                                                                                                | number[] \\| { time: number; value: number }[]      | -             | ✓        |\n| timebarType    | Timebar display type                                                                                                                                                                     | `time` \\| `chart`                                  | `time`        |          |\n| elementTypes   | Filter element types                                                                                                                                                                     | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]      |          |\n| mode           | Control element filtering method, supports the following two configurations: <br/>- `modify`: filter by modifying graph data <br/>- `visibility`: filter by modifying element visibility | `modify` \\| `visibility`                           | `modify`      |          |\n| values         | Current time value                                                                                                                                                                       | number \\| [number, number] \\| Date \\| [Date, Date] | -             |          |\n| loop           | Whether to loop playback                                                                                                                                                                 | boolean                                            | false         |          |\n| getTime        | Method to get element time                                                                                                                                                               | (datum: ElementDatum) => number                    | -             |          |\n| labelFormatter | Custom time formatting in chart mode                                                                                                                                                     | (time: number \\| Date) => string                   | -             |          |\n| onChange       | Callback when the time interval changes                                                                                                                                                  | (values: number \\| [number, number]) => void       | -             |          |\n| onReset        | Callback when reset                                                                                                                                                                      | () => void                                         | -             |          |\n| onSpeedChange  | Callback when playback speed changes                                                                                                                                                     | (speed: number) => void                            | -             |          |\n| onPlay         | Callback when playback starts                                                                                                                                                            | () => void                                         | -             |          |\n| onPause        | Callback when paused                                                                                                                                                                     | () => void                                         | -             |          |\n| onBackward     | Callback when moving backward                                                                                                                                                            | () => void                                         | -             |          |\n| onForward      | Callback when moving forward                                                                                                                                                             | () => void                                         | -             |          |\n\n### timebarType\n\nThe `timebarType` property is used to control the display type of the timebar, supporting the following two configurations:\n\n- `time`: Displayed as a timeline, refer to [Time Mode Example](/examples/plugin/timebar/#timer)\n- `chart`: Displayed as a trend chart, at this time the `data` configuration item under `timebar` needs to pass an additional `value` field as chart data, refer to [Chart Mode Example](/examples/plugin/timebar/#chart)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        // By default, elementTypes=['node'], so nodes need to set data.timestamp to display sequentially according to the timeline\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // Scenario 1: By default, elementTypes = ['node']\n        // - Edges do not need to set data.timestamp, the display/hide of edges depends entirely on whether the two connected nodes are visible\n\n        // Scenario 2: If elementTypes includes 'edge', for example, elementTypes = ['node', 'edge']\n        // - At this time, edges must set data.timestamp, and the display of edges is controlled by it\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\n`width`, `height`, `padding`, `className` can customize the display effect of the timebar, but note that `className` only acts on the outer DOM container and cannot affect the internal Canvas rendering content of the timebar (timeline, chart, play button, etc.).\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // Note: Since the content is Canvas rendered, CSS styles cannot affect the internal content of the timebar\n      width: 400, // Set timebar width\n      height: 80, // Set timebar height\n      padding: [20, 20, 10, 20], // Set padding [top, right, bottom, left]\n      position: 'bottom', // Keep position at the bottom\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\nCSS can only set the style of the timebar container:\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## Real Cases\n\n- [Time Mode](/examples/plugin/timebar/#timer)\n- [Chart Mode](/examples/plugin/timebar/#chart)\n","packages/site/docs/manual/plugin/Timebar.zh.md":"---\ntitle: 时间条 Timebar\norder: 14\n---\n\n## 概述\n\n时间条插件是一个用于时序数据探索的重要工具，它能够通过时间轴或趋势图的形式展示数据的时间分布，并支持时间区间筛选、动态播放等交互方式，帮助用户更好地理解数据随时间的变化。\n\n## 使用场景\n\n- 需要展示和分析时序数据的时间分布\n- 需要通过时间维度筛选和探索图数据\n- 需要动态展示数据随时间变化的过程\n\n## 基本用法\n\n以下是一个简单的 Timebar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // 时间数据\n      width: 450, // 时间条宽度\n      height: 60, // 时间条高度\n      position: 'bottom', // 位置\n      loop: false, // 是否循环播放\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                           | 类型                                               | 默认值       | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------------ | ---- |\n| type           | 插件类型                                                                                                                       | string                                             | `timebar`    | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                               | string                                             | -            |      |\n| className      | 给工具栏的 DOM 追加的类名                                                                                                      | string                                             | `g6-timebar` |      |\n| x              | X 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| y              | Y 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| width          | 时间条宽度                                                                                                                     | number                                             | 450          |      |\n| height         | 时间条高度                                                                                                                     | number                                             | 60           |      |\n| position       | 时间条位置                                                                                                                     | `bottom` \\| `top`                                  | `bottom`     |      |\n| padding        | 边距                                                                                                                           | number \\| number[]                                 | 10           |      |\n| data           | 时间数据                                                                                                                       | number[] \\| { time: number; value: number }[]      | -            | ✓    |\n| timebarType    | 时间条展示类型                                                                                                                 | `time` \\| `chart`                                  | `time`       |      |\n| elementTypes   | 筛选元素类型                                                                                                                   | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]     |      |\n| mode           | 控制元素的筛选方式，支持以下两种配置： <br/>- `modify`：通过修改图数据进行筛选 <br/>- `visibility`：通过修改元素可见性进行筛选 | `modify` \\| `visibility`                           | `modify`     |      |\n| values         | 当前时间值                                                                                                                     | number \\| [number, number] \\| Date \\| [Date, Date] | -            |      |\n| loop           | 是否循环播放                                                                                                                   | boolean                                            | false        |      |\n| getTime        | 获取元素时间的方法                                                                                                             | (datum: ElementDatum) => number                    | -            |      |\n| labelFormatter | 图表模式下自定义时间格式化                                                                                                     | (time: number \\| Date) => string                   | -            |      |\n| onChange       | 时间区间变化时的回调                                                                                                           | (values: number \\| [number, number]) => void       | -            |      |\n| onReset        | 重置时的回调                                                                                                                   | () => void                                         | -            |      |\n| onSpeedChange  | 播放速度变化时的回调                                                                                                           | (speed: number) => void                            | -            |      |\n| onPlay         | 开始播放时的回调                                                                                                               | () => void                                         | -            |      |\n| onPause        | 暂停时的回调                                                                                                                   | () => void                                         | -            |      |\n| onBackward     | 后退时的回调                                                                                                                   | () => void                                         | -            |      |\n| onForward      | 前进时的回调                                                                                                                   | () => void                                         | -            |      |\n\n### timebarType\n\n`timebarType` 属性用于控制时间条的展示类型，支持以下两种配置：\n\n- `time`：显示为时间轴形式，参考 [时间模式示例](/examples/plugin/timebar/#timer)\n- `chart`：显示为趋势图形式，此时`timebar`下的`data`配置项，每个数组项需要额外传入 `value` 字段作为图表数据，参考 [图表模式示例](/examples/plugin/timebar/#chart)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        // 默认情况下 elementTypes=['node']，所以节点需要设置 data.timestamp，才能按照时间轴内的时间依次展示\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // 场景一：默认情况 elementTypes = ['node']\n        // - 边不需要设置 data.timestamp，边的显示/隐藏完全取决于其连接的两个节点是否可见\n\n        // 场景二：如果elementTypes包含了'edge'，比如 elementTypes = ['node', 'edge']\n        // - 此时必须为边设置 data.timestamp，边的显示受其控制\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n`width`、`height`、`padding`、`className` 可自定义时间条的展示效果，但需要注意 `className` 仅作用于外层 DOM 容器，无法影响时间条内部的 Canvas 渲染内容（时间轴、图表、播放按钮等）。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // 注意：由于内容是 Canvas 渲染，CSS 样式无法影响到时间条的内部内容\n      width: 400, // 设置时间条宽度\n      height: 80, // 设置时间条高度\n      padding: [20, 20, 10, 20], // 设置内边距 [上, 右, 下, 左]\n      position: 'bottom', // 位置保持在底部\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\n通过 CSS 只能设置时间条容器的样式：\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\n效果如下：\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## 实际案例\n\n- [时间模式](/examples/plugin/timebar/#timer)\n- [图表模式](/examples/plugin/timebar/#chart)\n","packages/site/docs/manual/plugin/Title.en.md":"---\ntitle: Title\norder: 15\n---\n\n## Overview\n\nTitle indicates the name of the image and conveys the brief content of the image.\n\n## Basic Usage\n\nThe following is a simple example of initializing the Title plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: 'This is a title',\n      subTitle: 'This is a subtitle',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                   | Type                          | Default      | Required |\n| --------- | ------------------------------------------------------------- | ----------------------------- | ------------ | -------- |\n| type      | Plugin type                                                   | string                        | `title`      | ✓        |\n| key       | Unique identifier for the plugin, used for subsequent updates | string                        | -            |          |\n| title     | title content [style config](#title)                          | `TitleStyle`                  | -            | ✓        |\n| subtitle  | subtitle content [style config](#subtitle)                    | `SubTitleStyle`               | -            |          |\n| spacing   | Vertical spacing between main title and subtitle              | number                        | 8            |          |\n| className | Class name of the title canvas                                | string                        | -            |          |\n| align     | Graph title alignment                                         | `left` \\| `center` \\| `right` | `left`       |          |\n| size      | Height of the title plugin                                    | number                        | 44           |          |\n| padding   | Padding                                                       | number \\| number[]            | [16,24,0,24] |          |\n\n### size\n\n<description> _number_ **optional** </description>\n\nUsed to configure the space height of the title plugin. Default is `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\nUsed to configure the horizontal alignment of the title plugin. Default is `left`. You can choose `left`, `center`, or `right`, representing left-aligned, center-aligned, and right-aligned respectively.\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: 'Ciallo' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: 'This is a title This is a title',\n        subtitle: 'This is a sub-',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\nUsed to configure the spacing between the chart main title and subtitle. Default is `8`. Appropriate spacing can make the chart look more harmonious overall.\n\n### title\n\nThe title, specifically the main title, can be customized with the following configurations for various title styles.\n\n| Attr               | Desc                                               | Type       | Default               |\n| ------------------ | -------------------------------------------------- | ---------- | --------------------- |\n| title              | Title text content                                 | `string`   | -                     |\n| titleFontSize      | Title text size                                    | `number`   | 16                    |\n| titleFontFamily    | Title text font                                    | `string`   | system-ui, sans-serif |\n| titleFontWeight    | Title font weight                                  | `number`   | bold                  |\n| titleLineHeight    | Title text line height                             | `number`   | 16                    |\n| titleTextAlign     | Horizontal alignment of content in title text line | `string`   | left                  |\n| titleTextBaseline  | Vertical baseline of title text                    | `string`   | top                   |\n| titleFill          | Fill color of title text                           | `string`   | #1D2129               |\n| titleFillOpacity   | Fill transparency of title text                    | `number`   | 0.9                   |\n| titleStroke        | Stroke color of title text                         | `string`   | transparent           |\n| titleStrokeOpacity | Stroke transparency of title text                  | `number`   | 1                     |\n| titleLineWidth     | Stroke width of title text                         | `number`   | 0                     |\n| titleLineDash      | Dash style of title text                           | `number[]` | []                    |\n| titleOpacity       | Overall transparency of title text                 | `number`   | 1                     |\n| titleShadowColor   | Shadow color of title text                         | `string`   | transparent           |\n| titleShadowBlur    | Gaussian blur coefficient of title text shadow     | `number`   | 0                     |\n| titleShadowOffsetX | Horizontal offset of title text shadow             | `number`   | 0                     |\n| titleShadowOffsetY | Vertical offset of title text shadow               | `number`   | 0                     |\n| titleCursor        | Mouse style of title text                          | `string`   | default               |\n| titleDx            | Horizontal offset of title text                    | `number`   | 0                     |\n| titleDy            | Vertical offset of title text                      | `number`   | 0                     |\n\n### subtitle\n\nThe subtitle, which can be customized with the following configurations for various subtitle styles.\n\n| Attr                  | Desc                                            | Type       | Default               |\n| --------------------- | ----------------------------------------------- | ---------- | --------------------- |\n| subtitle              | Subtitle text content                           | `string`   | -                     |\n| subtitleFontSize      | Subtitle text size                              | `number`   | 12                    |\n| subtitleFontFamily    | Subtitle text font                              | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | Subtitle font weight                            | `number`   | normal                |\n| subtitleLineHeight    | Subtitle text line height                       | `number`   | 12                    |\n| subtitleTextAlign     | Subtitle text line content horizontal alignment | `string`   | left                  |\n| subtitleTextBaseline  | Subtitle text vertical baseline                 | `string`   | top                   |\n| subtitleFill          | Subtitle text fill color                        | `string`   | #1D2129               |\n| subtitleFillOpacity   | Subtitle text fill transparency                 | `number`   | 0.65                  |\n| subtitleStroke        | Subtitle text stroke color                      | `string`   | transparent           |\n| subtitleStrokeOpacity | Subtitle text stroke transparency               | `number`   | 1                     |\n| subtitleLineWidth     | Subtitle text stroke width                      | `number`   | 0                     |\n| subtitleLineDash      | Subtitle text dashed line style                 | `number[]` | []                    |\n| subtitleOpacity       | Subtitle text overall transparency              | `number`   | 1                     |\n| subtitleShadowColor   | Subtitle text shadow color                      | `string`   | transparent           |\n| subtitleShadowBlur    | Subtitle text shadow Gaussian blur coefficient  | `number`   | 0                     |\n| subtitleShadowOffsetX | Subtitle text shadow horizontal offset          | `number`   | 0                     |\n| subtitleShadowOffsetY | Subtitle text shadow vertical offset            | `number`   | 0                     |\n| subtitleCursor        | Subtitle text mouse style                       | `string`   | default               |\n| subtitleDx            | Subtitle text horizontal offset                 | `number`   | 0                     |\n| subtitleDy            | Subtitle text vertical offset                   | `number`   | 0                     |\n\n## Try it\n\nFeel free to modify this example and try different configurations\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // Alignment of title\n      spacing: 4, // Spacing between main title and subtitle\n      size: 60, // Height of title, default is 44\n\n      // title\n      title: 'This is a title This is a title', // Title text\n      titleFontSize: 28, // Main title font size\n      titleFontFamily: 'sans-serif', // Main title font\n      titleFontWeight: 600, // Main title font weight\n      titleFill: '#fff', // Main title text color\n      titleFillOpacity: 1, // Main title text transparency\n      titleStroke: '#000', // Main title text stroke color\n      titleLineWidth: 2, // Main title text stroke line width\n      titleStrokeOpacity: 1, // Main title text stroke transparency\n\n      // subtitle\n      subtitle: 'This is a sub-', // Subtitle text\n      subtitleFontSize: 16, // Subtitle font size\n      subtitleFontFamily: 'Arial', // Subtitle font\n      subtitleFontWeight: 300, // Subtitle font weight\n      subtitleFill: '#2989FF', // Subtitle text color\n      subtitleFillOpacity: 1, // Subtitle text transparency\n      subtitleStroke: '#000', // Subtitle text stroke color\n      subtitleLineWidth: 1, // Subtitle text stroke line width\n      subtitleStrokeOpacity: 0.5, // Subtitle text stroke transparency\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: 'Ciallo' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Title.zh.md":"---\ntitle: 标题 Title\norder: 15\n---\n\n## 概述\n\nTitle（标题）表明了这张图的名称，传达图的简略内容\n\n## 基本用法\n\n以下是一个简单的 Title 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: '这是一个标题',\n      subTitle: '这是一个副标题',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                             | 类型                          | 默认值       | 必选 |\n| --------- | -------------------------------- | ----------------------------- | ------------ | ---- |\n| type      | 插件类型                         | string                        | `title`      | ✓    |\n| key       | 插件唯一标识符，用于后续更新     | string                        | -            |      |\n| title     | 标题内容 [样式配置](#title)      | `TitleStyle`                  | -            | ✓    |\n| subtitle  | 副标题内容 [样式配置](#subtitle) | `SubTitleStyle`               | -            |      |\n| spacing   | 主标题、副标题之间的上下间距     | number                        | 8            |      |\n| className | 标题画布类名                     | string                        | -            |      |\n| align     | 标题相对于画布的位置             | `left` \\| `center` \\| `right` | `left`       |      |\n| size      | 整个标题插件的高度               | number                        | 44           |      |\n| padding   | 内边距                           | number \\| number[]            | [16,24,0,24] |      |\n\n### size\n\n<description> _number_ **optional** </description>\n\n用于配置标题的空间高度大小，默认为 `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\n用于配置标题的的左右对齐方式，默认为 `left`，可以选择使用 `left`，`center`，`right`，分别代表着居左对齐、居中对齐、居右对齐。\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: '你好' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: '这是一个标题这是一个标题',\n        subtitle: '这是一个副标',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\n用于配置主标题和副标题之间的间距，默认为 `8`，合适的间距，可以让看起来整体更协调。\n\n### title\n\n的标题，具体来说是主标题，可以用以下的配置来定制标题的各种样式。\n\n| 属性               | 描述                           | 类型       | 默认值                |\n| ------------------ | ------------------------------ | ---------- | --------------------- |\n| title              | 标题文字内容                   | `string`   | -                     |\n| titleFontSize      | 标题文字大小                   | `number`   | 16                    |\n| titleFontFamily    | 标题文字字体                   | `string`   | system-ui, sans-serif |\n| titleFontWeight    | 标题字体粗细                   | `number`   | bold                  |\n| titleLineHeight    | 标题文字的行高                 | `number`   | 16                    |\n| titleTextAlign     | 标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| titleTextBaseline  | 标题文字垂直方向的基线         | `string`   | top                   |\n| titleFill          | 标题文字的填充色               | `string`   | #1D2129               |\n| titleFillOpacity   | 标题文字的填充透明度           | `number`   | 0.9                   |\n| titleStroke        | 标题文字的描边颜色             | `string`   | transparent           |\n| titleStrokeOpacity | 标题文字的描边透明度           | `number`   | 1                     |\n| titleLineWidth     | 标题文字描边宽度               | `number`   | 0                     |\n| titleLineDash      | 标题文字虚线样式               | `number[]` | []                    |\n| titleOpacity       | 标题文字整体透明度             | `number`   | 1                     |\n| titleShadowColor   | 标题文字阴影颜色               | `string`   | transparent           |\n| titleShadowBlur    | 标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| titleShadowOffsetX | 标题文字阴影水平偏移量         | `number`   | 0                     |\n| titleShadowOffsetY | 标题文字阴影垂直偏移量         | `number`   | 0                     |\n| titleCursor        | 标题文字鼠标样式               | `string`   | default               |\n| titleDx            | 标题文字在水平方向的偏移量     | `number`   | 0                     |\n| titleDy            | 标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n### subtitle\n\n的副标题，可以用以下的配置来定制副标题的各种样式。\n\n| 属性                  | 描述                             | 类型       | 默认值                |\n| --------------------- | -------------------------------- | ---------- | --------------------- |\n| subtitle              | 副标题文字内容                   | `string`   | -                     |\n| subtitleFontSize      | 副标题文字大小                   | `number`   | 12                    |\n| subtitleFontFamily    | 副标题文字字体                   | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | 副标题字体粗细                   | `number`   | normal                |\n| subtitleLineHeight    | 副标题文字的行高                 | `number`   | 12                    |\n| subtitleTextAlign     | 副标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| subtitleTextBaseline  | 副标题文字垂直方向的基线         | `string`   | top                   |\n| subtitleFill          | 副标题文字的填充色               | `string`   | #1D2129               |\n| subtitleFillOpacity   | 副标题文字的填充透明度           | `number`   | 0.65                  |\n| subtitleStroke        | 副标题文字的描边颜色             | `string`   | transparent           |\n| subtitleStrokeOpacity | 副标题文字的描边透明度           | `number`   | 1                     |\n| subtitleLineWidth     | 副标题文字描边宽度               | `number`   | 0                     |\n| subtitleLineDash      | 副标题文字虚线样式               | `number[]` | []                    |\n| subtitleOpacity       | 副标题文字整体透明度             | `number`   | 1                     |\n| subtitleShadowColor   | 副标题文字阴影颜色               | `string`   | transparent           |\n| subtitleShadowBlur    | 副标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| subtitleShadowOffsetX | 副标题文字阴影水平偏移量         | `number`   | 0                     |\n| subtitleShadowOffsetY | 副标题文字阴影垂直偏移量         | `number`   | 0                     |\n| subtitleCursor        | 副标题文字鼠标样式               | `string`   | default               |\n| subtitleDx            | 副标题文字在水平方向的偏移量     | `number`   | 0                     |\n| subtitleDy            | 副标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n## 尝试一下\n\n你可以在这个例子里随意修改并尝试不同的配置\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // 标题的对齐方式\n      spacing: 4, // 主标题和副标题之间的间距\n      size: 60, // 标题的高度，默认为 44\n\n      // 标题\n      title: '这是一个标题这是一个标题', // 标题的文本\n      titleFontSize: 28, // 主标题的字体大小\n      titleFontFamily: 'sans-serif', // 主标题的字体\n      titleFontWeight: 600, // 主标题的字体粗细\n      titleFill: '#fff', // 主标题的文字颜色\n      titleFillOpacity: 1, // 主标题的文字透明度\n      titleStroke: '#000', // 主标题的文字描边颜色\n      titleLineWidth: 2, // 主标题的文字描边线宽\n      titleStrokeOpacity: 1, // 主标题的文字描边透明度\n\n      // 副标题\n      subtitle: '这是一个副标', // 副标题的文本\n      subtitleFontSize: 16, // 副标题的字体大小\n      subtitleFontFamily: 'Arial', // 副标题的字体\n      subtitleFontWeight: 300, // 副标题的字体粗细\n      subtitleFill: '#2989FF', // 副标题的文字颜色\n      subtitleFillOpacity: 1, // 副标题的文字透明度\n      subtitleStroke: '#000', // 副标题的文字描边颜色\n      subtitleLineWidth: 1, // 副标题的文字描边线宽\n      subtitleStrokeOpacity: 0.5, // 副标题的文字描边透明度\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: '你好' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Toolbar.en.md":"---\ntitle: Toolbar\norder: 15\n---\n\n## Overview\n\nThe Toolbar is a plugin in G6 used to provide a collection of operation buttons, supporting common chart operations such as zoom in, zoom out, auto-fit, and reset. Through the toolbar, users can quickly access common functions of the chart, improving operational efficiency and user experience.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Quickly accessing common functions of the chart\n\n## Basic Usage\n\nBelow is a simple example of initializing the Toolbar plugin:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // Handle button click events\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property  | Description                                                                  | Type                                                                                        | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type      | Plugin type                                                                  | string                                                                                      | `toolbar`     | ✓        |\n| key       | Unique identifier for the plugin, used for updates                           | string                                                                                      | -             |          |\n| className | Additional CSS class name for the toolbar DOM element                        | string                                                                                      | -             |          |\n| position  | Toolbar position relative to the canvas, [optional values](#position)        | string                                                                                      | `'top-left'`  |          |\n| style     | Custom style for the toolbar DOM element, [common values](#style-attributes) | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| getItems  | Returns the list of toolbar items                                            | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -             | ✓        |\n| onClick   | Callback function after a toolbar item is clicked                            | (value: string, target: Element) => void                                                    | -             |          |\n\n### position\n\nThe `position` parameter supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side, top\n- `'left-bottom'`: Left side, bottom\n- `'right-top'`: Right side, top\n- `'right-bottom'`: Right side, bottom\n\n### style Attributes\n\n| Attribute       | Description      | Type   | Default Value       |\n| --------------- | ---------------- | ------ | ------------------- |\n| backgroundColor | Background color | string | `#fff`              |\n| border          | Border           | string | `1px solid #e8e8e8` |\n| borderRadius    | Border radius    | string | `4px`               |\n| height          | Height           | string | `auto`              |\n| margin          | Margin           | string | `12px`              |\n| opacity         | Opacity          | number | 0.9                 |\n| padding         | Padding          | string | `8px`               |\n| width           | Width            | string | `auto`              |\n\n### ToolbarItem\n\nEach toolbar item (ToolbarItem) includes the following attributes:\n\n| Attribute | Description                                                | Type     | Required |\n| --------- | ---------------------------------------------------------- | -------- | -------- |\n| id        | Icon ID of the item, see [Built-in Icons](#built-in-icons) | `string` | ✓        |\n| value     | Value returned when the item is clicked                    | `string` | ✓        |\n\n### Built-in Icons\n\nThe Toolbar provides the following built-in icon IDs:\n\n- `'zoom-in'`: Zoom in\n- `'zoom-out'`: Zoom out\n- `'redo'`: Redo\n- `'undo'`: Undo\n- `'edit'`: Edit\n- `'delete'`: Delete\n- `'auto-fit'`: Auto-fit view\n- `'export'`: Export chart\n- `'reset'`: Reset view\n- `'request-fullscreen'`: Request fullscreen\n- `'exit-fullscreen'`: Exit fullscreen\n\n### Custom Icons\n\nIn addition to using built-in icons, you can also use custom icons by introducing third-party icon libraries (such as Alibaba iconfont):\n\n```js\n// Introduce iconfont script\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // Replace with your iconfont script URL\ndocument.head.appendChild(iconFont);\n\n// Use custom icons in the toolbar\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // Use icons from iconfont\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Note: Custom icon IDs usually start with `icon-` and need to correspond to the icon names in the introduced iconfont.\n\n## Code Examples\n\n### Basic Toolbar\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo, undo need to be used with the history plugin\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### Custom Styles\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Common style attributes include:\n>\n> - `backgroundColor`: Background color\n> - `padding`: Padding\n> - `margin`/`marginTop`/`marginLeft`, etc.: Margin\n> - `border`: Border\n> - `borderRadius`: Border radius\n> - `boxShadow`: Shadow effect\n> - `opacity`: Opacity\n> - `width`/`height`: Width and height (default is content adaptive)\n> - `zIndex`: Layer (default is 100)\n> - `display`: Display mode (default is flex)\n\nThe toolbar container is set to `display: flex` by default, and child items use row layout by default (or change according to the direction configured by position). You can customize its appearance and position through `style`.\n\n### Asynchronous Loading of Toolbar Items\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Toolbar icons not displaying?\n\n- Check if the correct built-in icon ID is used\n- Ensure CSS styles are not overridden or conflicting\n\n### 2. How to use with other plugins?\n\nThe toolbar is often used in conjunction with other plugins (such as history):\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// Update toolbar position\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Toolbar.zh.md":"---\ntitle: 工具栏 Toolbar\norder: 15\n---\n\n## 概述\n\nToolbar 是 G6 中用于提供操作按钮集合的插件，支持放大、缩小、自适应、重置等常用图表操作。通过工具栏，用户可以快速访问图表的常用功能，提高操作效率和用户体验。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 快速访问图表的常用功能\n\n## 基本用法\n\n以下是一个简单的 Toolbar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // 处理按钮点击事件\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                             | 类型                                                                                        | 默认值       | 必选 |\n| --------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type      | 插件类型                                         | string                                                                                      | `toolbar`    | ✓    |\n| key       | 插件唯一标识符，用于后续更新                     | string                                                                                      | -            |      |\n| className | 工具栏DOM元素的额外CSS类名                       | string                                                                                      | -            |      |\n| position  | 工具栏位置，相对于画布，[可选值](#position)      | string                                                                                      | `'top-left'` |      |\n| style     | 工具栏DOM元素的自定义样式，[常用值](#style-属性) | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| getItems  | 返回工具栏项目列表                               | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -            | ✓    |\n| onClick   | 工具栏项目点击后的回调函数                       | (value: string, target: Element) => void                                                    | -            |      |\n\n### position\n\n`position` 参数支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n### style 属性\n\n| 属性            | 描述     | 类型   | 默认值              |\n| --------------- | -------- | ------ | ------------------- |\n| backgroundColor | 背景颜色 | string | `#fff`              |\n| border          | 边框     | string | `1px solid #e8e8e8` |\n| borderRadius    | 圆角     | string | `4px`               |\n| height          | 高度     | string | `auto`              |\n| margin          | 外边距   | string | `12px`              |\n| opacity         | 透明度   | number | 0.9                 |\n| padding         | 内边距   | string | `8px`               |\n| width           | 宽度     | string | `auto`              |\n\n### ToolbarItem\n\n每个工具栏项目 (ToolbarItem) 包含以下属性：\n\n| 属性  | 描述                                            | 类型     | 必选 |\n| ----- | ----------------------------------------------- | -------- | ---- |\n| id    | 项目的图标ID，内置图标ID见[内置图标](#内置图标) | `string` | ✓    |\n| value | 点击项目时返回的值                              | `string` | ✓    |\n\n### 内置图标\n\nToolbar 提供以下内置图标 ID：\n\n- `'zoom-in'`：放大\n- `'zoom-out'`：缩小\n- `'redo'`：重做\n- `'undo'`：撤销\n- `'edit'`：编辑\n- `'delete'`：删除\n- `'auto-fit'`：自适应视图\n- `'export'`：导出图表\n- `'reset'`：重置视图\n- `'request-fullscreen'`：请求全屏\n- `'exit-fullscreen'`：退出全屏\n\n### 自定义图标\n\n除了使用内置图标外，还可以通过引入第三方图标库（如阿里巴巴 iconfont）来使用自定义图标：\n\n```js\n// 引入 iconfont 脚本\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // 替换为你的 iconfont 脚本地址\ndocument.head.appendChild(iconFont);\n\n// 在工具栏中使用自定义图标\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // 使用 iconfont 中的图标\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 注意：自定义图标的 ID 通常以 `icon-` 开头，需要与引入的 iconfont 中的图标名称对应。\n\n## 代码示例\n\n### 基础工具栏\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo、undo 需要配合 history 插件使用\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### 自定义样式\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 常用的样式属性包括：\n>\n> - `backgroundColor`：背景颜色\n> - `padding`：内边距\n> - `margin`/`marginTop`/`marginLeft` 等：外边距\n> - `border`：边框\n> - `borderRadius`：圆角\n> - `boxShadow`：阴影效果\n> - `opacity`：透明度\n> - `width`/`height`：宽高（默认自适应内容）\n> - `zIndex`：层级（默认为 100）\n> - `display`：显示方式（默认为 flex）\n\n工具栏容器默认设置 `display: flex`，子项目默认使用行布局（或根据 position 配置的方向改变）。你可以通过 `style` 自定义其外观和位置。\n\n### 异步加载工具栏项\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 工具栏图标不显示？\n\n- 检查是否使用了正确的内置图标 ID\n- 确保 CSS 样式未被覆盖或冲突\n\n### 2. 如何结合其他插件使用？\n\n工具栏常常与其他插件（如历史记录）配合使用：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// 更新工具栏位置\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Tooltip.en.md":"---\ntitle: Tooltip\norder: 16\n---\n\n## Overview\n\nThe Tooltip plugin is used to display additional information when users hover over or click on elements in the graph. It helps users better understand the data in the graph and improves the interactive experience.\n\n## Use Cases\n\n- **Detailed Information Display**: When users need to understand detailed information about elements, use Tooltip to display this information\n- **Data Visualization Assistance**: In data visualization, Tooltip can display detailed information about data points in charts, helping users better understand the data\n- **Interactive Feedback**: Provide immediate visual feedback for user mouse operations\n\n## Basic Usage\n\nThe simplest Tooltip plugin configuration:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property     | Description               | Type                                                                                                                                          | Default Value                         | Required |\n| ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------- |\n| type         | Plugin type               | string                                                                                                                                        | `tooltip`                             | ✓        |\n| key          | Identifier                | string                                                                                                                                        | -                                     |          |\n| position     | Tooltip position          | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                                        | `top-right`                           |          |\n| enable       | Whether plugin is enabled | boolean \\| ((event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |          |\n| getContent   | Custom content            | (event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |          |\n| onOpenChange | Show/hide callback        | (open: boolean) => void                                                                                                                       | -                                     |          |\n| trigger      | Trigger behavior          | `hover` \\| `click`                                                                                                                            | `hover`                               |\n| container    | Custom render container   | string \\| HTMLElement                                                                                                                         | -                                     |          |\n| offset       | Offset distance           | [number,number]                                                                                                                               | [10,10]                               |          |\n| enterable    | Whether pointer can enter | boolean                                                                                                                                       | false                                 |          |\n| title        | Title                     | string                                                                                                                                        | -                                     |\n| style        | Style object              | Record<string,any>                                                                                                                            | {'.tooltip': { visibility: 'hidden'}} |          |\n\n## Detailed Configuration\n\n### enable - Conditional Enable\n\nControls whether the plugin is enabled, supports passing functions to dynamically adjust enable logic.\n\n**Example: Enable Tooltip only for nodes**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Server Node' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Database Node' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: 'Connection' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // Enable only for nodes, not for edges\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>Node: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - Custom Content\n\nCustomize Tooltip content rendering, supports returning HTMLElement or string.\n\n**Example: Dynamically render custom HTML content**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: 'Server A', type: 'Application Server', status: 'Running', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: 'Database B', type: 'MySQL Database', status: 'Normal', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Type:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Status:</strong>\n                <span style=\"color: ${item.data.status === 'Running' || item.data.status === 'Normal' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Memory:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Connections:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Size:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">Connection Info</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Bandwidth:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Latency:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return 'No information available';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - Trigger Mode\n\nControls the trigger behavior of Tooltip.\n\n**Available values:**\n\n- `hover`: Trigger when mouse enters element (default)\n- `click`: Trigger when mouse clicks element\n\n**Example: Click-triggered Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Click me' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Click me too' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              Click Triggered 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              Element ID: ${items[0].id}<br/>\n              Name: ${items[0].data?.name || 'Unnamed'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - Display Position\n\nControls the display position of Tooltip relative to mouse position.\n\n**Available values:**\n\n- `top`: Top\n- `bottom`: Bottom\n- `left`: Left\n- `right`: Right\n- `top-left`: Top left\n- `top-right`: Top right (default)\n- `bottom-left`: Bottom left\n- `bottom-right`: Bottom right\n\n**Example: Tooltips at different positions**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Display at top ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Display at bottom ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `Display at left ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `Display at right ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - Offset\n\nSet the offset for Tooltip display position, with mouse position as the base point.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'Default offset' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'Custom offset' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Default offset [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // Offset 30px to the right, 10px up\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Custom offset [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - Mouse Enterable\n\nControls whether the mouse pointer can enter the tooltip box, commonly used for scenarios requiring interaction within the Tooltip.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'User A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: 'User B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">User Actions</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>Name:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>Email:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('Send message to ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Message\n              </button>\n              <button onclick=\"alert('View ${item.data.name} details')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Details\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - Style Customization\n\nCustomize Tooltip styles.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: 'Dark Theme' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: 'Light Theme' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Basic Tooltip](/en/examples/plugin/tooltip/#basic)\n- [Click-triggered Tooltip](/en/examples/plugin/tooltip/#click)\n- [Different tooltips for hover and click on the same element](/en/examples/plugin/tooltip/#dual)\n- [Custom styled Tooltip](/en/examples/plugin/tooltip/#custom-style)\n- [Asynchronous content loading Tooltip](/en/examples/plugin/tooltip/#async)\n\n## API\n","packages/site/docs/manual/plugin/Tooltip.zh.md":"---\ntitle: 提示框 Tooltip\norder: 16\n---\n\n## 概述\n\nTooltip 插件用于在用户将鼠标悬停或点击图中的元素时，显示额外的信息。它可以帮助用户更好地理解图中的数据，提高交互体验。\n\n## 使用场景\n\n- **详细信息展示**：当用户需要了解元素的详细信息时，使用 Tooltip 提示框来展示这些信息\n- **数据可视化辅助**：在数据可视化中，Tooltip 可以显示图表中数据点的详细信息，帮助用户更好地理解数据\n- **交互反馈**：为用户的鼠标操作提供即时的视觉反馈\n\n## 基本使用\n\n最简单的 Tooltip 插件配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性         | 描述                    | 类型                                                                                                                            | 默认值                                | 必选 |\n| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ---- |\n| type         | 插件类型                | string                                                                                                                          | `tooltip`                             | ✓    |\n| key          | 标识符                  | string                                                                                                                          | -                                     |      |\n| position     | 气泡框位置              | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                          | `top-right`                           |      |\n| enable       | 插件是否启用            | boolean \\| ((event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |      |\n| getContent   | 自定义内容              | (event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |      |\n| onOpenChange | 显示隐藏的回调          | (open: boolean) => void                                                                                                         | -                                     |      |\n| trigger      | 触发行为                | `hover` \\| `click`                                                                                                              | `hover`                               |\n| container    | tooltip自定义渲染的容器 | string \\| HTMLElement                                                                                                           | -                                     |      |\n| offset       | 偏移距离                | [number,number]                                                                                                                 | [10,10]                               |      |\n| enterable    | 指针是否可以进入        | boolean                                                                                                                         | false                                 |      |\n| title        | 标题                    | string                                                                                                                          | -                                     |\n| style        | 样式对象                | Record<string,any>                                                                                                              | {'.tooltip': { visibility: 'hidden'}} |      |\n\n## 详细配置说明\n\n### enable - 条件启用\n\n控制插件是否启用，支持传入函数动态调整启用逻辑。\n\n**示例：只对节点启用 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '服务器节点' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '数据库节点' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: '连接线' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // 只对节点启用，边不显示tooltip\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>节点: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - 自定义内容\n\n自定义渲染 Tooltip 内容，支持返回 HTMLElement 或 string。\n\n**示例：动态渲染自定义 HTML 内容**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: '服务器A', type: '应用服务器', status: '运行中', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: '数据库B', type: 'MySQL数据库', status: '正常', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>类型:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>状态:</strong>\n                <span style=\"color: ${item.data.status === '运行中' || item.data.status === '正常' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>内存:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>连接数:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>大小:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">连接信息</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>带宽:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>延迟:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return '暂无信息';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - 触发方式\n\n控制 Tooltip 的触发行为。\n\n**可选值：**\n\n- `hover`：鼠标移入元素时触发（默认）\n- `click`：鼠标点击元素时触发\n\n**示例：点击触发 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '点击我' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '也点击我' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              点击触发 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              元素ID: ${items[0].id}<br/>\n              名称: ${items[0].data?.name || '未命名'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - 显示位置\n\n控制 Tooltip 相对于鼠标位置的显示位置。\n\n**可选值：**\n\n- `top`: 顶部\n- `bottom`: 底部\n- `left`: 左侧\n- `right`: 右侧\n- `top-left`: 顶部靠左\n- `top-right`: 顶部靠右（默认）\n- `bottom-left`: 底部靠左\n- `bottom-right`: 底部靠右\n\n**示例：不同位置的 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `顶部显示 ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `底部显示 ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `左侧显示 ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `右侧显示 ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - 偏移量\n\n设置 Tooltip 显示位置的偏移量，以鼠标位置为基点。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: '默认偏移' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: '自定义偏移' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `默认偏移 [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // 向右偏移30px，向上偏移10px\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `自定义偏移 [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - 鼠标可进入\n\n控制鼠标指针是否可以进入气泡框，常用于需要在 Tooltip 内进行交互的场景。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '用户A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: '用户B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">用户操作</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>姓名:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>邮箱:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('发送消息给 ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                发消息\n              </button>\n              <button onclick=\"alert('查看 ${item.data.name} 的详情')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                详情\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - 样式自定义\n\n自定义 Tooltip 的样式。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: '深色主题' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: '浅色主题' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [基础提示框](/examples/plugin/tooltip/#basic)\n- [点击触发 Tooltip](/examples/plugin/tooltip/#click)\n- [鼠标移入和点击同一元素时显示不同的提示框](/examples/plugin/tooltip/#dual)\n- [自定义样式的 Tooltip](/examples/plugin/tooltip/#custom-style)\n- [异步加载内容的 Tooltip](/examples/plugin/tooltip/#async)\n","packages/site/docs/manual/plugin/Watermark.en.md":"---\ntitle: Watermark\norder: 17\n---\n\n## Overview\n\nThe watermark plugin supports using text and images as watermarks. The principle is to add a `background-image` attribute to the div of the Graph container, and then control the position and style of the watermark through CSS. For text watermarks, a hidden canvas is used to convert the text into an image.\n\n## Use Cases\n\n- Add copyright or ownership marks to charts\n- Mark the status of charts during presentations or previews\n- Add anti-leakage marks to sensitive data\n\n## Basic Usage\n\nBelow is a simple example of initializing the Watermark plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // Watermark text\n      opacity: 0.2, // Opacity\n      rotate: Math.PI / 12, // Rotation angle\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## Configuration Options\n\n| Property             | Description                                              | Type                                                                        | Default Value | Required |\n| -------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | -------- |\n| type                 | Plugin type                                              | string                                                                      | `watermark`   | ✓        |\n| width                | Width of a single watermark                              | number                                                                      | 200           |          |\n| height               | Height of a single watermark                             | number                                                                      | 100           |          |\n| opacity              | Opacity of the watermark                                 | number                                                                      | 0.2           |          |\n| rotate               | Rotation angle of the watermark                          | number                                                                      | Math.PI / 12  |          |\n| imageURL             | Image watermark URL, higher priority than text watermark | string                                                                      | -             |          |\n| text                 | Watermark text content                                   | string                                                                      | -             |          |\n| textFill             | Color of the text watermark                              | string                                                                      | `#000`        |          |\n| textFontSize         | Font size of the text watermark                          | number                                                                      | 16            |          |\n| textFontFamily       | Font of the text watermark                               | string                                                                      | -             |          |\n| textFontWeight       | Font weight of the text watermark                        | string                                                                      | -             |          |\n| textFontVariant      | Font variant of the text watermark                       | string                                                                      | -             |          |\n| textAlign            | Text alignment of the watermark                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`      |          |\n| textBaseline         | Baseline alignment of the text watermark                 | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`      |          |\n| backgroundRepeat     | Repeat mode of the watermark                             | string                                                                      | `repeat`      |          |\n| backgroundAttachment | Background attachment behavior of the watermark          | string                                                                      | -             |          |\n| backgroundBlendMode  | Background blend mode of the watermark                   | string                                                                      | -             |          |\n| backgroundClip       | Background clip of the watermark                         | string                                                                      | -             |          |\n| backgroundColor      | Background color of the watermark                        | string                                                                      | -             |          |\n| backgroundImage      | Background image of the watermark                        | string                                                                      | -             |          |\n| backgroundOrigin     | Background origin of the watermark                       | string                                                                      | -             |          |\n| backgroundPosition   | Background position of the watermark                     | string                                                                      | -             |          |\n| backgroundPositionX  | Horizontal position of the watermark background          | string                                                                      | -             |          |\n| backgroundPositionY  | Vertical position of the watermark background            | string                                                                      | -             |          |\n| backgroundSize       | Background size of the watermark                         | string                                                                      | -             |          |\n\n## Code Examples\n\n### Text Watermark\n\nThe simplest text watermark configuration:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Image Watermark\n\nUse an image as a watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style and position of the watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // Set font size\n      textFontFamily: 'Arial', // Set font\n      textFontWeight: 'bold', // Set font weight\n      textFill: '#1890ff', // Set text color\n      rotate: Math.PI / 6, // Set rotation angle\n      opacity: 0.15, // Set opacity\n      width: 180, // Set watermark width\n      height: 100, // Set watermark height\n      backgroundRepeat: 'space', // Set repeat mode\n      backgroundPosition: 'center', // Set position\n      textAlign: 'center', // Set text alignment\n      textBaseline: 'middle', // Set baseline alignment\n    },\n  ],\n});\n```\n\n## Real Cases\n\n- [Text Watermark](/examples/plugin/watermark/#text)\n- [Image Watermark](/examples/plugin/watermark/#repeat)\n","packages/site/docs/manual/plugin/Watermark.zh.md":"---\ntitle: 水印 Watermark\norder: 17\n---\n\n## 概述\n\n水印插件支持使用文本和图片作为水印，实现原理是在 Graph 容器的 div 上加上 `background-image` 属性，然后通过 CSS 来控制水印的位置和样式。对于文本水印，会使用隐藏 canvas 将文本转换为图片的方式来实现。\n\n## 使用场景\n\n- 为图表添加版权或所有权标识\n- 在演示或预览时标记图表的状态\n- 为敏感数据添加防泄露标记\n\n## 基本用法\n\n以下是一个简单的 Watermark 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // 水印文本\n      opacity: 0.2, // 透明度\n      rotate: Math.PI / 12, // 旋转角度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## 配置项\n\n| 属性                 | 描述                               | 类型                                                                        | 默认值       | 必选 |\n| -------------------- | ---------------------------------- | --------------------------------------------------------------------------- | ------------ | ---- |\n| type                 | 插件类型                           | string                                                                      | `watermark`  | ✓    |\n| width                | 单个水印的宽度                     | number                                                                      | 200          |      |\n| height               | 单个水印的高度                     | number                                                                      | 100          |      |\n| opacity              | 水印的透明度                       | number                                                                      | 0.2          |      |\n| rotate               | 水印的旋转角度                     | number                                                                      | Math.PI / 12 |      |\n| imageURL             | 图片水印的地址，优先级高于文本水印 | string                                                                      | -            |      |\n| text                 | 水印文本内容                       | string                                                                      | -            |      |\n| textFill             | 文本水印的颜色                     | string                                                                      | `#000`       |      |\n| textFontSize         | 文本水印的字体大小                 | number                                                                      | 16           |      |\n| textFontFamily       | 文本水印的字体                     | string                                                                      | -            |      |\n| textFontWeight       | 文本水印的字体粗细                 | string                                                                      | -            |      |\n| textFontVariant      | 文本水印的字体变体                 | string                                                                      | -            |      |\n| textAlign            | 文本水印的对齐方式                 | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`     |      |\n| textBaseline         | 文本水印的基线对齐方式             | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`     |      |\n| backgroundRepeat     | 水印的重复方式                     | string                                                                      | `repeat`     |      |\n| backgroundAttachment | 水印的背景定位行为                 | string                                                                      | -            |      |\n| backgroundBlendMode  | 水印的背景混合模式                 | string                                                                      | -            |      |\n| backgroundClip       | 水印的背景裁剪                     | string                                                                      | -            |      |\n| backgroundColor      | 水印的背景颜色                     | string                                                                      | -            |      |\n| backgroundImage      | 水印的背景图片                     | string                                                                      | -            |      |\n| backgroundOrigin     | 水印的背景原点                     | string                                                                      | -            |      |\n| backgroundPosition   | 水印的背景位置                     | string                                                                      | -            |      |\n| backgroundPositionX  | 水印的背景水平位置                 | string                                                                      | -            |      |\n| backgroundPositionY  | 水印的背景垂直位置                 | string                                                                      | -            |      |\n| backgroundSize       | 水印的背景大小                     | string                                                                      | -            |      |\n\n## 代码示例\n\n### 文本水印\n\n最简单的文本水印配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 图片水印\n\n使用图片作为水印：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义水印的样式和位置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // 设置字体大小\n      textFontFamily: 'Arial', // 设置字体\n      textFontWeight: 'bold', // 设置字体粗细\n      textFill: '#1890ff', // 设置文字颜色\n      rotate: Math.PI / 6, // 设置旋转角度\n      opacity: 0.15, // 设置透明度\n      width: 180, // 设置水印宽度\n      height: 100, // 设置水印高度\n      backgroundRepeat: 'space', // 设置重复方式\n      backgroundPosition: 'center', // 设置位置\n      textAlign: 'center', // 设置文本对齐\n      textBaseline: 'middle', // 设置基线对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n- [文本水印](/examples/plugin/watermark/#text)\n- [图片水印](/examples/plugin/watermark/#repeat)\n","packages/site/docs/manual/plugin/custom-plugin.en.md":"---\ntitle: Custom Plugin\norder: 20\n---\n\n## Overview\n\nCustom plugins can implement additional features, such as adding extra components, rendering logic, etc. Custom plugins can effectively achieve functional decoupling, better manage and orchestrate code, and facilitate subsequent maintenance.\n\n## Use Cases\n\n### Add extra components, rendering logic, etc.\n\n- **Extra components**: Such as built-in plugins like `Tooltip`, `Minimap`, `Snapline`, `Grid`, `Context Menu`, `Watermark`, etc.\n- **Rendering logic**: Such as built-in plugins like `Edge Bundling`, and `Remote Data Loading` ([Example](#remote-data-loading)), etc.\n\n### When built-in plugins cannot meet the requirements\n\nWhen built-in plugins cannot fully meet business needs, users can also make adjustments and modifications through custom plugins (inheriting built-in plugins).\n\n_(If the features supported by built-in plugins are more general, or if there are bugs in built-in plugins, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Custom Plugin Examples\n\nLike interactions, the implementation of plugins is also quite flexible, and you can implement your plugin in your preferred style.\n\nHere are a few simple custom plugin implementations:\n\n### Remote Data Loading\n\nAutomatically load remote data during graph instantiation:\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- In this example, we simulate a data loading plugin. After using this plugin, there is no need to pass data when instantiating the Graph, as the plugin will automatically load remote data.\n\n- `BasePlugin` is the base class for all plugins, and each custom plugin needs to inherit this base class.\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### Automatically Enable or Disable Animation Based on Node Count\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // Disable global animation when the number of nodes reaches this value\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In this example, we listen to the `GraphEvent.BEFORE_RENDER` event and determine whether the current number of nodes exceeds a specified value. If so, global animation is disabled; otherwise, it is enabled.\n- `maxLength` is a defined configuration item that can be passed in when initializing the graph instance. [Plugin Configuration](#configure-plugin)\n\n## Register Plugin\n\nRegister using the method provided by G6\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## Configure Plugin\n\n- You can pass the plugin type name or configuration parameter object in `plugins`, see [Configure Plugin](/manual/plugin/overview#configuration-method)\n\n- For example, the previous [Automatically Enable or Disable Animation Based on Node Count](#automatically-enable-or-disable-animation-based-on-node-count) is configured as follows:\n\n  ```typescript\n  const graph = new Graph({\n    // Other configurations\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","packages/site/docs/manual/plugin/custom-plugin.zh.md":"---\ntitle: 自定义插件\norder: 20\n---\n\n## 概述\n\n自定义插件可以实现一些额外的功能，例如添加额外的组件、渲染逻辑等。通过自定义插件可以很好地实现功能解耦，更好地进行管理、编排代码以及后续维护。\n\n## 使用场景\n\n### 添加额外的组件、渲染逻辑等\n\n- **额外的组件**：如内置插件的`提示框`、`小地图`、`对齐线`、`网格线`、`上下文菜单`、`水印`等\n- **渲染逻辑**：如内置插件的`边绑定`，以及`远程数据加载`（[示例](#远程数据加载)）等\n\n### 内置插件无法满足需求\n\n当内置插件无法完全满足业务需求时，用户也可以通过自定义插件（继承内置插件）进行调整和修改。\n\n_（如果需要内置插件支持的特性是较通用的，或者内置插件存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 自定义插件示例\n\n与交互类似，插件的实现也相当灵活，你可以以你喜欢的风格实现你的插件。\n\n下面列举几个简单的自定义插件实现：\n\n### 远程数据加载\n\n在图实例化过程中自动加载远程数据：\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- 在这个例子中，我们模拟实现了一个数据加载插件，在使用该插件后，实例化 Graph 时不用再传入数据，该插件会自动加载远程数据。\n\n- `BasePlugin` 是所有插件的基类，每个自定义插件都需要继承这个基类实现。\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### 自动判断节点数量开启或关闭动画\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // 节点数量达到这个值后关闭全局动画\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在这个例子中，我们监听 `GraphEvent.BEFORE_RENDER` 事件，在响应中判断当前节点数量是否大于指定值，是的话则关闭全局动画，否则开启\n- `maxLength` 是定义的配置项，可在初始化画布实例时传入具体配置，[插件配置](#配置插件)\n\n## 注册插件\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## 配置插件\n\n- 可在 `plugins` 中传入插件类型名称或配置参数对象，详见[配置插件](/manual/plugin/overview#配置方式)\n\n- 比如前面的[自动判断节点数量开启或关闭动画](#自动判断节点数量开启或关闭动画)，配置如下：\n\n  ```typescript\n  const graph = new Graph({\n    // 其他配置\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","packages/site/docs/manual/plugin/overview.en.md":"---\ntitle: Plugin Overview\norder: 0\n---\n\n## What is a Plugin\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nA Plugin is the most flexible extension mechanism in G6, allowing users to extend G6's functionality, such as adding graphical components to the canvas or implementing undo/redo features.\n\nMost customization needs can be achieved through plugins. G6 comes with some built-in plugins, such as: [Tooltip](/en/manual/plugin/tooltip), [Grid](/en/manual/plugin/grid-line), [History](/en/manual/plugin/history).\n\n## Built-in Plugins\n\nG6 provides a rich set of built-in plugins covering various common functional scenarios:\n\n| Category                     | Plugin Name                                                                                         | Registration Type  | Description                                                            |\n| ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |\n| **Visual Style Enhancement** |                                                                                                     |                    |                                                                        |\n|                              | [Grid Line](/en/manual/plugin/grid-line)                                                            | `grid-line`        | Displays grid reference lines on the canvas                            |\n|                              | [Background](/en/manual/plugin/background)                                                          | `background`       | Adds background images or colors to the canvas                         |\n|                              | [Watermark](/en/manual/plugin/watermark)                                                            | `watermark`        | Adds a watermark to the canvas to protect copyright                    |\n|                              | [Hull](/en/manual/plugin/hull)                                                                      | `hull`             | Creates an outline for a specified set of nodes                        |\n|                              | [Bubble Sets](/en/manual/plugin/bubble-sets)                                                        | `bubble-sets`      | Creates smooth bubble-like element outlines                            |\n|                              | [Snapline](/en/manual/plugin/snapline)                                                              | `snapline`         | Displays alignment reference lines when dragging elements              |\n| **Navigation and Overview**  |                                                                                                     |                    |                                                                        |\n|                              | [Minimap](/en/manual/plugin/minimap)                                                                | `minimap`          | Displays a thumbnail preview of the graph, supporting navigation       |\n|                              | [Fullscreen](/en/manual/plugin/fullscreen)                                                          | `fullscreen`       | Supports full-screen display and exit for charts                       |\n|                              | [Timebar](/en/manual/plugin/timebar)                                                                | `timebar`          | Provides filtering and playback control for temporal data              |\n| **Interactive Controls**     |                                                                                                     |                    |                                                                        |\n|                              | [Toolbar](/en/manual/plugin/toolbar)                                                                | `toolbar`          | Provides a collection of common operation buttons                      |\n|                              | [Context Menu](/en/manual/plugin/contextmenu)                                                       | `contextmenu`      | Displays a menu of selectable operations on right-click                |\n|                              | [Tooltip](/en/manual/plugin/tooltip)                                                                | `tooltip`          | Displays detailed information about elements on hover                  |\n|                              | [Legend](/en/manual/plugin/legend)                                                                  | `legend`           | Displays categories and corresponding style descriptions of chart data |\n| **Data Exploration**         |                                                                                                     |                    |                                                                        |\n|                              | [Fisheye](/en/manual/plugin/fisheye)                                                                | `fisheye`          | Provides a focus + context exploration experience                      |\n|                              | [Edge Filter Lens](/en/manual/plugin/edge-filter-lens)                                              | `edge-filter-lens` | Filters and displays edges within a specified area                     |\n|                              | [Edge Bundling](/en/manual/plugin/edge-bundling)                                                    | `edge-bundling`    | Bundles edges with similar paths together to reduce visual clutter     |\n| **Advanced Features**        |                                                                                                     |                    |                                                                        |\n|                              | [History](/en/manual/plugin/history)                                                                | `history`          | Supports undo/redo operations                                          |\n|                              | [Camera Setting](/enhttps://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | Configures camera parameters in a 3D scene                             |\n\nFor detailed configuration of each plugin, refer to the [Built-in Plugin Documentation](/en/manual/plugin/grid-line).\n\n## Configuration Methods\n\n### Basic Configuration\n\nSpecify the required plugins through the `plugins` array when initializing the graph instance:\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### Configuring Plugin Parameters\n\nFor plugins that require custom parameters, you can configure properties using the `object` form:\n\n```javascript {5-9}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // Specify a key for the plugin for future updates\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### Dynamically Updating Plugins\n\nG6 supports dynamic management of plugins during the runtime of the graph instance to meet complex interaction needs:\n\nUse the [getPlugins](/en/api/plugin#graphgetplugins) method to get the current list of plugins:\n\n```javascript\n// Get the list of plugins\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\nYou can adjust plugins using the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method:\n\n```javascript\n// Add a new plugin\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// Remove a plugin\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\nYou can update the configuration of a plugin using the [updatePlugin](/en/api/plugin#graphupdatepluginplugin) method:\n\n```javascript {6,14}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n\n// Update a single plugin\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>Updated content: ${e.target.id}</div>`,\n});\n```\n\n:::warning{title=Note}\nWhen using the `updatePlugin` method, you need to specify a unique `key` for the plugin during initialization.\n:::\n\n### Uninstalling Plugins\n\nUse the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method to uninstall plugins by setting the plugin configuration list to empty:\n\n```javascript\n// Uninstall all plugins\ngraph.setPlugins([]);\n```\n\n### Calling Plugin Methods\n\nSome plugins provide API methods for users to call, such as the `history` plugin providing `undo` and `redo` methods, allowing users to implement undo and redo operations by calling these methods.\n\nTo call these methods, you need to first get the plugin instance, which can be obtained through the [getPluginInstance](/en/api/plugin#graphgetplugininstancekey) method:\n\n```javascript\n// Configure the plugin\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// Get the plugin instance\nconst history = graph.getPluginInstance('my-history');\n\n// Call plugin methods\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=Note}\nThe `graph.getPluginInstance` method takes the plugin key value as a parameter, so if you need to get the plugin instance, you need to configure the corresponding plugin in the form of an `object` and pass in the `key` value.\n:::\n\nFor more plugin-related APIs, please refer to the [Plugin API Documentation](/en/api/plugin).\n\n## Custom Plugins\n\nWhen built-in plugins cannot meet your needs, you can:\n\n- Inherit and extend existing plugins\n- Create brand new custom plugins\n\nCustom plugins need to be registered before use. For detailed tutorials, please refer to the [Custom Plugin](/en/manual/plugin/custom-plugin) documentation.\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// Register custom plugin\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// Use custom plugin\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\nBy reasonably combining and configuring plugins, you can build graph visualization applications with rich features and excellent interactive experiences.\n","packages/site/docs/manual/plugin/overview.zh.md":"---\ntitle: 插件总览\norder: 0\n---\n\n## 什么是插件\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n插件(Plugin)是 G6 中最灵活的扩展机制，用户可以通过插件来扩展 G6 的功能，例如在画布中额外挂载图形组件、实现撤销重做等功能。\n\n绝大多数的定制需求都可以通过插件来实现，G6 内置了一些常用的插件，例如：[Tooltip](/manual/plugin/tooltip)、[Grid](/manual/plugin/grid-line)、[History](/manual/plugin/history)。\n\n## 内置插件\n\nG6 提供了丰富的内置插件，涵盖多种常见功能场景：\n\n| 分类             | 插件名称                                                                                   | 注册类型           | 功能描述                               |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------ | -------------------------------------- |\n| **视觉样式增强** |                                                                                            |                    |                                        |\n|                  | [网格线](/manual/plugin/grid-line)                                                         | `grid-line`        | 在画布上显示网格参考线                 |\n|                  | [背景](/manual/plugin/background)                                                          | `background`       | 为画布添加背景图片或颜色               |\n|                  | [水印](/manual/plugin/watermark)                                                           | `watermark`        | 为画布添加水印，保护版权               |\n|                  | [轮廓包围](/manual/plugin/hull)                                                            | `hull`             | 为指定节点集合创建轮廓                 |\n|                  | [气泡集](/manual/plugin/bubble-sets)                                                       | `bubble-sets`      | 创建平滑气泡状的元素集合轮廓           |\n|                  | [对齐线](/manual/plugin/snapline)                                                          | `snapline`         | 拖动元素时显示对齐参考线               |\n| **导航与概览**   |                                                                                            |                    |                                        |\n|                  | [缩略图](/manual/plugin/minimap)                                                           | `minimap`          | 显示图的缩略预览，支持导航             |\n|                  | [全屏](/manual/plugin/fullscreen)                                                          | `fullscreen`       | 支持图表全屏显示和退出                 |\n|                  | [时间轴](/manual/plugin/timebar)                                                           | `timebar`          | 提供时序数据的筛选和播放控制           |\n| **交互控件**     |                                                                                            |                    |                                        |\n|                  | [工具栏](/manual/plugin/toolbar)                                                           | `toolbar`          | 提供常用操作按钮集合                   |\n|                  | [上下文菜单](/manual/plugin/contextmenu)                                                   | `contextmenu`      | 右键点击时显示可选操作菜单             |\n|                  | [提示框](/manual/plugin/tooltip)                                                           | `tooltip`          | 悬停时显示元素详细信息                 |\n|                  | [图例](/manual/plugin/legend)                                                              | `legend`           | 显示图表数据的类别和对应样式说明       |\n| **数据探索**     |                                                                                            |                    |                                        |\n|                  | [鱼眼放大镜](/manual/plugin/fisheye)                                                       | `fisheye`          | 提供焦点+上下文的探索体验              |\n|                  | [边过滤镜](/manual/plugin/edge-filter-lens)                                                | `edge-filter-lens` | 在指定区域内筛选显示边                 |\n|                  | [边绑定](/manual/plugin/edge-bundling)                                                     | `edge-bundling`    | 将相似路径的边捆绑在一起，减少视觉混乱 |\n| **高级功能**     |                                                                                            |                    |                                        |\n|                  | [历史记录](/manual/plugin/history)                                                         | `history`          | 支持撤销/重做操作                      |\n|                  | [相机设置](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | 配置3D场景下的相机参数                 |\n\n各插件的详细配置可参考 [内置插件文档](/manual/plugin/grid-line)。\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `plugins` 数组指定需要的插件：\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### 配置插件参数\n\n对于需要自定义参数的插件，可以使用 `object` 形式配置属性：\n\n```javascript {5-9}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // 为插件指定key，便于后续更新\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### 动态更新插件\n\nG6 支持在图实例运行期间动态管理插件，满足复杂交互需求：\n\n通过 [getPlugins](/api/plugin#graphgetplugins) 方法获取当前插件列表：\n\n```javascript\n// 获取插件列表\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\n可以通过 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法调整插件：\n\n```javascript\n// 添加新插件\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// 移除插件\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\n可以通过 [updatePlugin](/api/plugin#graphupdatepluginplugin) 方法更新插件的配置：\n\n```javascript {6,14}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n\n// 更新单个插件\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>更新的内容：${e.target.id}</div>`,\n});\n```\n\n:::warning{title=注意}\n使用 `updatePlugin` 方法时，需要在初始化时为插件指定唯一的 `key`。\n:::\n\n### 卸载插件\n\n使用 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法同样可以卸载插件，将插件配置列表置为空即可：\n\n```javascript\n// 卸载所有插件\ngraph.setPlugins([]);\n```\n\n### 调用插件方法\n\n一些插件提供了可供用户调用的 API 方法，例如 `history` 插件提供了 `undo` 和 `redo` 方法，用户可以通过调用这些方法来实现撤销和重做操作。\n\n要调用这些方法，需要先获取到插件实例，可通过 [getPluginInstance](/api/plugin#graphgetplugininstancekey) 方法获取：\n\n```javascript\n// 配置插件\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// 获取插件实例\nconst history = graph.getPluginInstance('my-history');\n\n// 调用插件方法\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=注意}\n`graph.getPluginInstance` 方法接收插件 key 值作为参数，因此如果需要获取插件实例，需要将对应插件配置为 `object` 的形式，并传入 `key` 值。\n:::\n\n更多与插件相关的 API 请参考 [插件 API 文档](/api/plugin)。\n\n## 自定义插件\n\n当内置插件无法满足需求时，你可以：\n\n- 继承和扩展现有插件\n- 创建全新的自定义插件\n\n自定义插件需要先注册后使用。详细教程请参考 [自定义插件](/manual/plugin/custom-plugin) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// 注册自定义插件\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// 使用自定义插件\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\n通过合理组合和配置插件，你可以构建出功能丰富、交互体验出色的图可视化应用。\n","packages/site/docs/manual/theme/custom-palette.en.md":"---\ntitle: Custom Palette\norder: 4\n---\n\n## Overview\n\n[Core Concepts - Palette](/en/manual/core-concept/palette) mentions that G6 supports discrete palettes and continuous palettes. A discrete palette is essentially an array of colors, while a continuous palette is a color interpolator.\n\nTherefore, customizing a palette also adopts these two methods, and the following sections will introduce how to customize discrete and continuous palettes, respectively.\n\n## Implement Palette\n\n### Discrete Palette\n\nYou can simply define a string array that contains color values. Supported color values include: RGB color values, hexadecimal color values, and color names. Below is an example of a discrete palette:\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### Continuous Palette\n\nA continuous palette requires the definition of a color interpolator. The interpolator is a function that accepts a numerical value as a parameter and returns a color value. Below is an example of a continuous palette:\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can register a palette using the `register` method provided by G6. For more details, please refer to [Register Palette](/en/manual/core-concept/palette#register-palette)\n\n## Use Without Registration\n\nIn addition to registration, you can also bypass the registration mechanism and directly pass the palette value at the location where the palette is needed, for example:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // Pass in a color array.\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Pass in an interpolator\n    }\n  }\n}\n```\n","packages/site/docs/manual/theme/custom-palette.zh.md":"---\ntitle: 自定义色板\norder: 4\n---\n\n## 概述\n\n[色板](/manual/theme/palette) 中提到，G6 支持离散色板和连续色板，其中离散色板本质上是一个颜色数组，而连续色板是一个颜色插值器。\n\n因此自定义色板也采用这两种方式，下面分别介绍如何自定义离散色板和连续色板。\n\n## 实现色板\n\n### 离散色板\n\n直接定义一个包含颜色值的字符串数组即可，颜值值支持：RGB 色值、16 进制、颜色名，下面是一组离散色板示例：\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### 连续色板\n\n连续色板需要定义一个颜色插值器，插值器是一个函数，接受一个数值参数，返回一个颜色值，下面是一个连续色板示例：\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n通过 G6 提供的 register 方法注册即可，详见[注册色板](/manual/theme/palette#注册色板)\n\n## 非注册方式使用\n\n除此之外，你也可以在需要使用色板的位置跳过注册机制直接传入色板值，例如：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // 传入颜色数组\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 传入插值器\n    }\n  }\n}\n```\n","packages/site/docs/manual/theme/custom-theme.en.md":"---\ntitle: Custom Theme\norder: 2\n---\n\n## Overview\n\nIn G6, the theme is a subset of Graph Options and includes configurations related to the canvas and element styles. A theme can help you quickly switch between different graph styles.\n\n## Custom Theme\n\nFor element styles, the configurations within a theme are static and do not support the use of callback functions to dynamically calculate styles. Additionally, `type` is also not supported for configuration within a theme. A theme includes the following configurations:\n\n- `background`: Canvas background color\n- `node`: Node style\n- `edge`: Edge style\n- `combo`: Combo style\n\nBelow is a simple example of a theme configuration:\n\n```typescript\nconst theme = {\n  background: '#fff',\n  node: {\n    style: {\n      fill: '#e1f3fe',\n      lineWidth: 0,\n    },\n    selected: {\n      style: {\n        fill: '#3b71d6',\n        lineWidth: 1,\n      },\n    },\n  },\n  edge: {\n    // ...\n  },\n  combo: {\n    // ...\n  },\n};\n```\n\n❌ Incorrect Example\n\n```typescript\nconst theme = {\n  node: {\n    // ❌ The theme does not support configuring element types\n    type: 'rect',\n    style: {\n      // ❌ The theme does not support callback functions\n      fill: (d) => d.style.color,\n    },\n  },\n};\n```\n\n:::warning{title=Note}\nFor element state styles, please ensure that every property in the state style has a corresponding default style in the default style, otherwise it may result in the inability to clear the state style.\n:::\n\n## Register Theme\n\nYou can register a theme using the `register` method provided by G6. Here is an example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.THEME, 'custom-theme', theme);\n```\n\n## Configure Theme\n\nTo enable and configure a theme, you need to pass the `theme` option when instantiating the `Graph`:\n\n```typescript\n{\n  theme: 'custom-theme',\n}\n```\n\n### Switch Theme\n\nAfter the `Graph` instance is created, you can switch themes by using the [setTheme](/en/api/theme#graphsetthemetheme) method:\n\n```typescript\ngraph.setTheme('dark');\n```\n\nAdditionally, you can also obtain the current theme by using the `getTheme` method:\n\n```typescript\ngraph.getTheme();\n// => 'dark'\n```\n","packages/site/docs/manual/theme/custom-theme.zh.md":"---\ntitle: 自定义主题\norder: 2\n---\n\n除了使用内置主题外，G6 还支持创建自定义主题来满足特定的视觉需求。本文将介绍如何创建和使用自定义主题。\n\n## 创建自定义主题\n\n一个自定义主题需要遵循主题的基本结构，包含画布背景色和元素样式配置：\n\n```javascript\nconst customTheme = {\n  // 1. 画布背景色\n  background: '#f0f0f0',\n\n  // 2. 节点配置\n  node: {\n    // 调色板配置\n    palette: {\n      type: 'group',\n      color: ['#1783FF', '#00C9C9' /* 自定义颜色... */],\n    },\n    // 基础样式\n    style: {\n      fill: '#fff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他节点样式\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#e8f3ff',\n        stroke: '#1783FF',\n      },\n      // ... 其他状态样式\n    },\n  },\n\n  // 3. 边配置\n  edge: {\n    style: {\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他边样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n\n  // 4. Combo 配置\n  combo: {\n    style: {\n      fill: '#f7f7f7',\n      stroke: '#d9d9d9',\n      // ... 其他 Combo 样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n};\n```\n\n## 使用限制\n\n在创建自定义主题时，需要注意以下限制：\n\n1. **仅支持静态值**\n\n   ```javascript\n   // ❌ 错误示例：不支持回调函数\n   const theme = {\n     node: {\n       style: {\n         fill: (d) => d.style.color,\n       },\n     },\n   };\n   ```\n\n2. **不支持配置元素类型**\n\n   ```javascript\n   // ❌ 错误示例：不支持在主题中配置元素类型\n   const theme = {\n     node: {\n       type: 'rect',\n       style: {\n         fill: '#fff',\n       },\n     },\n   };\n   ```\n\n3. **状态样式需要对应默认样式**\n   ```javascript\n   // ✅ 正确示例：状态样式的属性在默认样式中都有定义\n   const theme = {\n     node: {\n       style: {\n         fill: '#fff',\n         stroke: '#000',\n       },\n       state: {\n         selected: {\n           fill: '#e8f3ff',\n           stroke: '#1783FF',\n         },\n       },\n     },\n   };\n   ```\n\n## 应用自定义主题\n\n先注册主题，然后通过名称引用：\n\n```javascript\n// 1. 注册主题\nimport { register, ExtensionCategory } from '@antv/g6';\nregister(ExtensionCategory.THEME, 'custom-theme', customTheme);\n\n// 2. 使用主题\nconst graph = new Graph({\n  theme: 'custom-theme',\n  // ... 其他配置\n});\n```\n","packages/site/docs/manual/theme/overview.en.md":"---\ntitle: Theme Overview\norder: 1\n---\n\n## Overview\n","packages/site/docs/manual/theme/overview.zh.md":"---\ntitle: 主题总览\norder: 1\n---\n\n## 概述\n\nG6 中的主题是 Graph Options 的子集，它包含了关于画布和元素样式的配置。多主题可以帮助你快速地切换不同的图样式。\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 主题结构\n\n一个主题由以下四个部分组成：\n\n1. **画布背景色 (background)**\n\n   - 控制整个画布的背景颜色\n\n2. **节点配置 (node)**\n\n   - 基础样式：填充色、描边、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于节点分组的颜色配置\n   - 状态样式：不同状态下的样式配置（选中、激活、禁用等）\n   - 动画配置：节点的动画效果配置\n\n3. **边配置 (edge)**\n\n   - 基础样式：线条样式、箭头、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于边分组的颜色配置\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：边的动画效果配置\n\n4. **Combo 配置 (combo)**\n   - 基础样式：填充、描边、折叠按钮等静态视觉属性\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：Combo 的动画效果配置\n\n> 注意：主题中的样式配置仅支持静态值，不支持回调函数形式的动态配置。如需动态样式，请使用图的配置项。\n\n## 内置主题\n\nG6 默认提供两种内置主题：\n\n### 亮色主题（默认）\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SPCES62UzzAAAAAAAAAAAAAAemJ7AQ/original\" alt=\"亮色主题\" />\n\n<details><summary>查看亮色主题完整配置项</summary>\n\n```js\nconst lightTheme = {\n  background: '#ffffff',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#000000',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#000000',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#000000',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fillOpacity: 0.25,\n        iconOpacity: 0.85,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.06,\n        fill: '#1B324F',\n        fillOpacity: 0.06,\n        iconFill: '#1B324F',\n        iconOpacity: 0.25,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.06,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#99ADD1',\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#99ADD1',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#99ADD1',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#1B324F',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#d9d9d9',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#ffffff',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#99ADD1',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99ADD1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99ADD1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d9d9d9',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#d9d9d9',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n### 暗色主题\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*qTlLSoAbaXYAAAAAAAAAAAAAemJ7AQ/original\" alt=\"暗色主题\" />\n\n<details><summary>查看暗色主题完整配置项</summary>\n\n```js\nconst darkTheme = {\n  background: '#000000',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#ffffff',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#d0e4ff',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#d0e4ff',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.45,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.25,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.45,\n        donutOpacity: 0.45,\n        fillOpacity: 0.45,\n        iconOpacity: 0.45,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.45,\n        strokeOpacity: 0.45,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fill: '#D0E4FF',\n        fillOpacity: 0.25,\n        iconFill: '#D0E4FF',\n        iconOpacity: 0.25,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#637088',\n        '#0F55A6',\n        '#008383',\n        '#9C5D38',\n        '#8B53A6',\n        '#4E40A6',\n        '#8F6608',\n        '#3E801D',\n        '#A65383',\n        '#175E75',\n        '#0F8248',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#637088',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#637088',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#D0E4FF',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#637088',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#000000',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#fdfdfd',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99add1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99add1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d0e4ff',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#969696',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n## 使用主题\n\n### 配置主题\n\n在创建图时通过 `theme` 选项指定要使用的主题：\n\n```javascript\nconst graph = new Graph({\n  theme: 'light', // 或 'dark'\n  // ... 其他配置\n});\n```\n\n### 切换主题\n\n创建图后，可以通过 `setTheme` 方法动态切换主题：\n\n```javascript\n// 切换到暗色主题\ngraph.setTheme('dark');\n\n// 获取当前主题\nconst currentTheme = graph.getTheme(); // 'dark'\n```\n\n## 样式优先级\n\n在 G6 中，元素的最终样式由多个层级的样式合并而成，按优先级从低到高排序：\n\n**⭐️ 主题默认样式** < 调色板样式 < 数据样式 < 图的默认样式 < **⭐️ 主题状态样式** < 图的状态样式\n\n详细说明：\n\n1. **主题默认样式**：主题系统提供的基础样式\n2. **调色板样式**：基于主题调色板配置的自动着色样式\n3. **数据样式**：在数据中定义的样式\n4. **图的默认样式**：通过图的配置项设置的样式\n5. **主题状态样式**：主题中定义的状态样式\n6. **图的状态样式**：通过图的配置项设置的状态样式\n\n更多关于自定义主题的内容，请参考[自定义主题](/manual/theme/custom-theme)。\n","packages/site/docs/manual/theme/palette.en.md":"---\ntitle: Palette\norder: 3\n---\n\n## Overview\n\nA palette refers to a set of predefined color collections that help users more conveniently select colors. In G6, a palette is a common option that allows users to configure the colors of elements such as nodes, edges, and links through the palette.\n\nPalettes are divided into two types: `discrete palette` and `continuous palette`.\n\nA discrete palette is an array of colors used to map discrete values within elements to different colors, such as the type of nodes, the relationship of edges, etc. Below is a simple example of a discrete palette:\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\nA continuous palette is an interpolator that takes a value between 0 and 1 and returns the corresponding color. It is used to map continuous values within elements to different colors, such as the degree of nodes, the weight of edges, etc. Below is a simple example of a continuous palette:\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can directly use the built-in palettes, but if you want to use other palettes, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=note}\n\nDuring the process of registering a palette, there is no distinction made between discrete and continuous palettes. It is necessary to ensure the consistency between the palette type and the data type when using the palette.\n:::\n\n### Built-in Palettes\n\nCurrently, G6 has 5 sets of commonly used discrete palettes that users can directly utilize:\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## Configure Palette\n\nCurrently, the configuration of palettes is mainly focused on elements, taking nodes as an example:\n\n### Discrete Palette\n\n1. Default Configuration: By directly setting the value of `palette` to the name of the palette, each node will be assigned a different color by default\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral is the Palette Name\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> When the number of elements exceeds the number of colors in the palette, the colors in the palette will be reused in a cyclic manner.\n\n2. Standard Configuration: The attributes for configuring a discrete palette include: `type: 'group'`, `field`, `color`, `invert`.\n\nAmong them, `type: 'group'` explicitly specifies that the current palette type is a discrete palette; `field` designates the field for grouping in the element data; `color` is the name of the palette; `invert` indicates whether to invert the palette.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\nIn the data, `node-1` and `node-4` belong to category A, `node-2` and `node-5` belong to category B, `node-3` and `node-6` belong to category C.\n\nConfigure the color of the nodes in such a way that nodes of the same category have the same color:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // Specify the palette type as a categorical palette.\n      field: 'category', // Specify the grouping field in the data.\n      color: 'tableau', // Use a Tableau-like palette.\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### Continuous Palette\n\nA continuous palette only supports standard configuration methods, with configuration properties including: `type: 'value'`, `field`, `color`, `invert`.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\nNow, create an interpolator that maps the maximum value to red (`rgb(255, 0, 0)`) and the minimum value to black (`rgb(0, 0, 0)`):\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\nConfigure the following so that the color of the nodes is mapped to different colors based on the value of the `value` field in the data:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // Specify the palette type as a continuous palette\n      field: 'value', // Specify the numerical field in the data\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Use an interpolator\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=note}\n\nThe built-in continuous palette does not support specifying a value range. If there is a need for more complex color mapping, it can be customized within the style mapping.\n:::\n\n## Custom Palette\n\nIf the built-in palette does not meet your requirements, you can customize the palette. For details, please refer to [Custom Palette](/en/manual/custom-extension/palette).\n\n## Priority\n\nThe palette generates styles based on the type of element. For nodes and combos, the color is mapped to the `fill` attribute; for edges, the color is mapped to the `stroke` attribute.\n\nIf both a palette and a style mapping are configured, the style mapping will override the palette colors. In the following example, the color of the nodes is always red:\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","packages/site/docs/manual/theme/palette.zh.md":"---\ntitle: 色板\norder: 3\n---\n\n## 概述\n\n色板(Palette)是指一组预定义的颜色集合，用于帮助用户更方便的选择颜色。在 G6 中，色板是一种常见的配置项，用户可以通过色板来配置节点、边、连线等元素的颜色。\n\n色板分为`离散色板`和`连续色板`两种类型。\n\n离散色板是一组颜色数组，用于将元素中的离散值映射到不同的颜色上，例如节点的类型、边的关系等。下面是一个简单的离散色板示例：\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\n连续色板是一个插值器，输入 0~1 的值，返回对应的颜色，用于将元素中的连续值映射到不同的颜色上，例如节点的度数、边的权重等。下面是一个简单的连续色板示例：\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n你可以直接使用内置色板，如果想使用其他色板，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=注意}\n在注册色板过程中并不会区分离散色板和连续色板，使用色板过程中需要自行保证色板类型和数据类型的一致性。\n:::\n\n### 内置色板\n\n目前 G6 内置了 5 套常用的离散色板，用户可以直接使用：\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## 配置色板\n\n目前开放色板配置的地方主要以元素为主，以节点为例：\n\n### 离散色板\n\n1. 默认配置，直接配置 `palette` 的值为色板名，会默认为每个节点分配不同的颜色\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral 为色板名\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> 当元素数量超过色板颜色数量时，会循环使用色板中的颜色\n\n2. 标准配置，离散色板配置属性包括：`type: 'group'`，`field`，`color`，`invert`\n\n其中 `type: 'group'` 显式指定了当前色板类型为离散色板；`field` 指定元素数据中的分组字段；`color` 为色板名；`invert` 为是否反转色板。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\n数据中 `node-1`，`node-4` 属于 A 类别，`node-2`，`node-5` 属于 B 类别，`node-3`，`node-6` 属于 C 类别。\n\n通过以下方式配置节点的颜色，使得同类别的节点颜色相同：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // 指定色板类型为分类色板\n      field: 'category', // 指定数据中的分组字段\n      color: 'tableau', // 使用 tableau 色板\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### 连续色板\n\n连续色板只支持标准方式配置，配置属性包括：`type: 'value'`，`field`，`color`，`invert`。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\n现在创建一个插值器，将最大值映射为红色(`rgb(255, 0, 0)`)，最小值映射为黑色(`rgb(0, 0, 0)`)：\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\n通过以下配置使得节点的颜色根据数据中的 `value` 字段的值映射到不同的颜色：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // 指定色板类型为连续色板\n      field: 'value', // 指定数据中的数值字段\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 使用插值器\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=注意}\n内置连续色板不支持指定值域范围，如果有更复杂的颜色映射需求，可以在样式映射中自定义\n:::\n\n## 自定义色板\n\n如果内置色板无法满足需求，可以自定义色板，具体请参考[自定义色板](/manual/theme/custom-palette)。\n\n## 优先级\n\n色板会基于元素类型生成样式，对于节点和组合，会将颜色映射到 `fill` 属性；对于边，会将颜色映射到 `stroke` 属性。\n\n如果同时配置了色板和样式映射，样式映射会覆盖色板颜色。下面的例子中，节点的颜色始终为红色：\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","packages/site/docs/manual/transform/MapNodeSize.en.md":"---\ntitle: MapNodeSize\norder: 1\n---\n\nIn graph visualization, the size of a node is usually used to convey the importance or influence of the node. By adjusting the size of the node based on the centrality of the node, we can more intuitively show the importance of each node in the network, helping users better understand and analyze complex network structures.\n\n## Options\n\n### centrality\n\n> [NodeCentralityOptions](#nodecentralityoptions) _\\| ((graphData:_ [GraphData](/manual/core-concept/data#图数据graphdata)_) =>_ _Map**&lt;**string, number>)_ **Default:** `type: 'eigenvector'`\n\nThe method of measuring the node centrality\n\n- `'degree'`: Degree centrality, measures centrality by the degree (number of connected edges) of a node. Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measures centrality by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measures centrality by the reciprocal of the average shortest path length from a node to all other nodes. Nodes with high closeness centrality usually can reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measures centrality by the degree of connection between a node and other central nodes. Nodes with high eigenvector centrality usually connect to other important nodes\n- `'pagerank'`: PageRank centrality, measures centrality by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to the page ranking algorithm\n- Custom centrality calculation method: `(graphData: GraphData) => Map<ID, number>`, where `graphData` is the graph data, and `Map<ID, number>` is the mapping from node ID to centrality value\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n### mapLabelSize\n\n> _boolean \\| [number, number]_ **Default:** `false`\n\nWhether to map label size synchronously\n\n### maxSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `80`\n\nThe maximum size of the node\n\n### minSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `20`\n\nThe minimum size of the node\n\n### scale\n\n> _'linear' \\| 'log' \\| 'pow' \\| 'sqrt' \\| ((value: number, domain: [number, number], range: [number, number]) => number)_ **Default:** `'log'`\n\nScale type\n\n- `'linear'`: Linear scale, maps a value from one range to another range linearly, commonly used for cases where the difference in centrality values is small\n\n- `'log'`: Logarithmic scale, maps a value from one range to another range logarithmically, commonly used for cases where the difference in centrality values is large\n\n- `'pow'`: Power-law scale, maps a value from one range to another range using power law, commonly used for cases where the difference in centrality values is large\n\n- `'sqrt'`: Square root scale, maps a value from one range to another range using square root, commonly used for cases where the difference in centrality values is large\n\n- Custom scale: `(value: number, domain: [number, number], range: [number, number]) => number`，where `value` is the value to be mapped, `domain` is the input range, and `range` is the output range\n","packages/site/docs/manual/transform/MapNodeSize.zh.md":"---\ntitle: 动态调整节点大小 MapNodeSize\norder: 1\n---\n\n## 概述\n\n在图可视化中，节点的大小通常用于传达节点的重要性或影响力。通过根据节点中心性调整节点的大小，我们可以更直观地展示网络中各个节点的重要性，从而帮助用户更好地理解和分析复杂的网络结构。\n\n## 使用场景\n\n需要通过节点大小来突出节点的重要性和影响力时，可使用此数据处理。\n\n以下为常见的场景：\n\n- **社交网络分析**：比如分析社交媒体平台中用户的活跃度与影响力，通过节点大小突出高互动用户。\n\n- **金融风险传导网络**：比如识别金融系统中承担关键资金流转职能的机构，预防系统性风险。\n\n- **交通枢纽规划**：比如优化城市地铁网络设计，识别换乘压力点。\n\n## 配置项\n\n| 属性         | 描述                                                       | 类型                                                                                                                               | 默认值               | 必选 |\n| ------------ | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type         | 数据处理类型                                               | map-node-size                                                                                                                      | -                    | ✓    |\n| centrality   | 节点中心性的度量方法，[配置项](#centrality)                | [NodeCentralityOptions](#nodecentralityoptions) \\| ((graphData: [GraphData](/manual/data#图数据graphdata)) => Map<string, number>) | `{ type: 'degree' }` |      |\n| mapLabelSize | 是否同步调整标签大小                                       | boolean \\| [number, number]                                                                                                        | false                |      |\n| maxSize      | 节点最大尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 80                   |      |\n| minSize      | 节点最小尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 20                   |      |\n| scale        | 插值函数，用于将节点中心性映射到节点大小，[配置项](#scale) | `linear` \\| `log` \\| `pow` \\| `sqrt` \\| ((value: number, domain: [number, number], range: [number, number]) => number)             | `log`                |      |\n\n### centrality\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n- 自定义中心性计算方法：`(graphData: GraphData) => Map<ID, number>`，其中 `graphData` 为图数据，`Map<ID, number>` 为节点 ID 到中心性值的映射\n\n**示例：**\n\n```typescript {6-9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n        direction: 'both',\n      },\n    },\n  ],\n});\n```\n\n效果如下（可切换度量方法查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-centrality.md\"></embed>\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n`direction`：表示统计哪些方向的边，`in` -入边、 `out` -出边、 `both` -入边和出边都考虑进去\n\n`directed`：是否为有向图\n\n`weightPropertyName`：边的权重属性名\n\n`epsilon`：PageRank 算法的收敛容差\n\n`linkProb`：PageRank 算法的阻尼系数，指任意时刻，用户访问到某节点后继续访问该节点链接的下一个节点的概率，经验值 0.85\n\n### scale\n\n- `'linear'`：线性插值函数，将一个值从一个范围线性映射到另一个范围，常用于处理中心性值的差异较小的情况\n- `'log'`：对数插值函数，将一个值从一个范围对数映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'pow'`：幂律插值函数，将一个值从一个范围幂律映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'sqrt'`：平方根插值函数，将一个值从一个范围平方根映射到另一个范围，常用于处理中心性值的差异较大的情况\n- 自定义插值函数：`(value: number, domain: [number, number], range: [number, number]) => number`，其中 `value` 为需要映射的值，`domain` 为输入值的范围，`range` 为输出值的范围\n\n**示例：**\n\n```typescript {9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n      },\n      scale: 'linear',\n    },\n  ],\n});\n```\n\n效果如下（该示例为基于度中心性 `degree` ，可切换插值函数查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-scale.md\"></embed>\n\n## 实际案例\n\n- [场景案例：独角兽和他们的投资者](/examples/feature/default/#unicorns-investors)\n","packages/site/docs/manual/transform/PlaceRadialLabels.en.md":"---\ntitle: PlaceRadialLabels\norder: 3\n---\n\n## Options\n\n### offset\n\n> _number_\n\nOffset\n","packages/site/docs/manual/transform/PlaceRadialLabels.zh.md":"---\ntitle: 径向标签 PlaceRadialLabels\norder: 2\n---\n\n**参考示例**：\n\n- [径向生态树](/examples/scene-case/tree-graph/#radial-dendrogram)\n- [径向紧凑树](/examples/scene-case/tree-graph/#radial-compact-tree)\n\n## 配置项\n\n### type\n\n> _`place-radial-labels` \\| string_\n\n此数据处理已内置，你可以通过 `type: 'place-radial-labels'` 来使用它。\n\n### offset\n\n> _number_\n\n偏移量\n","packages/site/docs/manual/transform/ProcessParallelEdges.en.md":"---\ntitle: ProcessParallelEdges\norder: 3\n---\n\nParallel Edges refer to multiple edges existing between two nodes in a graph structure. These edges share the same source and target nodes but may represent different relationships or attributes. To avoid edge overlap and confusion, two methods are provided for handling parallel edges: (1) Bundle Mode: Bundles parallel edges together and separates them from other edges by altering their curvature; (2) Merge Mode: Merges parallel edges into a single aggregated edge.\n\n## Options\n\n### distance\n\n> _number_\n\nThe distance between edges, only valid for bundling mode\n\n### edges\n\n> _string[]_\n\nThe edges to be handled, all edges by default\n\n### <Badge type=\"success\">Required</Badge> mode\n\n> _'bundle' \\| 'merge'_ **Default:** `'bundle'`\n\nProcessing mode\n\n- '`merge`': Merge parallel edges into one edge which is suitable for cases where parallel edges do not need to be distinguished\n\n- '`bundle`': Each edge will be bundled with all other parallel edges and separated from them by varying the curvature. If the number of parallel edges in a group is odd, the central edge will be drawn as a straight line, and the others will be drawn as curves\n\n### style\n\n> _PathStyleProps_ _\\| ((prev:_ [EdgeData](/api/graph/option#edgedata)_[]) =>_ _PathStyleProps)_\n\nThe style of the merged edge, only valid for merging mode\n","packages/site/docs/manual/transform/ProcessParallelEdges.zh.md":"---\ntitle: 平行边 ProcessParallelEdges\norder: 3\n---\n\n## 概述\n\n平行边（Parallel Edges）是指在图结构中，两个节点之间存在多条边。这些边共享相同的源节点和目标节点，但可能代表不同的关系或属性。为了避免边的重叠和混淆，提供了两种处理平行边的方式：\n\n- 捆绑模式（bundle）：将平行边捆绑在一起，通过改变曲率与其他边分开\n- 合并模式（merge）：将平行边合并为一条聚合\n\n## 使用场景\n\n下面为常见使用场景举例：\n\n- 双向数据流，比如客户端发送请求，服务端返回响应\n\n- 多依赖关系，即一个节点通过多种方式依赖另一个节点，比如微服务架构中，服务 A 调用服务 B的两个不同 API\n- 多链路，比如高可用架构中，主链路（实线，状态正常）与备份链路（灰色虚线，状态待机）同时展示\n\n## 基本用法\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges',\n      mode: 'bundle', // 默认就是捆绑模式了\n      distance: 30, // 配置捆绑模式下边之间的距离为30\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性     | 描述                                               | 类型                                                                                    | 默认值                  | 必选 |\n| -------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type     | 数据处理类型                                       | process-parallel-edges                                                                  | -                       | ✓    |\n| distance | 边之间的距离，仅在捆绑模式下有效                   | number                                                                                  | 15                      |      |\n| edges    | 考虑要处理的边，默认为全部边                       | string[]                                                                                | -                       |      |\n| mode     | 处理模式，[配置项](#mode)                          | `'bundle'`                                                                              | `'merge'` \\| `'bundle'` |      |\n| style    | 合并边的样式，仅在合并模式下有效，[配置项](#style) | PathStyleProps \\| ((prev: [EdgeData](/manual/data#边数据edgedata)[]) => PathStyleProps) | -                       |      |\n\n### mode\n\n提供了两种处理模式：\n\n- `'merge'`: 将平行边合并为一条边，适用于不需要区分平行边的情况，[示例](#合并模式)\n\n`merge` 使用的是内置的直线（ [`line`](/manual/element/edge/Line) ）来展示合并边。\n\n- `'bundle'`: 每条边都会与其他所有平行边捆绑在一起，并通过改变曲率与其他边分开。如果一组平行边的数量是奇数，那么中心的边将被绘制为直线，其他的边将被绘制为曲线，[示例](#捆绑模式)\n\n`bundle` 使用的是内置的二次贝塞尔曲线（ [`quadratic`](/manual/element/edge/Quadratic) ）来实现，数据处理过程会强制把每个 `edgeDatum.type` 改为 `quadratic`，并计算每条线的曲率。\n\n:::warning{title=注意}\n\n禁止在创建 Graph 实例时配置 `edge.type` 即默认的边类型，因为它的优先级比 `edgeDatum.type` 要高，会导致 `bundle` 模式的处理无法生效。\n\n:::\n\n### style\n\n合并边的样式，仅在合并模式下有效\n\n#### PathStyleProps\n\n下表列出了常用的属性，更多属性请参考 [PathStyleProps](https://g.antv.antgroup.com/api/basic/path#pathstyleprops)。\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| fill           | 填充色                    | string                        | `#1783FF` |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |\n| lineDash       | 描边虚线样式              | number[]                      | -         |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |\n| lineWidth      | 描边宽度                  | number                        | 1         |\n| opacity        | 透明度                    | number \\| string              | 1         |\n| shadowBlur     | 阴影模糊度                | number                        | -         |\n| shadowColor    | 阴影颜色                  | string                        | -         |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |\n| stroke         | 描边色                    | string                        | `#000`    |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |\n\n## 代码示例\n\n### 捆绑模式\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'C' },\n    { source: 'C', target: 'A' },\n    ...Array.from({ length: 10 }).map((_, i) => ({\n      id: `edge:A-B${i}`,\n      source: 'A',\n      target: 'B',\n      data: {\n        label: `A->B:${i}`,\n      },\n    })),\n    ...Array.from({ length: 5 }).map((_, i) => ({\n      id: `edge:B-C${i}`,\n      source: 'B',\n      target: 'C',\n      data: {\n        label: `B->C:${i}`,\n      },\n    })),\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      ports: [{ placement: 'center' }],\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n    },\n  },\n  behaviors: ['drag-element'],\n  transforms: ['process-parallel-edges'],\n});\n\ngraph.render();\n```\n\n### 合并模式\n\n下面是一个简单的合并模式的例子，需要注意：\n\n- 不需要合并（即两个节点间只有一条边）的边，合并样式不会在这条边上生效，比如例子中的 **A->C**\n- 合并样式实际上是赋值给 `datum.style` ，也就是优先级会比实例化 Graph 时配置的默认样式低（ `edge.style` ），所以例子中合并样式的 `startArrow` 没有生效\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'B' },\n    { source: 'B', target: 'A' },\n    { id: 'B-C:1', source: 'B', target: 'C' },\n    { id: 'B-C:2', source: 'B', target: 'C' },\n    { source: 'A', target: 'C' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n      startArrow: false,\n    },\n  },\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      mode: 'merge',\n      style: {\n        halo: true,\n        haloOpacity: 0.2,\n        haloStroke: 'red',\n        startArrow: true,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/transform/custom-transform.en.md":"---\ntitle: Custom Transform\norder: 4\n---\n","packages/site/docs/manual/transform/custom-transform.zh.md":"---\ntitle: 自定义数据处理\norder: 4\n---\n\n## 概述\n\n自定义数据处理允许用户在业务实现过程中，把额外的数据处理封装起来，在渲染前或者布局后对数据进行进一步处理。用户通过自定义数据处理，实现部分数据处理解耦，更好地进行管理、编排代码以及提高代码可维护性。\n\n## 开始前\n\n用户在进行自定义数据处理前，需要仔细阅读并掌握数据处理器的 [实现原理和执行时机](/manual/transform/overview#实现原理) 。\n\n## 代码示例\n\n接下来将讲述两个可能的业务场景，并通过自定义数据处理来实现：\n\n### 不展示游离节点\n\n- **需求**\n\n  游离节点，即没有连线的节点，画布渲染时不展示游离节点\n\n- **实现**\n\n  ```typescript\n  import type { DrawData, DrawContext } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory } from '@antv/g6';\n\n  class HideFreeNode extends BaseTransform {\n    public beforeDraw(input: DrawData, context: DrawContext): DrawData {\n      const { model } = this.context;\n      const { add, update, remove } = input;\n\n      add.nodes.forEach((nodeData, nodeId) => {\n        // 获取节点的相关连线\n        const edges = model.getRelatedEdgesData(nodeId);\n        // 没有任何连线的的节点则从add里面移除，添加到remove里面\n        if (!edges.length) {\n          add.nodes.delete(nodeId);\n          remove.nodes.set(nodeId, nodeData);\n        }\n      });\n\n      return input;\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/hide-free-node.md\"></embed>\n\n- **说明**\n\n  示例中总共有6个节点，id为1-6，id为4的节点没有连线，因此被移除了。\n\n  通过 `getRelatedEdgesData` 获取节点的相关连线，没有则把该节点放到 `remove.nodes` 里面去，并从 `add.nodes` 里面移除。\n\n### 环形布局径向label\n\n- **需求**\n\n  使用 [环形布局](/manual/layout/circular-layout) 时，节点 label 的也需要像内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 一样实现径向展示（但 PlaceRadialLabels 只支持径向布局，环形布局不是径向布局）\n\n- **实现**\n\n  ```typescript\n  import type { RuntimeContext, DrawContext, Point, TransformArray, Vector2, Vector3 } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory, BaseTransformOptions } from '@antv/g6';\n\n  // 目前circular布局没有暴露方法可以获取布局中心，这里简单处理先固定一个，配置circular布局时center与这里保持一致即可\n  const circularCenter = [300, 300];\n\n  // 下面的函数 G6 没有暴露出来，先自行声明\n  function subtract(a: Vector2 | Vector3, b: Vector2 | Vector3): Vector2 | Vector3 {\n    return a.map((v, i) => v - b[i]) as Vector2 | Vector3;\n  }\n  function rad(a: Vector2 | Vector3): number {\n    const [x, y] = a;\n    if (!x && !y) return 0;\n    return Math.atan2(y, x);\n  }\n  function rad2deg(rad: number): number {\n    return rad * (180 / Math.PI);\n  }\n\n  interface CircularRadialLabelsOptions extends BaseTransformOptions {\n    offset?: number; // 偏移量\n  }\n\n  class CircularRadialLabels extends BaseTransform<CircularRadialLabelsOptions> {\n    static defaultOptions = {\n      offset: 5,\n    };\n    constructor(context: RuntimeContext, options: CircularRadialLabelsOptions) {\n      super(context, Object.assign({}, CircularRadialLabels.defaultOptions, options));\n    }\n    get center(): Point {\n      return circularCenter;\n    }\n    public afterLayout() {\n      const { graph, model } = this.context;\n      const data = model.getData();\n      data.nodes?.forEach((datum) => {\n        const radian = rad(subtract([datum.style.x, datum.style.y], this.center));\n        const isLeft = Math.abs(radian) > Math.PI / 2;\n        const isLeaf = !datum.children || datum.children.length === 0;\n        const nodeId = datum.id;\n        const node = this.context.element?.getElement(nodeId);\n        if (!node || !node.isVisible()) return;\n\n        const nodeHalfWidth = graph.getElementRenderStyle(nodeId).size / 2;\n        const offset = (isLeaf ? 1 : -1) * (nodeHalfWidth + this.options.offset);\n\n        const labelTransform: TransformArray = [\n          ['translate', offset * Math.cos(radian), offset * Math.sin(radian)],\n          ['rotate', isLeft ? rad2deg(radian) + 180 : rad2deg(radian)],\n        ];\n\n        model.updateNodeData([\n          {\n            id: datum.id,\n            style: {\n              labelTextAlign: isLeft === isLeaf ? 'right' : 'left',\n              labelTextBaseline: 'middle',\n              labelTransform,\n            },\n          },\n        ]);\n      });\n\n      graph.draw();\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/circular-radial-labels.md\"></embed>\n\n- **说明**\n  上面的实现基本是参考内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 来实现的，区别是这里的实现是通过拿到布局中心来计算偏移和旋转，具体可参考 PlaceRadialLabels 的 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/place-radial-labels.ts)\n","packages/site/docs/manual/transform/overview.en.md":"---\ntitle: Data Transformation Overview\norder: 0\n---\n\n## Overview\n","packages/site/docs/manual/transform/overview.zh.md":"---\ntitle: 数据处理总览\norder: 0\n---\n\n## 什么是数据处理\n\n数据处理（ `transform` ），也叫数据转换器，是 G6 提供的支持在 **渲染前( `beforeDraw` )** 或者 **布局后( `afterLayout` )** 对绘制数据进行转化处理的机制，用户可以通过数据处理很方便地对数据处理逻辑进行封装解耦。\n\n## 实现原理\n\n### 基类\n\n所有的数据处理器都是基于 [BaseTransform](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/base-transform.ts) 这个基类进行实现，里面定义了两个基类方法 `beforeDraw` 和 `afterLayout` ：\n\n```typescript\nexport abstract class BaseTransform<T extends BaseTransformOptions = BaseTransformOptions> extends BaseExtension<T> {\n  public beforeDraw(data: DrawData, context: DrawContext): DrawData {\n    return data;\n  }\n\n  public afterLayout(type: 'pre', data: DrawData): void;\n  public afterLayout(type: 'post', data?: undefined): void;\n  public afterLayout(type: 'pre' | 'post', data?: DrawData) {}\n}\n```\n\n以下是这两个方法里核心的参数类型说明：\n\n- **DrawData**\n\n  ```typescript\n  type ProcedureData = {\n    nodes: Map<ID, NodeData>;\n    edges: Map<ID, EdgeData>;\n    combos: Map<ID, ComboData>;\n  };\n\n  type DrawData = {\n    add: ProcedureData; // 本次渲染需要新增的元素\n    update: ProcedureData; // 本次渲染需要更新的元素\n    remove: ProcedureData; // 本次渲染需要移除的元素\n  };\n  ```\n\n- **pre | post**\n\n  pre：绘制前进行的布局（只会在首次布局触发）\n\n  post：完成绘制后进行的布局\n\n### 执行时机\n\n- **beforeDraw**\n\n  下面是每次渲染时数据处理的执行流程/时机：\n\n  <img width=\"300px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Pb3kRI2yHo8AAAAAAAAAAAAAemJ7AQ/original\"/>\n\n  **详细说明：**\n\n  1. G6 在每次渲染前计算出 `add`、`update`、`remove`，分别对应为需要新增、更新、移除的元素，以下简称为 `DrawData`\n  2. 此时数据处理介入，按配置顺序执行每个数据处理的 `beforeDraw` 方法，参数则为 `DrawData`\n  3. 数据处理器中，对 `DrawData` 里面的元素数据进行改动，即可以按需对 `add`、`update`、`remove` 里面的元素数据进行修改、移除或者插入元素数据等，最终把改动后的 `DrawData` 返回给渲染主体逻辑\n  4. 在执行数据处理后，执行对应的新增、更新、移除元素的操作，完成渲染\n\n:::info{title=提示}\n触发渲染的场景分为主动和被动，列举如下：\n\n- **主动：** 用户主动调用 `graph.render()` 、 `graph.draw()` 或者在自定义插件、交互等实例里面通过上下文拿到元素控制器（ [ElementController](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/element.ts) ）实例调用 `this.context.element.draw()`，等（ `graph.render()` 和 `graph.draw()` 也是调用元素控制器的 `draw` 方法）\n- **被动：** 部分内置交互和插件有触发渲染，布局执行后也有触发渲染更新元素位置，等\n\n:::\n\n- **afterLayout**：在执行完布局计算并开始更新节点位置后，执行数据处理\n\n## 内置数据处理\n\n- **G6 提供给用户的内置数据处理如下：**\n\n各数据处理详细配置可参考 [内置数据处理文档](/manual/transform/map-node-size)。\n\n| 数据处理名称                                        | 注册类型                 | 功能描述                                             | 执行时机   |\n| --------------------------------------------------- | ------------------------ | ---------------------------------------------------- | ---------- |\n| [动态调整节点大小](/manual/transform/map-node-size) | `map-node-size`          | 根据节点中心性调整节点的大小                         | beforeDraw |\n| [径向标签](/manual/transform/place-radial-labels)   | `place-radial-labels`    | 根据径向布局自动调整节点标签样式，包括位置和旋转角度 | afterDraw  |\n| [平行边](/manual/transform/process-parallel-edges)  | `process-parallel-edges` | 处理平行边，即多条边共享同一源节点和目标节点         | beforeDraw |\n\n- **G6 内嵌的数据处理如下：**\n\n除了提供给用户选用的数据处理外， G6 也封装并使用了以下数据处理机制来实现基础功能。以下数据处理不开放给用户配置使用，默认必带（列举出来供用户有需要时点击查看并参考源码）：\n\n| 数据处理名称                                                                                                            | 注册类型                | 功能描述                                                                                                                                                      | 执行时机   |\n| ----------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| [调整combo绘制顺序](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/arrange-draw-order.ts)              | `arrange-draw-order`    | combo 嵌套时，优先绘制子 combo                                                                                                                                | beforeDraw |\n| [处理组合的展开收起](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-combo.ts)          | `collapse-expand-combo` | 收起时，移除 combo 内部元素、销毁内部边，外部边则连到收起的 combo 上；<br />展开时，反之；                                                                    | beforeDraw |\n| [处理（树图）节点的收起和展开](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-node.ts) | `collapse-expand-node`  | 绘制前，处理（树图）节点的收起和展开                                                                                                                          | beforeDraw |\n| [获取边的实际端点](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/get-edge-actual-ends.ts)             | `get-edge-actual-ends`  | 配合`collapse-expand-combo`实现收起时，combo 外部连到内部节点的边改为连到收起的 combo 上（`collapse-expand-combo`只是在收起时判断并标记了这些边需要更新端点） | beforeDraw |\n| [更新节点、combo相关边](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/update-related-edge.ts)         | `update-related-edges`  | 如果更新了节点/combo，则把连接的边也一起更新了                                                                                                                | beforeDraw |\n\n:::warning{title=注意}\n\n上面 G6 为实现自身基础功能使用的数据处理仅供参考，不可改动。如有需要在这些数据处理基础上做特殊处理，可通过 [自定义数据处理](#自定义数据处理) 实现。\n\n:::\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `transforms` 数组指定需要的数据处理：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n### 配置数据处理参数\n\n对于需要自定义参数的数据处理，可以使用 `object` 形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    'place-radial-labels',\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges-1',\n      mode: 'bundle',\n      distance: 30,\n    },\n  ],\n});\n```\n\n### 动态更新数据处理\n\nG6 支持在图实例运行期间动态管理数据处理：\n\n- 可以通过 [setTransforms](/api/transform#graphsettransformstransforms) 方法调整数据处理器：\n\n```javascript\n// 添加新的数据处理器\ngraph.setTransforms((transforms) => [...transforms, 'place-radial-labels']);\n\n// 移除数据处理器\ngraph.setTransforms((transforms) => transforms.filter((t) => t !== 'place-radial-labels'));\n```\n\n- 可以通过 [updateTransform](/api/transform#graphupdatetransformtransform) 方法更新数据处理的配置：\n\n```javascript\n// 更新单个数据处理器\ngraph.updateTransform({\n  key: 'process-parallel-edges-1',\n  distance: 100,\n});\n```\n\n:::warning{title=注意}\n使用`updateTransform`方法时，需要在初始化时为数据处理指定唯一的`key`。\n:::\n\n### 卸载数据处理\n\n使用 [setTransforms](/api/transform#graphsettransformstransforms) 方法同样可以卸载数据处理，将数据处理配置列表置为空即可：\n\n```javascript\n// 卸载所有数据处理器\ngraph.setTransforms([]);\n```\n\n## 自定义数据处理\n\n当内置数据处理器无法满足需求时，你可以：\n\n- 继承和扩展现有数据处理\n- 创建全新的自定义数据处理\n\n自定义数据处理需要先注册后使用。详细教程请参考 [自定义数据处理](/manual/transform/custom-transform) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomTransform } from './my-custom-transform';\n\n// 注册自定义数据处理器\nregister(ExtensionCategory.TRANSFORM, 'my-custom-transform', MyCustomTransform);\n\n// 使用自定义数据处理\nconst graph = new Graph({\n  transforms: ['my-custom-transform'],\n});\n```\n","packages/site/docs/manual/whats-new/feature.en.md":"---\ntitle: Feature\norder: 1\n---\n\n## 🏖️ Brand New Design Specification for Graphs\n\nG6 version 5.0 has redesigned the Options specification. While ensuring comprehensive capabilities, it optimizes the options structure to be more intuitive and easier to understand.\n\nYou only need to quickly grasp the basic [core concepts](/en/manual/graph/graph) to get started with G6 quickly and achieve graph visualization without delay.\n\n**😰 The 4.0 Options** had a complex nested structure and was less semantically capable\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 The 5.0 Options** has a clear structure and is easy to understand\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 Brand New API Design\n\nG6 5.0 features a cleaner, easy-to-use API design that is more in line with modern front-end frameworks.\n\n## 🌲 Merging Graphs with Tree Graphs\n\nTree graphs are essentially a type of directed acyclic graph. G6 5.0 has integrated the design of graphs and tree graphs, reducing the cost of understanding and usage.\n\nNow, you can directly use `Graph` to instantiate and draw tree graphs in G6, without the need to use `TreeGraph`. You simply need to specify the layout as a tree graph layout.\n\nAdditionally, G6 provides the `treeToGraphData` utility method to help you quickly convert tree graph data into graph data.\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 Multi-Renderer Support\n\nG6 5.0 employs the next-generation @antv/g rendering engine, which has been newly designed. It offers support for multiple renderers such as `Canvas`, `SVG`, and `WebGL`. Additionally, it supports the mixed use of different renderers on layered canvases.\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other configurations\n  // Use the WebGL renderer\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 High-Performance Layouts\n\nG6 5.0 has adopted a brand-new layout engine, with some layouts implemented in Rust, providing higher performance for layout calculations. Additionally, there is support for WebGPU acceleration in certain layouts.\n\n> 🚀 To utilize high-performance layouts, you will need to install the `@antv/layout-wasm` package\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... Other Layout Configurations\n  },\n});\n```\n\n## 🎨 Multiple Themes Mechanism\n\nG6 5.0 comes with two built-in themes: light and dark, and allows for flexible customization based on the use case. For details, please refer to [Custom Theme](/en/manual/custom-extension/theme).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D Large Graphs\n\nG6 5.0 provides 3D rendering, layout, interaction capabilities, and can be used by import 3d elements, renderer, and behaviors from `@antv/g6-extension-3D` registration, see: [Using 3D](/manual/further-reading/3d).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 Plugin Optimization and Enhancement\n\nG6 5.0 has optimized and enhanced existing plugins, decoupling Graph from plugins, and providing richer capabilities while optimizing configurations.\n\nPlease visit [Plugin](/en/api/plugins/bubble-sets) to experience the capabilities of more plugins.\n\n## 💼 Optimized Package Size\n\nThanks to the well-modularized design and extension registration mechanism of G6 5.0, modules that are not used will not be packaged into the final build file, reducing the package size.\n\nCompared to 4.0, the UMD package size has been reduced from 1.8 MB to 0.96 MB, a reduction of nearly 50%.\n","packages/site/docs/manual/whats-new/feature.zh.md":"---\ntitle: 新版本特性\norder: 1\n---\n\n## 🏖️ 全新设计图配置范式\n\nG6 5.0 重新设计了图配置范式，在保证能力完善的基础上，优化配置项结构，更加直观、易于理解。\n\n仅需快速了解基本[核心概念](/manual/graph/graph)，即可快速上手 G6，快速实现图可视化。\n\n**😰 4.0 配置项** 嵌套结构复杂，语义化能力较弱\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 5.0 配置项** 结构清晰，易于理解\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 全新 API 设计\n\nG6 5.0 采用了更加简洁、易用的 API 设计，更加符合现代前端框架的设计风格。\n\n## 🌲 合并图与树图\n\n树图本质上是一种单向无环图，G6 5.0 融合了图与树图的设计，降低了理解和使用成本。\n\n现在，你可以在 G6 中直接使用 `Graph` 来实例化绘制树图，而不需要再使用 `TreeGraph`，仅需指定布局为树图布局即可。\n\n此外，G6 提供了 `treeToGraphData` 工具方法，帮助你快速将树图数据转换为图数据。\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 多渲染器支持\n\nG6 5.0 采用了新一代设计的 @antv/g 渲染引擎，提供了 `Canvas` `SVG` `WebGL` 多种渲染器支持，并且分层画布支持不同渲染器的混合使用。\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 WebGL 渲染器\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 高性能布局\n\nG6 5.0 采用了全新布局引擎，部分布局提供 Rust 实现，提供了更高性能的布局计算。另有布局支持 WebGPU 加速。\n\n> 🚀 高性能布局需要安装 `@antv/layout-wasm` 包\n\n```typescript\nimport { ForceAtlas2Layout, initThreads, supportsThreads } from '@antv/layout-wasm';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'forceatlas2-wasm', ForceAtlas2Layout);\n\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'forceatlas2-wasm',\n    threads,\n    // ... 其他布局配置\n  },\n});\n```\n\n> GPU 加速布局需要安装 `@antv/layout-gpu` 包\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他布局配置\n  },\n});\n```\n\n## 🎨 多主题机制\n\nG6 5.0 内置了亮色、暗色两套主题，并可基于使用场景进行灵活定制，具体可参考[自定义主题](/manual/theme/custom-theme)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D 大图\n\nG6 5.0 提供了 3D 大图渲染、布局、交互能力，从 `@antv/g6-extension-3d` 中引入 3D 元素、渲染器、交互等注册即可使用，详见：[使用 3D](/manual/further-reading/3d)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 插件优化增强\n\nG6 5.0 对现有插件进行了优化增强，解除了 Graph 与插件之间的耦合，并优化配置的同时提供了更加丰富了能力。\n\n敬请前往[插件](/manual/plugin/overview)体验更多插件的能力。\n\n## 💼 优化包体积\n\n得益于 G6 5.0 良好的模块化的设计以及扩展注册机制，对于未使用的模块，不会被打包到最终的构建文件中，减小了包体积。\n\n与 4.0 相比，UMD 包体积从 1.8 MB 减小到 0.96 MB，减小了近 50%。\n","packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md":"---\ntitle: Upgrade from 5.0 to 5.1 (Layout)\norder: 7\n---\n\nThis page focuses on layout documentation changes introduced in G6 `5.1`. Starting from `5.1`, layout pages prioritize the field naming aligned with `@antv/layout`; common `5.0` layout writeups are collected here for migration reference.\n\n## What Changed\n\n- Since `5.1`, layout docs prioritize shared `@antv/layout` fields such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`\n- Individual layout pages mainly keep the recommended `5.1` writeup\n- If you are migrating an existing `5.0` project, use this page to map old field names to the new documentation style\n\n## D3Force: center force to shortcut fields\n\nIn `5.0` documentation, the center force was commonly written inside `center`:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is the shortcut fields:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` maps to `centerX`\n- `center.y` maps to `centerY`\n- `center.strength` maps to `centerStrength`\n\nFor the full field description, see [D3Force Layout](/en/manual/layout/d3-force-layout).\n\n## ComboCombined: innerLayout / outerLayout to layout\n\nIn `5.0` documentation, the inner combo layout and the outer layout were commonly configured separately:\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is a single `layout` entry that returns different configurations for different levels based on `comboId`:\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- When `comboId` has a value, it refers to the layout inside a combo\n- When `comboId` is empty, it refers to the outermost layout\n- Multiple layout choices are unified under the `layout` entry\n\nFor the `5.1` recommended form, see [ComboCombined Layout](/en/manual/layout/combo-combined-layout).\n\n## Migration Suggestion\n\n1. Identify the matching layout type from your existing `5.0` project\n2. Map the old fields to the recommended `5.1` documentation style\n3. Return to the specific layout page to verify shared fields and defaults\n","packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md":"---\ntitle: 从 5.0 升级到 5.1（布局）\norder: 7\n---\n\n本文档聚焦 G6 `5.1` 中布局文档的写法调整。`5.1` 的布局页面会优先展示与 `@antv/layout` 对齐后的字段；`5.0` 中常见的布局写法统一收敛到本文档中，便于迁移时对照。\n\n## 总体变化\n\n- `5.1` 起，布局文档会优先展示 `@antv/layout` 的公共字段，例如 `width` `height` `center` `enableWorker` `node` `edge`\n- 各布局页主要保留 `5.1` 推荐写法，`5.0` 中常见写法请以本文档为准\n- 迁移时，建议先按旧项目中的字段定位，再映射到 `5.1` 文档里的推荐配置\n\n## D3Force：center force 改为快捷字段\n\n`5.0` 文档中，常见把中心力写在 `center` 中：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\n`5.1` 文档中推荐写成更直接的快捷字段：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` 对应 `centerX`\n- `center.y` 对应 `centerY`\n- `center.strength` 对应 `centerStrength`\n\n如果你需要继续对照完整字段说明，可查看 [D3Force 布局](/manual/layout/d3-force-layout)。\n\n## ComboCombined：innerLayout / outerLayout 收敛为 layout\n\n`5.0` 文档中，常见分别配置 Combo 内部布局和最外层布局：\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\n`5.1` 文档中推荐使用单个 `layout` 字段，根据 `comboId` 为不同层级返回布局配置：\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- `comboId` 有值时，表示当前为 Combo 内部层级\n- `comboId` 为空时，表示当前为最外层布局\n- 多层布局选择统一收敛到 `layout` 入口\n\n如果你需要查看 `5.1` 推荐写法，可查看 [ComboCombined 布局](/manual/layout/combo-combined-layout)。\n\n## 迁移建议\n\n1. 先按旧项目中的布局类型定位到本文档对应条目\n2. 再把 `5.0` 字段映射成 `5.1` 文档里的推荐写法\n3. 最后回到具体布局页，核对公共字段和默认值\n","packages/site/docs/manual/whats-new/upgrade.en.md":"---\ntitle: Upgrade To 5.0\norder: 6\n---\n\nThis document will guide you through the process of upgrading from G6 version `4.x` to `5.x`. If you are using version `3.x`, please upgrade to version `4.x` first.\n\n## Preparation Before Upgrade\n\n1. Please ensure that your current git branch is clean and there is no uncommitted code.\n2. Refer to the [Installation](./getting-started/installation) document to install version `5.x` and remove the dependencies for version `4.x`.\n\n## Start Upgrade\n\n### Data\n\nThe data format in the new version has changed as follows:\n\n1. All style attributes in `nodes`, `edges`, and `combos` need to be placed within `style`, and data attributes should be stored in `data`:\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // The label is a non-stylistic attribute, placed in the data, and can be accessed in the style mapping function\n    // The `size` is a stylistic attribute, placed within the `style`\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\nSince we have redesigned and implemented the elements, please refer to the corresponding documentation to modify the new element options:\n\n- [Node](/en/api/elements/nodes/base-node)\n- [Edge](/en/api/elements/edges/base-edge)\n- [Combo](/en/api/elements/combos/base-combo)\n\n2. If you need to specify the element type in the data, you can use the `type` attribute:\n\n```typescript\n{\n  nodes: [\n    // Specify the node type as rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### Options\n\n<Badge type=\"warning\">Change</Badge> **fitView / fitCenter / fitViewPadding**\n\n- The `fitView` and `fitCenter` options have been merged into `autoFit`.\n- To use `fitView`, you can configure it as `autoFit: 'view'`\n- To use `fitCenter`, you can configure it as `autoFit: 'center'`\n- You can also pass an object for full configuration:\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- The `fitViewPadding` has been changed to `padding`.\n\n<Badge type=\"error\">Removed</Badge> **linkCenter**\n\nIn version 5.x, the edge connection mechanism will attempt to connect to nodes/Combos in the following order:\n\n1. Connect Port\n2. Outline\n3. Center\n\n<Badge type=\"error\">Removed</Badge> **groupByTypes**\n\n<Badge type=\"error\">Removed</Badge> **autoPaint**\n\nPlease manually call the `render` or `draw` method to perform rendering.\n\n<Badge type=\"warning\">Changed</Badge> **modes**\n\nIn version 5.x, interaction modes have been removed. You can switch the currently enabled behaviors by setting `behaviors`.\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">Change</Badge> **defaultNode / defaultEdge / defaultCombo**\n\nThe element styles have been moved to `[element].style`, for example, `defaultNode` has been changed to `node.style`:\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\nElement state styles have been moved to `[element].state`, for example, `nodeStateStyles` has been changed to `node.stateStyles`:\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **animate / animateCfg**\n\n- The `animate` options has been changed to `animation`\n- `animate` and `animateCfg` have been merged into `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **minZoom / maxZoom**\n\n- The `minZoom` and `maxZoom` options have been merged into `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **renderer**\n\nG6 5.x supports multi-layer canvases and defaults to using the `canvas` renderer.\n\nThe `renderer` no longer supports the string type and has been changed to a callback function:\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **enabledStack / maxStep**\n\nThe built-in undo and redo functionality has been removed in version 5.x. For related capabilities, please use a plugin to implement.\n\n### API\n\n<Badge type=\"warning\">Change</Badge> **data / save / read / changeData**\n\nVersion 5.x offers a completely new data API. For details, see [Data API](/en/api/data).\n\n- The `data` and `changeData` methods from 4.x are replaced by `setData` in 5.x.\n- The `save` method from 4.x is replaced by `getData` in 5.x.\n- The `read` method from 4.x is replaced by `setData` + `render` in 5.x.\n\n<Badge type=\"warning\">Change</Badge> **get / set**\n\nTo access Graph options, please use `getOptions` or the `getXxx` API, such as `getZoomRange`, `getBehaviors`, etc. The `set` method is analogous.\n\n<Badge type=\"warning\">Change</Badge> **getContainer**\n\nDirect API to obtain the container is not currently supported, but you can obtain it through `graph.getCanvas().getContainer()`.\n\n> In most cases, you do not need to directly manipulate the container.\n\n<Badge type=\"error\">Removed</Badge> **getGroup**\n\n<Badge type=\"warning\">Change</Badge> **getMinZoom / getMaxZoom**\n\nUse `getZoomRange` to obtain the values.\n\n<Badge type=\"warning\">Change</Badge> **setMinZoom / setMaxZoom**\n\nUse the `setZoomRange` method to set the values.\n\n<Badge type=\"warning\">Change</Badge> **getWidth / getHeight**\n\nUse `getSize` to get the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **changeSize**\n\nUse `setSize` to set the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **zoom**\n\nChanged to `zoomBy`.\n\n<Badge type=\"warning\">Change</Badge> **translate**\n\nChanged to `translateBy`.\n\n<Badge type=\"warning\">Change</Badge> **moveTo**\n\nChanged to `translateTo`.\n\n<Badge type=\"warning\">Change</Badge> **focusItem**\n\nChanged to `focusElement`.\n\n<Badge type=\"error\">Removed</Badge> **addItem / updateItem / removeItem**\n\nTo add or remove elements, use the methods `addData` / `updateData` / `removeData` to manipulate data.\n\n<Badge type=\"error\">Removed</Badge> **refreshItem**\n\n<Badge type=\"error\">Removed</Badge> **refreshPositions**\n\n<Badge type=\"error\">Removed</Badge> **updateCombo**\n\n<Badge type=\"error\">Removed</Badge> **updateCombos**\n\n<Badge type=\"error\">Removed</Badge> **updateComboTree**\n\n<Badge type=\"warning\">Change</Badge> **node / edge / combo**\n\nUse the `setNode` / `setEdge` / `setCombo` methods as alternatives.\n\n<Badge type=\"warning\">Change</Badge> **showItem / hideItem**\n\nUse the `setElementVisibility` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **getNodes / getEdges / getCombos / getComboChildren / getNeighbors / find / findById / findAll / findAllByState**\n\nIn version 5.x, direct retrieval of element instances is not supported.\n\n- To obtain element data, use the methods `getData`, `getNodeData`, `getEdgeData`, `getComboData`, which support searching by element ID.\n- To obtain child node data, use the `getChildrenData` method.\n- To obtain neighbor node data, use the `getNeighborNodesData` method.\n- To find element data based on state, use the `getElementDataByState` method.\n\n<Badge type=\"warning\">Change</Badge> **collapseCombo / expandCombo**\n\nUse the `collapseElement` / `expandElement` methods as alternatives.\n\n<Badge type=\"error\">Removed</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">Removed</Badge> **createCombo**\n\nCombos can now be added using the `addData` / `addComboData` methods.\n\n<Badge type=\"error\">Removed</Badge> **uncombo**\n\nCombos can now be removed using the `removeData` / `removeComboData` methods.\n\n<Badge type=\"warning\">Change</Badge> **setItemState**\n\nUse the `setElementState` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **clearItemStates**\n\n- To clear all states of a single element: `graph.setElementState(id, [])`\n- To clear all states of multiple elements: `graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">Removed</Badge> **priorityState**\n\nWhen using `setElementState`, the state that appears later in the array has a higher priority.\n\n<Badge type=\"error\">Removed</Badge> **setMode**\n\nUse `setBehaviors` to set the current behaviors.\n\n<Badge type=\"error\">Removed</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">Change</Badge> **layout**\n\nDoes not support parameters. To configure the layout, please use `setLayout`.\n\n<Badge type=\"warning\">Change</Badge> **updateLayout**\n\nChanged to `setLayout`.\n\n<Badge type=\"error\">Removed</Badge> **destroyLayout**\n\n<Badge type=\"warning\">Change</Badge> **addBehaviors / removeBehaviors**\n\nReplaced with `setBehaviors`.\n\n<Badge type=\"error\">Removed</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- For multiple `Hull` instances, you need to configure multiple `hull` plugins in `plugins`, such as:\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- Operations to retrieve, update, and remove `Hull` are implemented through `setPlugins`, `updatePlugin`.\n\n<Badge>Not yet available</Badge> **getNodeDegree**\n\n<Badge>Not yet available</Badge> **getShortestPathMatrix**\n\n<Badge>Not yet available</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">Removed</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\nAll undo and redo related APIs should be called after obtaining the corresponding plugin, for example:\n\n```typescript\n// 'history' is the key configured for use with the plugin\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">Removed</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\nAnimation-related information is now emitted through events:\n\n- Animation start event: `beforeanimate`\n- Animation end event: `afteranimate`\n- To stop an animation:\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">Change</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x uses a different coordinate system than 4.x. For details, see [Coordinate](/en/manual/further-reading/coordinate).\n\n<Badge type=\"error\">Removed</Badge> **setTextWaterMarker / setImageWaterMarker**\n\nFor watermark functionality, please refer to the [Watermark](/en/api/plugins/watermark)plugin.\n\n<Badge type=\"warning\">Change</Badge> **toFullDataURL**\n\nReplaced with `toDataURL`, specify the parameter as: `mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">Removed</Badge> **downloadFullImage / downloadImage**\n\nOnly the capability to export as a `DataURL` is provided. If you need to download an image, please refer to the following example code:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **clear**\n\nUse `setData` + `draw` to clear data and the canvas.\n\n### Extension Registration\n\nUnlike G6 4.x, G6 5.x uses a unified extension registration function (register). You can refer to the [Extension Register](/en/manual/core-concept/extension#register-extension) to register G6 extensions.\n\nThe following G6 4.x registration functions have been deprecated:\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### Events\n\nCompared to G6 4.x, G6 5.x has the following differences in events:\n\n- The `mouse` and `touch` events have been removed and are unified under the `pointer` event.\n- The naming convention for lifecycle events is usually in the format of: `before/after` + `object/property` + `action`, for example: `beforeelementcreate` is triggered before an element is created.\n- The following events have been removed:\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- The following element change events have been removed, but you can still access them through `beforeelementupdate` and `afterelementupdate`:\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- The following events have been changed:\n  - The `graphstatechange` event has been changed to `beforeelementstatechange` / `afterelementstatechange`.\n  - The `viewportchange` event has been changed to `beforetransform` / `aftertransform`.\n\nFor a complete list of events, please refer to [Event](/en/api/reference/g6#event).\n","packages/site/docs/manual/whats-new/upgrade.zh.md":"---\ntitle: 升级到 5.0\norder: 6\n---\n\n本文档将引导你从 G6 `4.x` 版本升级到 `5.x` 版本。如果你使用的是 `3.x` 版本，请先升级到 `4.x` 版本。\n\n## 升级前准备\n\n1. 请确保当前 git 分支是干净的，没有未提交的代码。\n2. 参考 [安装](/manual/getting-started/installation) 文档安装 `5.x` 版本，并移除 `4.x` 版本依赖。\n\n## 开始升级\n\n### 数据\n\n新版本的数据格式有所变化，具体如下：\n\n1. `nodes` `edges` `combos` 中所有样式属性都需要放在 `style` 中，`data` 中存放数据属性：\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // label 为非样式属性，放在 data 中，可在样式映射函数中访问\n    // size 为样式属性，放在 style 中\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\n由于我们重新设计实现了元素，新的元素配置项请参考相应文档进行修改：\n\n- [Node](/manual/element/node/overview)\n- [Edge](/manual/element/edge/overview)\n- [Combo](/manual/element/combo/overview)\n\n2. 如果要在数据中指定元素类型，可以使用 `type` 属性：\n\n```typescript\n{\n  nodes: [\n    // 指定节点类型为 rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### 配置项\n\n<Badge type=\"warning\">变更</Badge> **fitView / fitCenter / fitViewPadding**\n\n- `fitView` 和 `fitCenter` 配置项已经合并为 `autoFit`\n- 若要使用 `fitView`，可以配置为 `autoFit: 'view'`\n- 若要使用 `fitCenter`，可以配置为 `autoFit: 'center'`\n- 也可以传入对象进行完整配置：\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- `fitViewPadding` 已变更为 `padding`\n\n<Badge type=\"error\">移除</Badge> **linkCenter**\n\n5.x 的边连接机制会按照如下顺序依次尝试连接到节点/Combo：\n\n1. 连接桩\n2. 轮廓\n3. 中心\n\n<Badge type=\"error\">移除</Badge> **groupByTypes**\n\n<Badge type=\"error\">移除</Badge> **autoPaint**\n\n请手动调用 `render` 或 `draw` 方法进行绘制。\n\n<Badge type=\"warning\">变更</Badge> **modes**\n\n5.x 已经移除交互模式，你可以通过设置 `behaviors` 来切换当前启用的交互行为。\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">变更</Badge> **defaultNode / defaultEdge / defaultCombo**\n\n元素样式已移至 `[element].style` 中，如 `defaultNode` 变更为 `node.style`：\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\n元素状态样式已移至 `[element].state` 中，如 `nodeStateStyles` 变更为 `node.stateStyles`：\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **animate / animateCfg**\n\n- `animate` 配置项已变更为 `animation`\n- `animate` 和 `animateCfg` 已合并为 `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **minZoom / maxZoom**\n\n`minZoom` 和 `maxZoom` 已合并为 `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **renderer**\n\nG6 5.x 支持多层画布，默认使用 `canvas` 渲染。\n\nrenderer 不再支持字符串类型，变更为回调函数：\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">移除</Badge> **enabledStack / maxStep**\n\n5.x 已移除内置撤销重做功能，相关能力请使用插件实现。\n\n### API\n\n<Badge type=\"warning\">变更</Badge> **data / save / read / changeData**\n\n5.x 提供了全新的数据 API，详见 [数据 API](/api/data)。\n\n- 4.x `data` `changeData` 方法使用 5.x `setData` 替代\n- 4.x `save` 方法使用 5.x `getData` 替代\n- 4.x `read` 方法使用 5.x `setData` + `render` 替代\n\n<Badge type=\"warning\">变更</Badge> **get / set**\n\n若要访问 Graph options，请使用 `getOptions` 或者 `getXxx` API，例如 `getZoomRange` `getBehaviors` 等。 `set` 同理。\n\n<Badge type=\"warning\">变更</Badge> **getContainer**\n\n暂不支持直接获取容器的 API，但可以通过 `graph.getCanvas().getContainer()` 获取。\n\n> 绝大部分情况下，你都不需要直接操作容器。\n\n<Badge type=\"error\">移除</Badge> **getGroup**\n\n<Badge type=\"warning\">变更</Badge> **getMinZoom / getMaxZoom**\n\n使用 `getZoomRange` 获取。\n\n<Badge type=\"warning\">变更</Badge> **setMinZoom / setMaxZoom**\n\n使用 `setZoomRange` 方法设置。\n\n<Badge type=\"warning\">变更</Badge> **getWidth / getHeight**\n\n使用 `getSize` 获取。\n\n<Badge type=\"warning\">变更</Badge> **changeSize**\n\n使用 `setSize` 设置。\n\n<Badge type=\"warning\">变更</Badge> **zoom**\n\n变更为 `zoomBy`。\n\n<Badge type=\"warning\">变更</Badge> **translate**\n\n变更为 `translateBy`。\n\n<Badge type=\"warning\">变更</Badge> **moveTo**\n\n变更为 `translateTo`。\n\n<Badge type=\"warning\">变更</Badge> **focusItem**\n\n变更为 `focusElement`。\n\n<Badge type=\"error\">移除</Badge> **addItem / updateItem / removeItem**\n\n通过 `addData` / `updateData` / `removeData` 方法操作数据来添加或删除元素。\n\n<Badge type=\"error\">移除</Badge> **refreshItem**\n\n<Badge type=\"error\">移除</Badge> **refreshPositions**\n\n<Badge type=\"error\">移除</Badge> **updateCombo**\n\n<Badge type=\"error\">移除</Badge> **updateCombos**\n\n<Badge type=\"error\">移除</Badge> **updateComboTree**\n\n<Badge type=\"warning\">变更</Badge> **node / edge / combo**\n\n使用 `setNode` / `setEdge` / `setCombo` 方法替代。\n\n<Badge type=\"warning\">变更</Badge> **showItem / hideItem**\n\n使用 `setElementVisibility` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **getNodes / getEdges / getCombos / getComboChildren /getNeighbors /find /findById / findAll /findAllByState**\n\n5.x 不支持直接获取元素实例。\n\n- 若要获取元素数据，使用 `getData` `getNodeData` `getEdgeData` `getComboData` 方法，支持传入元素 id 进行查找。\n- 获取子节点数据，使用 `getChildrenData` 方法。\n- 获取邻居节点数据，使用 `getNeighborNodesData` 方法。\n- 基于状态查找元素数据，使用 `getElementDataByState`。\n\n<Badge type=\"warning\">变更</Badge> **collapseCombo / expandCombo**\n\n使用 `collapseElement` / `expandElement` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">移除</Badge> **createCombo**\n\n通过 `addData` / `addComboData` 方法添加 Combo。\n\n<Badge type=\"error\">移除</Badge> **uncombo**\n\n通过 `removeData` / `removeComboData` 方法移除 Combo。\n\n<Badge type=\"warning\">变更</Badge> **setItemState**\n\n使用 `setElementState` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **clearItemStates**\n\n- 清除单个元素所有状态：`graph.setElementState(id, [])`\n- 清除多个元素所有状态：`graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">移除</Badge> **priorityState**\n\n`setElementState` 时状态数组中靠后的状态优先级更高。\n\n<Badge type=\"error\">移除</Badge> **setMode**\n\n使用 `setBehaviors` 来设置当前交互。\n\n<Badge type=\"error\">移除</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">变更</Badge> **layout**\n\n不支持参数，如需配置布局，请使用 `setLayout`。\n\n<Badge type=\"warning\">变更</Badge> **updateLayout**\n\n变更为 `setLayout`。\n\n<Badge type=\"error\">移除</Badge> **destroyLayout**\n\n<Badge type=\"warning\">变更</Badge> **addBehaviors / removeBehaviors**\n\n使用 `setBehaviors` 替代。\n\n<Badge type=\"error\">移除</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- 多个 `Hull` 需在 `plugins` 中配置多个 `hull` 插件，如：\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- `Hull` 的获取、更新、移除操作通过 `setPlugins`, `updatePlugin` 实现。\n\n<Badge>暂未提供</Badge> **getNodeDegree**\n\n<Badge>暂未提供</Badge> **getShortestPathMatrix**\n\n<Badge>暂未提供</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">移除</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\n所有撤销重做相关 API 请获取到对应插件后调用 API，例：\n\n```typescript\n// 'history' 为使用插件时配置的 key\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">移除</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\n动画相关信息通过事件抛出：\n\n- 动画开始事件：`beforeanimate`\n- 动画结束事件：`afteranimate`\n- 停止动画：\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">变更</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x 采用了与 4.x 不同的坐标系，详见 [坐标系](/manual/further-reading/coordinate)。\n\n<Badge type=\"error\">移除</Badge> **setTextWaterMarker / setImageWaterMarker**\n\n要使用水印功能，请参考 [水印](/manual/plugin/watermark)插件。\n\n<Badge type=\"warning\">变更</Badge> **toFullDataURL**\n\n使用 `toDataURL` 替代，指定参数为：`mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">移除</Badge> **downloadFullImage / downloadImage**\n\n仅提供导出为 `DataURL` 的能力，如需下载图片，请参考如下实例代码：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">移除</Badge> **clear**\n\n使用 `setData` + `draw` 清空数据和画布。\n\n### 扩展注册\n\n与 G6 4.x 不同，G6 5.x 使用的统一的扩展注册函数(register)，你可以参考 [注册扩展](/manual/graph/extension#注册扩展) 来注册 G6 扩展。\n\n下列 G6 4.x 的注册函数已经废除：\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### 事件\n\n与 G6 4.x 相比，G6 5.x 的事件但存下如下差异：\n\n- 移除了 `mouse` 和 `touch` 事件，统一使用 `pointer` 事件\n- 生命周期事件名命名格式通常为： `before/after` + `对象/属性` + `操作`，例如：`beforeelementcreate` 表示在创建元素前触发\n- 下列事件已被移除：\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- 下列元素变更事件被移除，但你仍可通过 `beforeelementupdate` 和 `afterelementupdate` 获取：\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- 下列事件有所变更：\n  - graphstatechange 事件变更为 beforeelementstatechange / afterelementstatechange\n  - viewportchange 事件变更为 beforetransform / aftertransform\n\n完整的事件列表请参考 [事件](/api/event)。\n"},"files":{".cursor/rules/translation.mdc":"---\ndescription: 翻译\nglobs:\nalwaysApply: false\n---\n# Translation Guidelines for site/docs\n\nWhen translating files under the `site/docs` directory, please adhere to the following guidelines:\n\n1. **Consistency in Terminology**: Ensure that terminology is consistent throughout the document. Use a glossary if available to maintain uniformity in terms.\n\n   **Glossary**:\n\n   - 画布 (Canvas)\n   - 元素 (Element)\n   - 节点 (Node)\n   - 边 (Edge)\n   - 组合 (Combo)\n   - 交互 (Behavior)\n   - 布局 (Layout)\n   - 插件 (Plugin)\n   - 动画 (Animation)\n   - 数据处理 (Transform)\n   - 色板 (Palette)\n   - 配置项 (Option)\n   - 图数据 (Graph Data)\n   - 树图 (Tree Graph)\n   - 属性 (Property)\n   - 描述 (Description)\n   - 类型 (Type)\n   - 默认值 (Default Value)\n   - 必选 (Required)\n\n2. **Adjust Hyperlinks**: Review and adjust hyperlinks to ensure they point to the correct translated sections or documents. Verify that all links are functional and correctly formatted.\n\n   - **Internal Links**: In the English version, all internal links should have a `/en` prefix, while the Chinese version should not have any prefix. Ensure this prefix is added to all internal links in English documents to avoid any oversight.\n   - **Anchor Points**: For anchor points following a `#`, if they contain Chinese characters, they should be adjusted to match the corresponding title in the English version rather than being directly translated.\n   - **External Links**: Convert external links appropriately to ensure they align with the language and context of the document.\n\n3. **Direct Writing to Translated Documents**: Translations should be stored in corresponding `.en.md` or `.zh.md` files within the same directory. Ensure that the translated content is placed in the correct location within the document.\n\n   - When translating from Chinese to English, create or update the `.en.md` file in the same directory.\n   - When translating from English to Chinese, create or update the `.zh.md` file in the same directory.\n\n4. **Support for Partial Content Translation**: Allow for the selection and translation of specific sections of content. Translated sections should be inserted into the appropriate location within the document, maintaining the logical flow and structure.\n\n   - **Full Document Translation**: If the entire document is selected for translation, replace the entire content with the translated version.\n   - **Partial Content Translation**: If only specific sections are selected, find the appropriate place to replace or insert the translated content, ensuring the document's logical flow and structure are maintained.\n\n5. **Contextual Translation**: Avoid literal translations. Ensure that the translation fits the English context and conveys the intended meaning accurately.\n\n6. **Direct Modification**: Translations should be directly modified in the corresponding `.en.md` or `.zh.md` files without returning the translated content separately. Ensure that the changes are saved in the correct file and location.\n\n7. **Preserve Metadata Order**: Do not modify the `order` attribute in the page metadata during translation. This ensures that the document order remains consistent across different language versions.\n\n8. **Add '/en' Prefix to Internal Links**: Ensure that all internal links in English documentation have the '/en' prefix to maintain consistency and correct navigation.\n\nBy following these guidelines, translations will be more accurate and consistent, facilitating easier review and integration into the documentation.\n","packages/cli/README.md":"# @antv/g6-cli\n\n`@antv/g6-cli` is a G6 template generation tool that comes with several templates.\n\nCurrently, it owns a built-in template called `extension`. This template handles the boilerplate setup, which encompasses a seamless local development environment, linting, code formatting, Jest for snapshot testing and bundling with Rollup etc.\n\n`@antv/g6-cli` i\n\n## Getting Started\n\nTo start using `@antv/g6-cli`, you'll first need to install it globally.\n\n```bash\nnpm i @antv/g6-cli -g\n```\n\nOnce installed, you can easily scaffold a new project:\n\n```bash\ncreate-g6\n```\n\nThen follow the prompts!\n\n![prompts](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*09BKQrIcZUMAAAAAAAAAAAAADmJ7AQ/original)\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a **G6 Extension** project, run:\n\n```bash\ncreate-g6 g6-extension-test --template extension\n```\n","packages/g6-extension-3d/README.md":"## 3D extension for G6\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*lEL3TrCLnPsAAAAAAAAAAAAADmJ7AQ/original\" />\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yFa5RKilu6kAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension package provides 3D elements, behaviors and plugins for G6.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-3d\n```\n\n2. Import and Register\n\n> Where renderer, elements and lighting are necessary\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { DragCanvas3D, Light, Line3D, Sphere, renderer } from '@antv/g6-extension-3d';\n\n// 3d light plugin\nregister(ExtensionCategory.PLUGIN, '3d-light', Light);\n// sphere node element\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\n// line edge element\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\n// drag canvas in 3d scene\nregister(ExtensionCategory.BEHAVIOR, 'drag-canvas-3d', DragCanvas3D);\n// camera setting plugin\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting);\n```\n\n3. Use\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  renderer, // use 3d renderer\n  data: {\n    // your data\n  },\n  node: {\n    type: 'sphere', // use sphere node\n  },\n  edge: {\n    type: 'line3d', // use 3d line edge\n  },\n  behaviors: ['drag-canvas-3d'],\n  plugins: [\n    // set camera configs, see: https://g.antv.antgroup.com/en/api/camera/intro\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n    // add directional light\n    {\n      type: '3d-light',\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n```\n\n## Resources\n\n- [Lite Solar System](https://g6.antv.antgroup.com/en/examples/feature/default/#lite-solar-system)\n- [3D Node](https://g6.antv.antgroup.com/en/examples/element/node/#3d-node)\n","packages/g6-extension-react/README.md":"## React extension for G6\n\n<img width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rWSiT6dnwfcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension allows you to define G6 node by React component and JSX syntax.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-react\n```\n\n2. Import and Register\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n```\n\n3. Define Node\n\nReact Node:\n\n```jsx\nconst ReactNode = () => {\n  return <div>node</div>;\n};\n```\n\nG Node:\n\n```jsx\nimport { Group, Rect, Text } from '@antv/g6-extension-react';\n\nconst GNode = () => {\n  return <Group>\n    <Rect width={100} height={100}></Rect>\n    <Text text={\"node\"} />\n  <Group>\n};\n```\n\n4. Use\n\nUse ReactNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'react',\n    style: {\n      component: () => <ReactNode />,\n    },\n  },\n});\n```\n\nUse GNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'g',\n    style: {\n      component: () => <GNode />,\n    },\n  },\n});\n```\n\n## Q&A\n\n1. Difference between ReactNode and GNode\n\nReactNode is a React component, while GNode support jsx syntax but can only use G tag node.\n\n## Resources\n\n- [React node](https://g6.antv.antgroup.com/examples/element/custom-node/#react-node)\n- [G node with JSX syntax](https://g6.antv.antgroup.com/en/examples/element/custom-node/#react-g)\n","packages/g6-ssr/README.md":"## SSR extension for G6 5.0\n\nThis extension package provides SSR support for G6 5.0, which supports canvas rendering in server side.\n\n## Usage\n\n### Install\n\n```bash\nnpm install @antv/g6-ssr\n```\n\n### Render in JavaScript API\n\n> For complete options, please refer to [G6 Graph Options](https://g6.antv.antgroup.com/api/graph/option)\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  imageType: 'png', // or 'jpeg'\n  data: {\n    // data\n  },\n  // other options\n});\n\ngraph.exportToFile('image');\n// -> image.png\n\ngraph.toBuffer();\n// -> get buffer\n```\n\n### Render in CLI\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./image\n```\n\n### Export SVG / PDF\n\nWhen render in JavaScript API, you can pass `outputType` option to export SVG or PDF.\n\n```js\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  data: {\n    // data\n  },\n  outputType: 'svg', // or 'pdf'\n  // other options\n});\n```\n\nWhen render in CLI, you can pass `-t` or `--type` option to export SVG or PDF.\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./file -t pdf\n```\n\n### Register Custom G6 Extensions\n\nIf you need to register custom extensions of G6, please use the `registry` function exported from `@antv/g6-ssr`.\n\n```js\nimport { createGraph, registry } from '@antv/g6-ssr';\nimport { BaseNode, ExtensionCategory } from '@antv/g6';\n\nclass CustomNode extends BaseNode {\n  // custom node\n}\n\nregistry(ExtensionCategory.Node, 'custom-node', CustomNode);\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  node: {\n    type: 'custom-node',\n    // other options\n  },\n  // other options\n});\n```\n\n### Use Plugins\n\nWhen using G6-SSR, you can also use G render plugins. Here's how to use plugins in server-side rendering:\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\nimport { Plugin as RoughCanvasPlugin } from '@antv/g-plugin-rough-canvas-renderer';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  renderPlugins: [new RoughCanvasPlugin()],\n  data: {\n    // data\n  },\n});\n```\n\n## License\n\nMIT\n","packages/g6/src/plugins/hull/hull/README.md":"> Code copied from [hull-js](https://github.com/hull/hull-js), and fix the issue [[Bug]: hull.js Code Injection Vulnerability #6605](https://github.com/antvis/G6/issues/6605).\n","packages/site/docs/api/behavior.en.md":"---\ntitle: Behavior\norder: 8\n---\n\n## Overview of Behavior\n\nBehavior is a core building block of G6, precisely defining the interaction between users and the graph. Each Behavior plugin is a highly encapsulated functional unit, integrating event listening, state management, and response handling logic for specific scenarios.\n\nG6's built-in Behaviors cover most common interaction needs and provide a flexible extension mechanism, allowing developers to create customized interaction experiences based on business scenarios. For a complete list of behavior types, configuration options, and development examples, please refer to the [Behavior Overview](/en/manual/behavior/overview) section.\n\n## API Reference\n\n### Graph.getBehaviors()\n\nGet all configured behaviors in the current graph.\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**Return Value**\n\n- **Type**: [BehaviorOptions](#behavioroptions)\n- **Description**: All configured behaviors in the current graph\n\n**Example**\n\n```typescript\n// Get all current behaviors\nconst behaviors = graph.getBehaviors();\nconsole.log('Current graph behaviors:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\nSet the behaviors of the graph, replacing all existing behaviors.\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                    | Type                                                                              | Default | Required |\n| --------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------- | -------- |\n| behaviors | New behavior configuration, or a function returning new configuration based on the current one | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -       | ✓        |\n\n**Note**\n\nThe set behaviors will completely replace the original ones. To add new behaviors, you can use functional updates:\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**Example 1**: Set basic behaviors\n\n```typescript\n// Set basic behaviors\ngraph.setBehaviors([\n  'drag-canvas', // Drag canvas\n  'zoom-canvas', // Zoom canvas\n  'drag-element', // Drag element\n]);\n```\n\n**Example 2**: Set behaviors with configuration\n\n```typescript\ngraph.setBehaviors([\n  // String form (using default configuration)\n  'drag-canvas',\n\n  // Object form (custom configuration)\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // Specify a unique identifier for subsequent updates\n    sensitivity: 1.5, // Zoom sensitivity\n  },\n\n  // Enable drag only on nodes\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // Enable drag only on nodes\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new behavior\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// Replace specific behavior\ngraph.setBehaviors((currentBehaviors) => {\n  // Filter out existing zoom behaviors\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // Add new zoom behavior configuration\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\nUpdate the configuration of a specific behavior, identified by the `key`.\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                             | Type                                          | Default | Required |\n| --------- | --------------------------------------- | --------------------------------------------- | ------- | -------- |\n| behavior  | Configuration of the behavior to update | [UpdateBehaviorOption](#updatebehavioroption) | -       | ✓        |\n\n**Note**\n\nTo update a behavior, the original behavior configuration must specify the `key` field to accurately locate and update the behavior.\n\n**Example 1**: Update behavior configuration\n\n```typescript\n// Specify key when initially setting behaviors\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// Update behavior configuration\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // Specify the behavior to update\n  sensitivity: 2.0, // New zoom sensitivity\n  enableOptimize: true, // Add new configuration\n});\n```\n\n**Example 2**: Disable/Enable behavior\n\n```typescript\n// Set behaviors with keys\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// Disable drag functionality\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// Re-enable later\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## Type Definitions\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // Interaction type\n  type: string;\n\n  // Interaction key, a unique identifier for identifying and further operating this interaction\n  key?: string;\n\n  // There may be other configuration items for different types of interactions\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // Unique identifier of the behavior to update\n  key: string;\n\n  // Other configuration items to update\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/behavior.zh.md":"---\ntitle: 交互\norder: 8\n---\n\n## 交互概述\n\n交互（Behavior）是 G6 的核心构建模块，它精确定义了用户与图之间的互动行为。每个 Behavior 插件都是一个高度封装的功能单元，内部集成了特定场景下的事件监听、状态管理和响应处理逻辑。\n\nG6 的内置 Behavior 涵盖了大多数常见交互需求，同时提供了灵活的扩展机制，支持开发者根据业务场景构建定制化交互体验。\n有关完整的交互行为类型、配置选项及开发示例，请参阅 [交互总览](/manual/behavior/overview) 章节。\n\n## API 参考\n\n### Graph.getBehaviors()\n\n获取当前图表中所有已配置的交互行为。\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**返回值**\n\n- **类型**: [BehaviorOptions](#behavioroptions)\n- **描述**: 当前图表中已配置的所有交互行为\n\n**示例**\n\n```typescript\n// 获取当前所有交互行为\nconst behaviors = graph.getBehaviors();\nconsole.log('当前图表的交互行为:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\n设置图表的交互行为，将替换所有现有的交互行为。\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**参数**\n\n| 参数      | 描述                                                 | 类型                                                                              | 默认值 | 必选 |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | ------ | ---- |\n| behaviors | 新的交互行为配置，或一个基于当前配置返回新配置的函数 | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -      | ✓    |\n\n**说明**\n\n设置的交互会全量替换原有的交互，如果需要新增交互可以使用函数式更新：\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**示例 1**: 设置基本交互\n\n```typescript\n// 设置基本交互\ngraph.setBehaviors([\n  'drag-canvas', // 拖拽画布\n  'zoom-canvas', // 缩放画布\n  'drag-element', // 拖拽元素\n]);\n```\n\n**示例 2**: 设置带配置的交互\n\n```typescript\ngraph.setBehaviors([\n  // 字符串形式（使用默认配置）\n  'drag-canvas',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // 指定唯一标识，用于后续更新\n    sensitivity: 1.5, // 缩放灵敏度\n  },\n\n  // 只有节点上启用拖拽\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // 仅在节点上启用拖拽\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的交互行为\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// 替换特定交互行为\ngraph.setBehaviors((currentBehaviors) => {\n  // 过滤掉现有的缩放交互\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // 添加新的缩放交互配置\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\n更新指定的交互行为配置，需要通过 `key` 标识要更新的交互。\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**参数**\n\n| 参数     | 描述               | 类型                                          | 默认值 | 必选 |\n| -------- | ------------------ | --------------------------------------------- | ------ | ---- |\n| behavior | 更新的交互行为配置 | [UpdateBehaviorOption](#updatebehavioroption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个交互，必须在原始交互配置中指定 `key` 字段，以便能够准确找到并更新该交互。\n\n**示例 1**: 更新交互配置\n\n```typescript\n// 初始设置交互时指定 key\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// 更新交互配置\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // 指定要更新的交互\n  sensitivity: 2.0, // 新的缩放灵敏度\n  enableOptimize: true, // 添加新配置\n});\n```\n\n**示例 2**: 禁用/启用交互\n\n```typescript\n// 设置带 key 的行为\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// 禁用拖拽功能\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// 稍后重新启用\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## 类型定义\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // 交互类型\n  type: string;\n\n  // 交互 key，即唯一标识，用于标识交互，从而进一步操作此交互\n  key?: string;\n\n  // 针对不同类型的交互，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // 要更新的交互的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/canvas.en.md":"---\ntitle: Canvas Operations\norder: 1\n---\n\n## Overview of Canvas Operations\n\nG6 provides a series of canvas operation APIs to control and obtain basic information about the canvas. With these APIs, you can:\n\n- Get the canvas instance\n- Get and set the canvas size\n- Operate the canvas renderer and layers\n\n## API Reference\n\n### Graph.getCanvas()\n\nGet the canvas instance, which can be used for low-level canvas operations.\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**Return Value Description**\n\nThe Canvas instance includes the following main functions:\n\n- `getLayer(name?: string)`: Get the specified layer\n- `getLayers()`: Get all layers\n- `getCamera()`: Get the camera instance\n- `getRoot()`: Get the root node\n- `setCursor(cursor: string)`: Set the mouse cursor style\n\n**Example**\n\n```typescript\n// Get the canvas instance\nconst canvas = graph.getCanvas();\n\n// Get the main layer\nconst mainLayer = canvas.getLayer('main');\n\n// Set the mouse cursor style\ncanvas.setCursor('pointer');\n\n// Get the root node of the canvas\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\nGet the size of the current canvas container. Returns an array containing the width and height.\n\n```typescript\ngetSize(): [number, number];\n```\n\n**Example**\n\n```typescript\n// Get the canvas size\nconst [width, height] = graph.getSize();\nconsole.log('Canvas width:', width);\nconsole.log('Canvas height:', height);\n\n// Use the size information for calculations\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\nSet the size of the canvas container. This method will update both the canvas and container size.\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description            | Type   | Default | Required |\n| --------- | ---------------------- | ------ | ------- | -------- |\n| width     | Canvas width (pixels)  | number | -       | ✓        |\n| height    | Canvas height (pixels) | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set a fixed size\ngraph.setSize(800, 600);\n```\n","packages/site/docs/api/canvas.zh.md":"---\ntitle: 画布操作\norder: 1\n---\n\n## 画布操作概述\n\nG6 提供了一系列画布操作 API，用于控制和获取画布的基本信息。通过这些 API，你可以：\n\n- 获取画布实例\n- 获取和设置画布尺寸\n- 操作画布渲染器和图层\n\n## API 参考\n\n### Graph.getCanvas()\n\n获取画布实例，返回的实例可用于进行底层的画布操作。\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**返回值类型说明**\n\nCanvas 实例包含以下主要功能：\n\n- `getLayer(name?: string)`: 获取指定图层\n- `getLayers()`: 获取所有图层\n- `getCamera()`: 获取相机实例\n- `getRoot()`: 获取根节点\n- `setCursor(cursor: string)`: 设置鼠标样式\n\n**示例**\n\n```typescript\n// 获取画布实例\nconst canvas = graph.getCanvas();\n\n// 获取主图层\nconst mainLayer = canvas.getLayer('main');\n\n// 设置鼠标样式\ncanvas.setCursor('pointer');\n\n// 获取画布根节点\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\n获取当前画布容器的尺寸。返回一个包含宽度和高度的数组。\n\n```typescript\ngetSize(): [number, number];\n```\n\n**示例**\n\n```typescript\n// 获取画布尺寸\nconst [width, height] = graph.getSize();\nconsole.log('画布宽度:', width);\nconsole.log('画布高度:', height);\n\n// 使用尺寸信息进行计算\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\n设置画布容器的尺寸。这个方法会同时更新画布和容器的大小。\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述             | 类型   | 默认值 | 必选 |\n| ------ | ---------------- | ------ | ------ | ---- |\n| width  | 画布宽度（像素） | number | -      | ✓    |\n| height | 画布高度（像素） | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置固定尺寸\ngraph.setSize(800, 600);\n```\n","packages/site/docs/api/coordinate.en.md":"---\ntitle: Coordinate Transformation\norder: 12\n---\n\n## Overview of Coordinate Systems\n\nUnderstanding different coordinate systems and their transformations is crucial in graph visualization. G6 involves multiple coordinate systems, each used for different scenarios:\n\n- **Client Coordinate System**: Origin is at the top-left corner of the browser viewport, measured in pixels. Typically used for handling browser events.\n- **Screen Coordinate System**: Origin is at the top-left corner of the screen, affected by page scrolling.\n- **Page Coordinate System**: Origin is at the top-left corner of the document, considering document scrolling.\n- **Canvas Coordinate System**: Also known as the world coordinate system, used for drawing and layout, with the origin at the top-left corner of the canvas element.\n- **Viewport Coordinate System**: The visible area of the canvas, with the origin at the top-left corner of the viewport. The viewport can be panned and zoomed to view different areas of the Canvas.\n\nIn this [example](https://g.antv.antgroup.com/en/examples/canvas/canvas-basic#coordinates), moving the mouse shows the position in various coordinate systems:\n\n![Coordinate System Diagram](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\nWhen the canvas is not panned or zoomed, the Viewport and Canvas coordinate systems coincide. With user interactions like dragging or zooming, the two systems may shift.\n\nG6 provides a series of APIs for converting between different coordinate systems, detailed below.\n\n## API Reference\n\n### Graph.getCanvasByClient(point)\n\nConvert browser coordinates (client coordinates) to canvas coordinates.\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description              | Type                                         | Default | Required |\n| --------- | ------------------------ | -------------------------------------------- | ------- | -------- |\n| point     | Browser coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getCanvasByViewport(point)\n\nConvert viewport coordinates to canvas coordinates.\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                         | Default | Required |\n| --------- | ------------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Viewport coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getClientByCanvas(point)\n\nConvert canvas coordinates to browser client coordinates.\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the browser client coordinate system\n\n### Graph.getViewportByCanvas(point)\n\nConvert canvas coordinates to viewport coordinates.\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the viewport coordinate system\n","packages/site/docs/api/coordinate.zh.md":"---\ntitle: 坐标转换\norder: 12\n---\n\n## 坐标系概述\n\n在图可视化中，理解不同的坐标系及其转换关系至关重要。G6 中涉及多种坐标系，它们各自用于不同的场景：\n\n- **Client 坐标系**：浏览器视口左上角为原点，单位为像素。通常用于处理浏览器事件。\n- **Screen 坐标系**：屏幕左上角为原点，会受页面滚动影响。\n- **Page 坐标系**：文档左上角为原点，考虑文档滚动。\n- **Canvas 坐标系**：也称为世界坐标系，图形绘制和布局时使用的坐标系，画布元素左上角为原点。\n- **Viewport 坐标系**：视口坐标系，当前可见的画布区域，视口左上角为原点。视口通过平移、缩放等操作，可以观察不同的 Canvas 区域。\n\n在这个[示例](https://g.antv.antgroup.com/zh/examples/canvas/canvas-basic#coordinates)中，移动鼠标可以看到鼠标所在位置在各个坐标系下的值：\n\n![坐标系关系图](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\n当画布没有发生平移和缩放时，Viewport 坐标系与 Canvas 坐标系重合。随着用户的交互（如拖拽画布、缩放），两个坐标系会出现偏移。\n\nG6 提供了一系列 API 用于在不同坐标系之间进行转换，下面将详细介绍这些 API。\n\n## API 参考\n\n### Graph.getCanvasByClient(point)\n\n将浏览器坐标（客户端坐标）转换为画布坐标。\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述         | 类型                                         | 默认值 | 必选 |\n| ----- | ------------ | -------------------------------------------- | ------ | ---- |\n| point | 浏览器坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getCanvasByViewport(point)\n\n将视口坐标转换为画布坐标。\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 视口坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getClientByCanvas(point)\n\n将画布坐标转换为浏览器客户端坐标。\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 浏览器客户端坐标系下的坐标点\n\n### Graph.getViewportByCanvas(point)\n\n将画布坐标转换为视口坐标。\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 视口坐标系下的坐标点\n","packages/site/docs/api/data.en.md":"---\ntitle: Data\norder: 0\n---\n\n## Overview of Data Operations\n\nG6 provides a comprehensive [data](/en/manual/data) operation API, covering the complete lifecycle of graph data from query, modification to update.\n\n## API Reference\n\n### Graph.getData()\n\nGet the complete data of the graph.\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**Return Value**:\n\n- **Type**: [GraphData](#graphdata)\n\n- **Description**: Returns the complete graph data containing all nodes, edges, and combo data\n\n**Example**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('Node data:', graphData.nodes);\nconsole.log('Edge data:', graphData.edges);\nconsole.log('Combo data:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\nGet node data, supporting three calling methods.\n\n```typescript\n// Get all node data\ngetNodeData(): NodeData[];\n\n// Get single node data\ngetNodeData(id: ID): NodeData;\n\n// Get multiple node data\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Node ID       | string   | -       |          |\n| ids       | Node ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **Description**: Returns the specified node data or node data array\n\n**Example**:\n\n```typescript\n// Get all nodes\nconst nodes = graph.getNodeData();\n\n// Get single node\nconst node = graph.getNodeData('node1');\nconsole.log('Node position:', node.style.x, node.style.y);\n\n// Get multiple nodes\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\nGet edge data, supporting three calling methods.\n\n```typescript\n// Get all edge data\ngetEdgeData(): EdgeData[];\n\n// Get single edge data\ngetEdgeData(id: ID): EdgeData;\n\n// Get multiple edge data\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Edge ID       | string   | -       |          |\n| ids       | Edge ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **Description**: Returns the specified edge data or edge data array\n\n**Example**:\n\n```typescript\n// Get all edges\nconst edges = graph.getEdgeData();\n\n// Get single edge\nconst edge = graph.getEdgeData('edge1');\nconsole.log('Edge source and target:', edge.source, edge.target);\n\n// Get multiple edges\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\nGet combo data, supporting three calling methods.\n\n```typescript\n// Get all combo data\ngetComboData(): ComboData[];\n\n// Get single combo data\ngetComboData(id: ID): ComboData;\n\n// Get multiple combo data\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter | Description    | Type     | Default | Required |\n| --------- | -------------- | -------- | ------- | -------- |\n| id        | Combo ID       | string   | -       |          |\n| ids       | Combo ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **Description**: Returns the specified combo data or combo data array\n\n**Example**:\n\n```typescript\n// Get all combos\nconst combos = graph.getComboData();\n\n// Get single combo\nconst combo = graph.getComboData('combo1');\nconsole.log('Nodes in combo:', combo.children);\n\n// Get multiple combos\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\nGet single element data, supporting two calling methods.\n\n⚠️ **Note**: This API directly gets the data of the element without considering the element type.\n\n```typescript\n// Get single element data\ngetElementData(id: ID): ElementDatum;\n\n// Get multiple element data\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type     | Default | Required |\n| --------- | ---------------- | -------- | ------- | -------- |\n| id        | Element ID       | string   | -       |          |\n| ids       | Element ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: ElementDatum \\| ElementDatum[]\n- **Description**: Directly gets the data of the element without considering the element type\n\n**Example**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('Element data:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('Multiple element data:', elements);\n```\n\n### Graph.getElementDataByState()\n\nGet element data in a specified state, supporting three calling methods.\n\n```typescript\n// Get node data in a specified state\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// Get edge data in a specified state\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// Get combo data in a specified state\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter   | Description  | Type                              | Default | Required |\n| ----------- | ------------ | --------------------------------- | ------- | -------- |\n| elementType | Element type | `'node'` \\| `'edge'` \\| `'combo'` | -       | ✓        |\n| state       | State        | string                            | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **Description**: Returns node data, edge data, or combo data in the specified state\n\n**Example**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('Selected nodes:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('Selected edges:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('Selected combos:', selectedCombos);\n```\n\n**Built-in States**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\nGet the data of neighbor nodes of a node or combo.\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[]\n- **Description**: Returns neighbor node data\n\n**Example**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('Neighbor nodes:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\nGet the data of edges related to a node or combo.\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type                          | Default | Required |\n| --------- | ---------------- | ----------------------------- | ------- | -------- |\n| id        | Node or combo ID | string                        | -       | ✓        |\n| direction | Edge direction   | `'in'` \\| `'out'` \\| `'both'` | -       |          |\n\n**Return Value**:\n\n- **Type**: EdgeData[]\n- **Description**: Returns the data of edges related to the specified node or combo\n\n**Example**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('Related edges:', relatedEdges);\n```\n\n### Graph.getParentData()\n\nGet the data of the parent element of a node or combo.\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       |          |\n\n**Return Value**:\n\n- **Type**: NodeData \\| ComboData \\| undefined\n- **Description**: Returns the parent element data, or undefined if it does not exist\n\n**Example**:\n\n```typescript\n// Get the parent node in a tree graph\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// Get the parent combo in a combo\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\nGet the data of child elements of a node or combo.\n\n```typescript\ngetChildrenData(id: ID): (NodeData \\| ComboData)[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: (NodeData \\| ComboData)[]\n- **Description**: Returns an array of child element data\n\n**Note**:\n\n- **Querying combo's child elements**: If the id corresponds to a combo element, you can directly use this API to get all its child elements.\n- **Querying node's child elements**: If the id corresponds to a node, only when the graph data is a tree structure (i.e., the node data maintains a `children` field, and `children` is an array of child node IDs for that node), can you use this API to get the child elements of that node. Otherwise, an empty array is returned.\n\n**Example**:\n\n```typescript\n// Get the child elements of a combo\nconst children = graph.getChildrenData('combo1');\nconsole.log('Number of child nodes:', children.length);\n\n// Process each child element\nchildren.forEach((child) => {\n  console.log('Child element ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\nGet the data of all ancestor elements of a node or combo.\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of ancestor element data, ordered from parent to root\n\n**Example**:\n\n```typescript\n// Get all ancestor nodes in a tree graph\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  'Ancestor node path:',\n  treeAncestors.map((node) => node.id),\n);\n\n// Get all parent combos in a combo\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\nGet the data of all descendant elements of a node or combo.\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of descendant element data\n\n**Example**:\n\n```typescript\n// Get all descendants of a node\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('Number of descendants:', descendants.length);\n\n// Process all descendant elements\ndescendants.forEach((descendant) => {\n  console.log('Descendant element ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\nSet the complete data of the graph.\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                        | Default | Required |\n| --------- | ----------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | New graph data or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Directly set data\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// Use functional incremental update: get current graph data and return new graph data\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\nAdd new element data.\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                              | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Graph data to add or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\nAdd new node data.\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Node data to add or a function returning node data | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single node\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: 'Node 1' },\n  },\n]);\n\n// Add multiple nodes\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// Functional addition\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\nAdd new edge data.\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                          | Default | Required |\n| --------- | -------------------------------------------------- | ------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to add or a function returning edge data | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single edge\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: 'Relation',\n    },\n  },\n]);\n\n// Add multiple edges\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// Functional addition\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\nAdd new combo data.\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                          | Type                                                            | Default | Required |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to add or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\nAdd child node data to a tree graph node.\n\n⚠️ **Note**: Use addNodeData / addComboData methods to add child nodes to a combo.\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**Parameters**:\n\n| Parameter    | Description     | Type                    | Default | Required |\n| ------------ | --------------- | ----------------------- | ------- | -------- |\n| parentId     | Parent node ID  | string                  | -       | ✓        |\n| childrenData | Child node data | [NodeData](#nodedata)[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\nRemove element data.\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                               | Type                                               | Default | Required |\n| --------- | --------------------------------------------------------- | -------------------------------------------------- | ------- | -------- |\n| ids       | Element IDs to remove or a function returning element IDs | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\nRemove node data.\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Node IDs to remove or a function returning node IDs | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\nRemove edge data.\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Edge IDs to remove or a function returning edge IDs | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\nRemove combo data.\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                            | Default | Required |\n| --------- | ----------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Combo IDs to remove or a function returning combo IDs | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\nUpdate element data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                 | Type                                                                             | Default | Required |\n| --------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Element data to update or a function returning element data | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\nUpdate node data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                           | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------- | ------- | -------- |\n| data      | Node data to update or a function returning node data | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\nUpdate edge data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                                                                                         | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to update or a function returning edge data | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\nUpdate combo data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                             | Type                                                            | Default | Required |\n| --------- | ------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to update or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\nDetermine if an node exists\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n| Parameter | Description | Type | Default | Required |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id | Node ID to be judged | [ID](#id) | - | ✓ |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\nDetermine if an edge exists\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description          | Type      | Default | Required |\n| --------- | -------------------- | --------- | ------- | -------- |\n| id        | Edge ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\nDetermine if combo exists\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description           | Type      | Default | Required |\n| --------- | --------------------- | --------- | ------- | -------- |\n| id        | Combo ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## Type Definitions\n\n### ID\n\nElement ID type.\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\nMultiple element ID type.\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 graph data type.\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\nNode data type.\n\n```typescript\ninterface NodeData {\n  id: string; // Node ID\n  type?: string; // Node type\n  data?: Record<string, any>; // Node data\n  style?: Record<string, any>; // Node style\n  states?: string[]; // Initial node states\n  combo?: string; // Belonging combo\n  children?: string[]; // Array of child node IDs\n}\n```\n\nFor detailed type definitions, please refer to [Node Data](/en/manual/data#nodedata).\n\n### EdgeData\n\nEdge data type.\n\n```typescript\ninterface EdgeData {\n  source: string; // Source ID\n  target: string; // Target ID\n  id?: string; // Edge ID\n  type?: string; // Edge type\n  data?: Record<string, any>; // Edge data\n  style?: Record<string, any>; // Edge style\n  states?: string[]; // Initial edge states\n}\n```\n\nFor detailed type definitions, please refer to [Edge Data](/en/manual/data#edgedata).\n\n### ComboData\n\nCombo data type.\n\n```typescript\ninterface ComboData {\n  id: string; // Combo ID\n  type?: string; // Combo type\n  data?: Record<string, any>; // Combo data\n  style?: Record<string, any>; // Combo style\n  states?: string[]; // Initial combo states\n  combo?: string; // Parent combo ID\n}\n```\n\nFor detailed type definitions, please refer to [Combo Data](/en/manual/data#combodata).\n","packages/site/docs/api/data.zh.md":"---\ntitle: 数据\norder: 0\n---\n\n## 数据操作概述\n\nG6 提供了一套全面的 [数据](/manual/data) 操作 API，覆盖了图数据从查询、修改到更新的完整生命周期。\n\n## API 参考\n\n### Graph.getData()\n\n获取图的完整数据。\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**返回值**:\n\n- **类型**: [GraphData](#graphdata)\n\n- **描述**: 返回包含所有节点、边和组合数据的完整图数据\n\n**示例**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('节点数据:', graphData.nodes);\nconsole.log('边数据:', graphData.edges);\nconsole.log('组合数据:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\n获取节点数据，支持三种调用方式。\n\n```typescript\n// 获取所有节点数据\ngetNodeData(): NodeData[];\n\n// 获取单个节点数据\ngetNodeData(id: ID): NodeData;\n\n// 批量获取多个节点数据\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 节点 ID      | string   | -      |      |\n| ids  | 节点 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **描述**: 返回指定的节点数据或节点数据数组\n\n**示例**:\n\n```typescript\n// 获取所有节点\nconst nodes = graph.getNodeData();\n\n// 获取单个节点\nconst node = graph.getNodeData('node1');\nconsole.log('节点位置:', node.style.x, node.style.y);\n\n// 获取多个节点\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\n获取边数据，支持三种调用方式。\n\n```typescript\n// 获取所有边数据\ngetEdgeData(): EdgeData[];\n\n// 获取单条边数据\ngetEdgeData(id: ID): EdgeData;\n\n// 批量获取多条边数据\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**参数**:\n\n| 参数 | 描述       | 类型     | 默认值 | 必选 |\n| ---- | ---------- | -------- | ------ | ---- |\n| id   | 边 ID      | string   | -      |      |\n| ids  | 边 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **描述**: 返回指定的边数据或边数据数组\n\n**示例**:\n\n```typescript\n// 获取所有边\nconst edges = graph.getEdgeData();\n\n// 获取单条边\nconst edge = graph.getEdgeData('edge1');\nconsole.log('边的起点和终点:', edge.source, edge.target);\n\n// 获取多条边\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\n获取组合数据,支持三种调用方式。\n\n```typescript\n// 获取所有组合数据\ngetComboData(): ComboData[];\n\n// 获取单个组合数据\ngetComboData(id: ID): ComboData;\n\n// 批量获取多个组合数据\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 组合 ID      | string   | -      |      |\n| ids  | 组合 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **描述**: 返回指定的组合数据或组合数据数组\n\n**示例**:\n\n```typescript\n// 获取所有组合\nconst combos = graph.getComboData();\n\n// 获取单个组合\nconst combo = graph.getComboData('combo1');\nconsole.log('组合包含的节点:', combo.children);\n\n// 获取多个组合\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\n获取单个元素数据，支持两种调用方式。\n\n⚠️ **注意**: 此 API 直接获取元素的数据而不必考虑元素类型。\n\n```typescript\n// 获取单个元素数据\ngetElementData(id: ID): ElementDatum;\n\n// 批量获取多个元素数据\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 元素 ID      | string   | -      |      |\n| ids  | 元素 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: ElementDatum \\| ElementDatum[]\n- **描述**: 直接获取元素的数据而不必考虑元素类型\n\n**示例**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('元素数据:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('多个元素数据:', elements);\n```\n\n### Graph.getElementDataByState()\n\n获取指定状态下的元素数据，支持三种调用方式。\n\n```typescript\n// 获取指定状态下的节点数据\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// 获取指定状态下的边数据\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// 获取指定状态下的组合数据\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**参数**:\n\n| 参数        | 描述     | 类型                              | 默认值 | 必选 |\n| ----------- | -------- | --------------------------------- | ------ | ---- |\n| elementType | 元素类型 | `'node'` \\| `'edge'` \\| `'combo'` | -      | ✓    |\n| state       | 状态     | string                            | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **描述**: 返回指定状态下的节点数据、边数据或组合数据\n\n**示例**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('选中的节点:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('选中的边:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('选中的组合:', selectedCombos);\n```\n\n**内置状态**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\n获取节点或组合的一跳邻居节点数据。\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[]\n- **描述**: 返回邻居节点数据\n\n**示例**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('邻居节点:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\n获取节点或组合关联边的数据。\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**参数**:\n\n| 参数      | 描述            | 类型                          | 默认值 | 必选 |\n| --------- | --------------- | ----------------------------- | ------ | ---- |\n| id        | 节点或组合的 ID | string                        | -      | ✓    |\n| direction | 边的方向        | `'in'` \\| `'out'` \\| `'both'` | -      |      |\n\n**返回值**:\n\n- **类型**: EdgeData[]\n- **描述**: 返回与指定节点或组合关联的边数据\n\n**示例**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('关联边:', relatedEdges);\n```\n\n### Graph.getParentData()\n\n获取节点或组合的父元素数据。\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      |      |\n\n**返回值**:\n\n- **类型**: NodeData \\| ComboData \\| undefined\n- **描述**: 返回父元素数据,如果不存在则返回 undefined\n\n**示例**:\n\n```typescript\n// 获取树图中节点的父节点\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// 获取组合中节点的父组合\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\n获取节点或组合的子元素数据。\n\n```typescript\ngetChildrenData(id: ID):(NodeData \\| ComboData)[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: (NodeData \\| ComboData)[]\n- **描述**: 返回子元素数据数组\n\n**注意**:\n\n- **查询 combo 的子元素**：如果 id 对应的是 combo 元素，可以直接通过此 API 获取其所有子元素。\n- **查询节点的子元素**：如果 id 对应的是节点，只有当图数据为树结构（即节点数据中维护有 `children` 字段，且 `children` 为该节点的子节点 ID 数组）时，才能通过此 API 获取到该节点的子元素。否则返回空数组。\n\n**示例**:\n\n```typescript\n// 获取组合的子元素\nconst children = graph.getChildrenData('combo1');\nconsole.log('子节点数量:', children.length);\n\n// 处理每个子元素\nchildren.forEach((child) => {\n  console.log('子元素ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\n获取节点或组合的所有祖先元素数据。\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回祖先元素数据数组，从父节点到根节点的顺序排列\n\n**示例**:\n\n```typescript\n// 获取树图中节点的所有祖先节点\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  '祖先节点路径:',\n  treeAncestors.map((node) => node.id),\n);\n\n// 获取组合中节点的所有父组合\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\n获取节点或组合的所有后代元素数据。\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回后代元素数据数组\n\n**示例**:\n\n```typescript\n// 获取节点的所有后代\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('后代数量:', descendants.length);\n\n// 处理所有后代元素\ndescendants.forEach((descendant) => {\n  console.log('后代元素ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\n设置图的完整数据。\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                           | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 新的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 直接设置数据\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// 使用函数式增量更新：获取当前图数据，并返回新的图数据\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\n新增元素数据。\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 需要添加的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\n新增节点数据。\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 要添加的节点数据或返回节点数据的函数 | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: '节点 1' },\n  },\n]);\n\n// 批量添加节点\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// 函数式添加\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\n新增边数据。\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                          | 默认值 | 必选 |\n| ---- | -------------------------------- | ------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的边数据或返回边数据的函数 | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单条边\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: '关系',\n    },\n  },\n]);\n\n// 批量添加边\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// 函数式添加\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\n新增组合数据。\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\n为树图节点添加子节点数据。\n\n⚠️ **注意**: 为组合添加子节点使用 addNodeData / addComboData 方法。\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**参数**:\n\n| 参数         | 描述       | 类型                    | 默认值 | 必选 |\n| ------------ | ---------- | ----------------------- | ------ | ---- |\n| parentId     | 父节点 ID  | string                  | -      | ✓    |\n| childrenData | 子节点数据 | [NodeData](#nodedata)[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\n删除元素数据。\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                               | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的元素 ID 或返回元素 ID 的函数 | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\n删除节点数据。\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的节点 ID 或返回节点 ID 的函数 | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\n删除边数据。\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                            | 默认值 | 必选 |\n| ---- | -------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的边 ID 或返回边 ID 的函数 | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\n删除组合数据。\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的组合 ID 或返回组合 ID 的函数 | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\n更新元素数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                                             | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的元素数据或返回元素数据的函数 | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\n更新节点数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                           | 默认值 | 必选 |\n| ---- | ------------------------------------ | ---------------------------------------------- | ------ | ---- |\n| data | 要更新的节点数据或返回节点数据的函数 | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\n更新边数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                                                                                         | 默认值 | 必选 |\n| ---- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的边数据或返回边数据的函数 | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\n更新组合数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\n判断节点是否存在\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                 | 类型      | 默认值 | 必选 |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的节点id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\n判断边是否存在\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述               | 类型      | 默认值 | 必选 |\n| ---- | ------------------ | --------- | ------ | ---- |\n| id   | 需要进行判断的边id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\n判断combo是否存在\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                      | 类型      | 默认值 | 必选 |\n| ---- | ------------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的combo组合id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## 类型定义\n\n### ID\n\n元素 ID 类型。\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\n多个元素 ID 类型。\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 图数据类型。\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\n节点数据类型。\n\n```typescript\ninterface NodeData {\n  id: string; // 节点 ID\n  type?: string; // 节点类型\n  data?: Record<string, any>; // 节点数据\n  style?: Record<string, any>; // 节点样式\n  states?: string[]; // 节点初始状态\n  combo?: string; // 所属组合\n  children?: string[]; // 子节点 ID 数组\n}\n```\n\n详细类型定义请参考 [节点数据](/manual/data#节点数据nodedata)。\n\n### EdgeData\n\n边数据类型。\n\n```typescript\ninterface EdgeData {\n  source: string; // 起点 ID\n  target: string; // 终点 ID\n  id?: string; // 边 ID\n  type?: string; // 边类型\n  data?: Record<string, any>; // 边数据\n  style?: Record<string, any>; // 边样式\n  states?: string[]; // 边初始状态\n}\n```\n\n详细类型定义请参考 [边数据](/manual/data#边数据edgedata)。\n\n### ComboData\n\n组合数据类型。\n\n```typescript\ninterface ComboData {\n  id: string; // 组合 ID\n  type?: string; // 组合类型\n  data?: Record<string, any>; // 组合数据\n  style?: Record<string, any>; // 组合样式\n  states?: string[]; // 组合初始状态\n  combo?: string; // 父组合 ID\n}\n```\n\n详细类型定义请参考 [组合数据](/manual/data#组合数据combodata)。\n","packages/site/docs/api/element.en.md":"---\ntitle: Element Operations\norder: 1\n---\n\n## Overview of Element Operations\n\nThe [Element](/en/manual/element/overview) operation API in G6 allows you to control the behavior and attributes of elements such as nodes, edges, and Combos in the graph. These APIs can be used for:\n\n1. **Element State Management**: Set, update, or remove the state of elements\n2. **Element Display Control**: Control the z-index and visibility of elements\n3. **Element Collapse/Expand**: Operate the collapse/expand state of collapsible elements\n4. **Element Position Operations**: Move and align element positions\n5. **Element Focus**: Focus the viewport on specific elements\n\nThrough these operations, you can achieve rich interactive effects and visual presentations.\n\n## API Reference\n\n### Graph.getElementPosition(id)\n\nGet the position of an element.\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Returns the coordinates of the element\n\n**Example**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\nGet the rendering bounding box of the element itself and its child nodes in the world coordinate system.\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [AABB](#aabb)\n- **Description**: Returns the rendering bounding box of the element\n\n### Graph.getElementRenderStyle(id)\n\nGet the rendering style of an element.\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Record<string, any>\n- **Description**: Returns the rendering style of the element\n\n### Graph.getElementState(id)\n\nGet the state of an element.\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [State](#state)[]\n- **Description**: Returns the state of the element\n\n### Graph.getElementType(id)\n\nGet the type of an element.\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: string\n- **Description**: Returns the type of the element\n\n### Graph.getElementVisibility(id)\n\nGet the visibility of an element.\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden';\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: 'visible' | 'hidden'\n- **Description**: Returns the visibility of the element\n\n### Graph.getElementZIndex(id)\n\nGet the z-index of an element.\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: number\n- **Description**: Returns the z-index of the element\n\n### Graph.setElementState(id, state, options)\n\nSet the state of an element, supporting two calling methods:\n\n```typescript\n// Set the state of a single element\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// Set the state of multiple elements\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element State Setting**\n\n| Parameter | Description       | Type            | Default | Required |\n| --------- | ----------------- | --------------- | ------- | -------- | --- |\n| id        | Element ID to set | string          | -       | ✓        |\n| state     | State to set      | [State](#state) | State[] | -        | ✓   |\n| animation | Enable animation  | boolean         | -       |          |\n\n**Batch Element State Setting**\n\n| Parameter | Description                    | Type                       | Default  | Required |\n| --------- | ------------------------------ | -------------------------- | -------- | -------- | --- |\n| state     | Mapping of element ID to state | Record<ID, [State](#state) | State[]> | -        | ✓   |\n| animation | Enable animation               | boolean                    | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the state setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the state of a single element\nawait graph.setElementState('node1', 'selected');\n\n// Set the state of multiple elements\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\nSet the visibility of an element, supporting two calling methods:\n\n```typescript\n// Set the visibility of a single element\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// Set the visibility of multiple elements\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Visibility Setting**\n\n| Parameter  | Description       | Type      | Default  | Required |\n| ---------- | ----------------- | --------- | -------- | -------- | --- |\n| id         | Element ID to set | string    | -        | ✓        |\n| visibility | Visibility to set | 'visible' | 'hidden' | -        | ✓   |\n| animation  | Enable animation  | boolean   | -        |          |\n\n**Batch Element Visibility Setting**\n\n| Parameter  | Description                         | Type                 | Default   | Required |\n| ---------- | ----------------------------------- | -------------------- | --------- | -------- | --- |\n| visibility | Mapping of element ID to visibility | Record<ID, 'visible' | 'hidden'> | -        | ✓   |\n| animation  | Enable animation                    | boolean              | -         |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the visibility setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the visibility of a single element\nawait graph.setElementVisibility('node1', 'hidden');\n\n// Set the visibility of multiple elements\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\nSet the z-index of an element, supporting two calling methods:\n\n```typescript\n// Set the z-index of a single element\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// Set the z-index of multiple elements\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Z-Index Setting**\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n| zIndex    | Z-Index     | number | -       | ✓        |\n\n**Batch Element Z-Index Setting**\n\n| Parameter | Description                      | Type               | Default | Required |\n| --------- | -------------------------------- | ------------------ | ------- | -------- |\n| zIndex    | Mapping of element ID to z-index | Record<ID, number> | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the z-index setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the z-index of a single element\nawait graph.setElementZIndex('node1', 10);\n\n// Set the z-index of multiple elements\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\nSet the node style mapping, i.e., the value of `options.node`.\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| node      | Node configuration | [NodeOptions](/en/manual/element/node/overview) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Set the fill color of all nodes to red\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\nSet the edge style mapping, i.e., the value of `options.edge`.\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| edge      | Edge configuration | [EdgeOptions](/en/manual/element/edge/overview) | -       | ✓        |\n\n### Graph.setCombo(combo)\n\nSet the combo style mapping, i.e., the value of `options.combo`.\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description         | Type                                              | Default | Required |\n| --------- | ------------------- | ------------------------------------------------- | ------- | -------- |\n| combo     | Combo configuration | [ComboOptions](/en/manual/element/combo/overview) | -       | ✓        |\n\n### Graph.collapseElement(id, options)\n\nCollapse the specified element, usually used to collapse Combos or nodes with child elements.\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                     | Type    | Default                                                 | Required |\n| --------- | --------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to collapse                                          | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for collapsing nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the collapse operation is complete\n\n**Example**:\n\n```typescript\n// Simple collapse with default configuration\nawait graph.collapseElement('combo1');\n\n// Collapse with animation\ngraph.collapseElement('combo1', true);\n\n// Collapse while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\nExpand the specified element, usually used to expand previously collapsed Combos or nodes.\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                    | Type    | Default                                                 | Required |\n| --------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to expand                                           | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for expanding nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the expand operation is complete\n\n**Example**:\n\n```typescript\n// Simple expand with default configuration\nawait graph.expandElement('combo1');\n\n// Expand with animation\nawait graph.expandElement('combo1', true);\n\n// Expand while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\nBring the specified element to the front, making it appear above other overlapping elements.\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default  | Required |\n| --------- | ----------- | ------ | -------- | -------- | --- |\n| id        | Element ID  | string | string[] | -        | ✓   |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\n// Bring a node to the front\ngraph.frontElement('node1');\n\n// Bring multiple selected nodes to the front\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\nShow the specified element.\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the show operation is complete\n\n**Example**:\n\n```typescript\n// Show a single element\nawait graph.showElement('node1');\n\n// Show an element with animation\nawait graph.showElement('node1', true);\n\n// Show multiple elements\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\nHide the specified element.\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the hide operation is complete\n\n**Example**:\n\n```typescript\n// Hide an element without animation\nawait graph.hideElement('node1');\n\n// Hide an element with animation\nawait graph.hideElement('node1', true);\n\n// Hide multiple elements\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\nTranslate an element by a specified distance, supporting two calling methods:\n\n```typescript\n// Translate an element by a specified distance (relative translation)\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// Translate multiple elements by a specified distance (relative translation)\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Translation**\n\n| Parameter | Description                            | Type             | Default | Required |\n| --------- | -------------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                             | string           | -       | ✓        |\n| offset    | Relative translation distance [dx, dy] | [number, number] | -       | ✓        |\n| animation | Enable animation                       | boolean          | -       |          |\n\n**Batch Element Translation**\n\n| Parameter | Description                                   | Type                         | Default | Required |\n| --------- | --------------------------------------------- | ---------------------------- | ------- | -------- |\n| offsets   | Mapping of element ID to translation distance | Record<ID, [number, number]> | -       | ✓        |\n| animation | Enable animation                              | boolean                      | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the translation operation is complete\n\n**Example**:\n\n```typescript\n// Translate right by 100 pixels and down by 50 pixels\nawait graph.translateElementBy('node1', [100, 50]);\n\n// Translate with animation\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// Apply the same translation to multiple nodes\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\nMove an element to a specified position, supporting two calling methods:\n\n```typescript\n// Move an element to a specified position (absolute position)\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// Move multiple elements to specified positions (absolute position)\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Movement**\n\n| Parameter | Description                     | Type             | Default | Required |\n| --------- | ------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                      | string           | -       | ✓        |\n| position  | Target absolute position [x, y] | [number, number] | -       | ✓        |\n| animation | Enable animation                | boolean          | -       |          |\n\n**Batch Element Movement**\n\n| Parameter | Description                              | Type                             | Default | Required |\n| --------- | ---------------------------------------- | -------------------------------- | ------- | -------- |\n| positions | Mapping of element ID to target position | Record<string, [number, number]> | -       | ✓        |\n| animation | Enable animation                         | boolean                          | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the movement operation is complete\n\n**Example**:\n\n```typescript\n// Move a node to position (200, 300) on the canvas\nawait graph.translateElementTo('node1', [200, 300]);\n\n// Move with animation\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// Arrange a group of nodes neatly\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\nFocus on the specified element, centering it in the viewport.\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                         | Type                                                            | Default  | Required |\n| --------- | ----------------------------------- | --------------------------------------------------------------- | -------- | -------- | --- |\n| id        | One or more element IDs to focus on | string                                                          | string[] | -        | ✓   |\n| animation | Viewport animation configuration    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the focus operation is complete\n\n**Example**:\n\n```typescript\n// Focus on a single node\nawait graph.focusElement('node1');\n\n// Use custom animation configuration\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// Focus on multiple nodes\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## Type Definitions\n\n### CollapseExpandNodeOptions\n\nConfiguration options for collapsing or expanding elements.\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * Enable animation\n   */\n  animation?: boolean;\n  /**\n   * Ensure the position of expanded/collapsed nodes remains unchanged\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) is a fundamental concept in computer graphics.\n\n```typescript\ninterface AABB {\n  x: number; // x-coordinate of the top-left corner of the rectangle\n  y: number; // y-coordinate of the top-left corner of the rectangle\n  width: number; // Width of the rectangle\n  height: number; // Height of the rectangle\n}\n```\n\n### State\n\nElement state type.\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","packages/site/docs/api/element.zh.md":"---\ntitle: 元素操作\norder: 1\n---\n\n## 元素操作概述\n\nG6 中的 [元素](/manual/element/overview) 操作 API 允许您控制图中节点、边和组合(Combo)等元素的行为和属性。这些 API 可以用于：\n\n1. **元素状态管理**：设置、更新或移除元素的状态\n2. **元素显示控制**：控制元素的层级、可见性\n3. **元素展开/收起**：操作可折叠元素的展开/收起状态\n4. **元素位置操作**：移动、对齐元素位置\n5. **元素聚焦**：将视口聚焦到特定元素\n\n通过这些操作，您可以实现丰富的交互效果和视觉呈现。\n\n## API 参考\n\n### Graph.getElementPosition(id)\n\n获取元素位置。\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 返回元素的坐标位置\n\n**示例**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\n获取元素自身以及子节点在世界坐标系下的渲染包围盒。\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [AABB](#aabb)\n- **描述**: 返回元素的渲染包围盒\n\n### Graph.getElementRenderStyle(id)\n\n获取元素的渲染样式。\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Record\\<string, any\\>\n- **描述**: 返回元素的渲染样式\n\n### Graph.getElementState(id)\n\n获取元素的状态。\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [State](#state)[]\n- **描述**: 返回元素的状态\n\n### Graph.getElementType(id)\n\n获取元素类型。\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: string\n- **描述**: 返回元素的类型\n\n### Graph.getElementVisibility(id)\n\n获取元素可见性。\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden' ;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: 'visible' | 'hidden'\n- **描述**: 返回元素的可见性\n\n### Graph.getElementZIndex(id)\n\n获取元素层级。\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: number\n- **描述**: 返回元素的层级\n\n### Graph.setElementState(id, state, options)\n\n设置元素状态，支持两种调用方式：\n\n```typescript\n// 设置单个元素状态\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// 批量设置元素状态\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素状态设置**\n\n| 参数      | 描述                | 类型                       | 默认值 | 必选 |\n| --------- | ------------------- | -------------------------- | ------ | ---- |\n| id        | 要设置状态的元素 ID | string                     | -      | ✓    |\n| state     | 要设置的状态        | [State](#state) \\| State[] | -      | ✓    |\n| animation | 是否启用动画        | boolean                    | -      |      |\n\n**批量元素状态设置**\n\n| 参数      | 描述               | 类型                                   | 默认值 | 必选 |\n| --------- | ------------------ | -------------------------------------- | ------ | ---- |\n| state     | 元素ID到状态的映射 | Record<ID, [State](#state) \\| State[]> | -      | ✓    |\n| animation | 是否启用动画       | boolean                                | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，状态设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素状态\nawait graph.setElementState('node1', 'selected');\n\n// 设置多个元素状态\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\n设置元素的可见性，支持两种调用方式：\n\n```typescript\n// 设置单个元素可见性\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// 批量设置元素可见性\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素可见性设置**\n\n| 参数       | 描述                  | 类型                      | 默认值 | 必选 |\n| ---------- | --------------------- | ------------------------- | ------ | ---- |\n| id         | 要设置可见性的元素 ID | string                    | -      | ✓    |\n| visibility | 要设置的可见性        | `'visible'` \\| `'hidden'` | -      | ✓    |\n| animation  | 是否启用动画          | boolean                   | -      |      |\n\n**批量元素可见性设置**\n\n| 参数       | 描述                 | 类型                                  | 默认值 | 必选 |\n| ---------- | -------------------- | ------------------------------------- | ------ | ---- |\n| visibility | 元素ID到可见性的映射 | Record<ID, `'visible'` \\| `'hidden'`> | -      | ✓    |\n| animation  | 是否启用动画         | boolean                               | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，可见性设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素可见性\nawait graph.setElementVisibility('node1', 'hidden');\n\n// 设置多个元素可见性\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\n设置元素的层级，有两种调用方式：\n\n```typescript\n// 设置单个元素层级\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// 批量设置元素层级\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**参数**:\n\n**单个元素层级设置**\n\n| 参数   | 描述    | 类型   | 默认值 | 必选 |\n| ------ | ------- | ------ | ------ | ---- |\n| id     | 元素 ID | string | -      | ✓    |\n| zIndex | 层级    | number | -      | ✓    |\n\n**批量元素层级设置**\n\n| 参数   | 描述               | 类型               | 默认值 | 必选 |\n| ------ | ------------------ | ------------------ | ------ | ---- |\n| zIndex | 元素ID到层级的映射 | Record<ID, number> | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，层级设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素层级\nawait graph.setElementZIndex('node1', 10);\n\n// 设置多个元素层级\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\n设置节点样式映射。即 `options.node` 的值。\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述     | 类型                                         | 默认值 | 必选 |\n| ---- | -------- | -------------------------------------------- | ------ | ---- |\n| node | 节点配置 | [NodeOptions](/manual/element/node/overview) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 设置所有的节点填充色为红色\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\n设置边样式映射。即 `options.edge` 的值。\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述   | 类型                                         | 默认值 | 必选 |\n| ---- | ------ | -------------------------------------------- | ------ | ---- |\n| edge | 边配置 | [EdgeOptions](/manual/element/edge/overview) | -      | ✓    |\n\n### Graph.setCombo(combo)\n\n设置组合样式映射。即 `options.combo` 的值。\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**参数**:\n\n| 参数  | 描述     | 类型                                           | 默认值 | 必选 |\n| ----- | -------- | ---------------------------------------------- | ------ | ---- |\n| combo | 组合配置 | [ComboOptions](/manual/element/combo/overview) | -      | ✓    |\n\n### Graph.collapseElement(id, options)\n\n收起指定元素，通常用于折叠组合(Combo)或具有子元素的节点。\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要收起的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或收起节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，收起操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单收起，使用默认配置\nawait graph.collapseElement('combo1');\n\n// 收起并启用动画\nawait graph.collapseElement('combo1', true);\n\n// 收起并保证展开/收起的节点位置不变\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\n展开指定元素，通常用于展开先前收起的组合(Combo)或节点。\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要展开的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或展开节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，展开操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单展开，使用默认配置\nawait graph.expandElement('combo1');\n\n// 展开并启用动画\nawait graph.expandElement('combo1', true);\n\n// 展开并保证展开/收起的节点位置不变\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\n将指定元素置于最顶层，使其显示在其他重叠元素之上。\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型               | 默认值 | 必选 |\n| ---- | ------- | ------------------ | ------ | ---- |\n| id   | 元素 ID | string \\| string[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\n// 将节点置于最顶层\ngraph.frontElement('node1');\n\n// 对于选中的多个节点，都置于最顶层\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\n显示指定元素。\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，显示操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 显示单个元素\nawait graph.showElement('node1');\n\n// 带动画显示元素\nawait graph.showElement('node1', true);\n\n// 显示多个元素\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\n隐藏指定元素。\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，隐藏操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 无动画隐藏元素\nawait graph.hideElement('node1');\n\n// 带动画隐藏元素\nawait graph.hideElement('node1', true);\n\n// 隐藏多个元素\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\n相对平移元素指定距离，支持两种调用方式：\n\n```typescript\n// 将元素平移指定距离（相对平移）\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素平移指定距离（相对平移）\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素平移**\n\n| 参数      | 描述                    | 类型             | 默认值 | 必选 |\n| --------- | ----------------------- | ---------------- | ------ | ---- |\n| id        | 要平移的元素 ID         | string           | -      | ✓    |\n| offset    | 平移的相对距离 [dx, dy] | [number, number] | -      | ✓    |\n| animation | 是否启用动画            | boolean          | -      |      |\n\n**批量元素平移**\n\n| 参数      | 描述                   | 类型                         | 默认值 | 必选 |\n| --------- | ---------------------- | ---------------------------- | ------ | ---- |\n| offsets   | 元素ID到平移距离的映射 | Record<ID, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                      | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，平移操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 向右平移100像素，向下平移50像素\nawait graph.translateElementBy('node1', [100, 50]);\n\n// 带动画平移\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// 对多个节点应用相同的平移\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\n将元素移动到指定位置，支持两种调用方式：\n\n```typescript\n// 将元素移动到指定位置（绝对位置）\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素移动到指定位置（绝对位置）\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素移动**\n\n| 参数      | 描述                | 类型             | 默认值 | 必选 |\n| --------- | ------------------- | ---------------- | ------ | ---- |\n| id        | 要移动的元素 ID     | string           | -      | ✓    |\n| position  | 目标绝对位置 [x, y] | [number, number] | -      | ✓    |\n| animation | 是否启用动画        | boolean          | -      |      |\n\n**批量元素移动**\n\n| 参数      | 描述                   | 类型                             | 默认值 | 必选 |\n| --------- | ---------------------- | -------------------------------- | ------ | ---- |\n| positions | 元素ID到目标位置的映射 | Record<string, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                          | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，移动操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 将节点移动到画布的 (200, 300) 位置\nawait graph.translateElementTo('node1', [200, 300]);\n\n// 带动画移动\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// 将一组节点整齐排列\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\n聚焦到指定元素，使元素居中于视口。\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述                      | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| id        | 要聚焦的一个或多个元素 ID | string \\| string[]                                              | -      | ✓    |\n| animation | 视口动画配置              | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，聚焦操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 聚焦到单个节点\nawait graph.focusElement('node1');\n\n// 使用自定义动画配置\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// 聚焦到多个节点\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## 类型定义\n\n### CollapseExpandNodeOptions\n\n收起或展开元素的配置选项。\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * 是否使用动画\n   */\n  animation?: boolean;\n  /**\n   * 保证展开/收起的节点位置不变\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) 是\"轴对齐包围盒\"的缩写，是计算机图形学中的一个基础概念。\n\n```typescript\ninterface AABB {\n  x: number; // 矩形左上角的 x 坐标\n  y: number; // 矩形左上角的 y 坐标\n  width: number; // 矩形宽度\n  height: number; // 矩形高度\n}\n```\n\n### State\n\n元素状态类型。\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","packages/site/docs/api/event.en.md":"---\ntitle: Event Listening\norder: 11\n---\n\n## Overview of the Event System\n\nG6 provides a powerful event mechanism that allows you to respond to various interactive behaviors occurring in the chart, such as node clicks, edge hovers, canvas drags, etc. Through the event system, you can implement complex interactive logic to enhance user experience.\n\n### Event Categories\n\nEvents in G6 can be broadly categorized into the following types:\n\n1. **Element Events**: Events related to nodes, edges, and Combos, such as `node:click`, `edge:mouseenter`\n2. **Canvas Events**: Events related to the entire canvas, such as `canvas:drag`, `canvas:wheel`\n3. **Lifecycle Events**: Events related to the chart lifecycle, such as `beforerender`, `afterrender`\n\n### Event Naming Convention\n\nG6 events follow the `[object]:[event]` format, for example:\n\n- `node:click` - Node click event\n- `edge:mouseenter` - Mouse enters edge event\n- `canvas:drag` - Canvas drag event\n\n## Best Practice: Using Constant Enums\n\nG6 provides a complete set of event constant enums, and it is **strongly recommended** to use these constants instead of directly using string event names:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// Use constant enums to listen to events\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**Advantages**:\n\n- Type safety, avoiding string spelling errors\n- Provides intelligent code hints and auto-completion\n\n## API Reference\n\n### Graph.on(eventName, callback, once)\n\nListen to a specified event and execute a callback function when the event is triggered.\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n| once      | Whether to listen only once                            | boolean            | -       |          |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Listen to node click event\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // Get the ID of the clicked node\n  console.log(`Node ${target.id} was clicked`);\n\n  // Get node data\n  const nodeData = graph.getNodeData(target.id);\n  console.log('Node data:', nodeData);\n\n  // Modify node state\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen to edge mouse enter event\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// Listen to canvas drag event\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('Canvas is being dragged');\n});\n```\n\n### Graph.once(eventName, callback)\n\nListen to an event once, and automatically remove the listener after the event is triggered once.\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// Listen to the chart's first load completion event, executed only once\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('Chart rendered for the first time');\n  // Execute one-time initialization operations\n  highlightImportantNodes();\n});\n\n// Wait for the user to click a node for the first time and then perform operations\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('User clicked a node for the first time:', evt.target.id);\n  showTutorialTip('You can drag nodes to change their position');\n});\n```\n\n### Graph.off()\n\nRemove all event listeners.\n\n```typescript\noff(): this;\n```\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\n// Remove all event listeners\ngraph.off();\nconsole.log('All event listeners have been removed');\n```\n\n### Graph.off(eventName)\n\nRemove all listeners of a specified event type.\n\n```typescript\noff(eventName: string): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type   | Default | Required |\n| --------- | --------------------------- | ------ | ------- | -------- |\n| eventName | Name of the event to remove | string | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Remove all node click event listeners\ngraph.off(NodeEvent.CLICK);\nconsole.log('All node click event listeners have been removed');\n\n// Remove related temporary event listeners after a certain operation mode ends\nfunction exitEditMode() {\n  // Remove all listeners in edit mode\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('Exited edit mode');\n}\n```\n\n### Graph.off(eventName, callback)\n\nRemove a specific callback function for a specific event.\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type                     | Default | Required |\n| --------- | --------------------------- | ------------------------ | ------- | -------- |\n| eventName | Name of the event to remove | string                   | -       | ✓        |\n| callback  | Callback function to remove | (...args: any[]) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Define callback function\nconst handleNodeClick = (evt) => {\n  console.log('Node clicked:', evt.target.id);\n};\n\n// Add listener\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// Later, remove this specific listener at a certain point\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('Specific node click event listener has been removed');\n```\n\n## Event Constant Enums\n\nG6 provides various event constant enums to facilitate developers in using standardized event names. Below is a detailed description of all event constants:\n\n### Node Events (NodeEvent)\n\n| Constant Name | Event Name          | Description                                                                   |\n| ------------- | ------------------- | ----------------------------------------------------------------------------- |\n| CLICK         | `node:click`        | Triggered when a node is clicked                                              |\n| DBLCLICK      | `node:dblclick`     | Triggered when a node is double-clicked                                       |\n| POINTER_OVER  | `node:pointerover`  | Triggered when the pointer enters a node                                      |\n| POINTER_LEAVE | `node:pointerleave` | Triggered when the pointer leaves a node                                      |\n| POINTER_ENTER | `node:pointerenter` | Triggered when the pointer enters a node or its child elements (non-bubbling) |\n| POINTER_MOVE  | `node:pointermove`  | Triggered when the pointer moves over a node                                  |\n| POINTER_OUT   | `node:pointerout`   | Triggered when the pointer leaves a node                                      |\n| POINTER_DOWN  | `node:pointerdown`  | Triggered when the pointer is pressed down on a node                          |\n| POINTER_UP    | `node:pointerup`    | Triggered when the pointer is released on a node                              |\n| CONTEXT_MENU  | `node:contextmenu`  | Triggered when the context menu is opened on a node                           |\n| DRAG_START    | `node:dragstart`    | Triggered when dragging a node starts                                         |\n| DRAG          | `node:drag`         | Triggered during node dragging                                                |\n| DRAG_END      | `node:dragend`      | Triggered when node dragging ends                                             |\n| DRAG_ENTER    | `node:dragenter`    | Triggered when a draggable item enters a node                                 |\n| DRAG_OVER     | `node:dragover`     | Triggered when a draggable item is over a node                                |\n| DRAG_LEAVE    | `node:dragleave`    | Triggered when a draggable item leaves a node                                 |\n| DROP          | `node:drop`         | Triggered when a draggable item is dropped on a node                          |\n\n### Edge Events (EdgeEvent)\n\n| Constant Name | Event Name          | Description                                                                    |\n| ------------- | ------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `edge:click`        | Triggered when an edge is clicked                                              |\n| DBLCLICK      | `edge:dblclick`     | Triggered when an edge is double-clicked                                       |\n| POINTER_OVER  | `edge:pointerover`  | Triggered when the pointer enters an edge                                      |\n| POINTER_LEAVE | `edge:pointerleave` | Triggered when the pointer leaves an edge                                      |\n| POINTER_ENTER | `edge:pointerenter` | Triggered when the pointer enters an edge or its child elements (non-bubbling) |\n| POINTER_MOVE  | `edge:pointermove`  | Triggered when the pointer moves over an edge                                  |\n| POINTER_OUT   | `edge:pointerout`   | Triggered when the pointer leaves an edge                                      |\n| POINTER_DOWN  | `edge:pointerdown`  | Triggered when the pointer is pressed down on an edge                          |\n| POINTER_UP    | `edge:pointerup`    | Triggered when the pointer is released on an edge                              |\n| CONTEXT_MENU  | `edge:contextmenu`  | Triggered when the context menu is opened on an edge                           |\n| DRAG_ENTER    | `edge:dragenter`    | Triggered when a draggable item enters an edge                                 |\n| DRAG_OVER     | `edge:dragover`     | Triggered when a draggable item is over an edge                                |\n| DRAG_LEAVE    | `edge:dragleave`    | Triggered when a draggable item leaves an edge                                 |\n| DROP          | `edge:drop`         | Triggered when a draggable item is dropped on an edge                          |\n\n### Combo Events (ComboEvent)\n\n| Constant Name | Event Name           | Description                                                                    |\n| ------------- | -------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `combo:click`        | Triggered when a Combo is clicked                                              |\n| DBLCLICK      | `combo:dblclick`     | Triggered when a Combo is double-clicked                                       |\n| POINTER_OVER  | `combo:pointerover`  | Triggered when the pointer enters a Combo                                      |\n| POINTER_LEAVE | `combo:pointerleave` | Triggered when the pointer leaves a Combo                                      |\n| POINTER_ENTER | `combo:pointerenter` | Triggered when the pointer enters a Combo or its child elements (non-bubbling) |\n| POINTER_MOVE  | `combo:pointermove`  | Triggered when the pointer moves over a Combo                                  |\n| POINTER_OUT   | `combo:pointerout`   | Triggered when the pointer leaves a Combo                                      |\n| POINTER_DOWN  | `combo:pointerdown`  | Triggered when the pointer is pressed down on a Combo                          |\n| POINTER_UP    | `combo:pointerup`    | Triggered when the pointer is released on a Combo                              |\n| CONTEXT_MENU  | `combo:contextmenu`  | Triggered when the context menu is opened on a Combo                           |\n| DRAG_START    | `combo:dragstart`    | Triggered when dragging a Combo starts                                         |\n| DRAG          | `combo:drag`         | Triggered during Combo dragging                                                |\n| DRAG_END      | `combo:dragend`      | Triggered when Combo dragging ends                                             |\n| DRAG_ENTER    | `combo:dragenter`    | Triggered when a draggable item enters a Combo                                 |\n| DRAG_OVER     | `combo:dragover`     | Triggered when a draggable item is over a Combo                                |\n| DRAG_LEAVE    | `combo:dragleave`    | Triggered when a draggable item leaves a Combo                                 |\n| DROP          | `combo:drop`         | Triggered when a draggable item is dropped on a Combo                          |\n\n### Canvas Events (CanvasEvent)\n\n| Constant Name | Event Name            | Description                                                                       |\n| ------------- | --------------------- | --------------------------------------------------------------------------------- |\n| CLICK         | `canvas:click`        | Triggered when clicking on the canvas blank area                                  |\n| DBLCLICK      | `canvas:dblclick`     | Triggered when double-clicking on the canvas blank area                           |\n| POINTER_OVER  | `canvas:pointerover`  | Triggered when the pointer enters the canvas                                      |\n| POINTER_LEAVE | `canvas:pointerleave` | Triggered when the pointer leaves the canvas                                      |\n| POINTER_ENTER | `canvas:pointerenter` | Triggered when the pointer enters the canvas or its child elements (non-bubbling) |\n| POINTER_MOVE  | `canvas:pointermove`  | Triggered when the pointer moves over the canvas                                  |\n| POINTER_OUT   | `canvas:pointerout`   | Triggered when the pointer leaves the canvas                                      |\n| POINTER_DOWN  | `canvas:pointerdown`  | Triggered when the pointer is pressed down on the canvas                          |\n| POINTER_UP    | `canvas:pointerup`    | Triggered when the pointer is released on the canvas                              |\n| CONTEXT_MENU  | `canvas:contextmenu`  | Triggered when the context menu is opened on the canvas                           |\n| DRAG_START    | `canvas:dragstart`    | Triggered when dragging the canvas starts                                         |\n| DRAG          | `canvas:drag`         | Triggered during canvas dragging                                                  |\n| DRAG_END      | `canvas:dragend`      | Triggered when canvas dragging ends                                               |\n| DRAG_ENTER    | `canvas:dragenter`    | Triggered when a draggable item enters the canvas                                 |\n| DRAG_OVER     | `canvas:dragover`     | Triggered when a draggable item is over the canvas                                |\n| DRAG_LEAVE    | `canvas:dragleave`    | Triggered when a draggable item leaves the canvas                                 |\n| DROP          | `canvas:drop`         | Triggered when a draggable item is dropped on the canvas                          |\n| WHEEL         | `canvas:wheel`        | Triggered when scrolling the mouse wheel on the canvas                            |\n\n### Graph Lifecycle Events (GraphEvent)\n\n| Constant Name            | Event Name               | Description                                    |\n| ------------------------ | ------------------------ | ---------------------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | Triggered before canvas initialization         |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | Triggered after canvas initialization          |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | Triggered before viewport size change          |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | Triggered after viewport size change           |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | Triggered before element creation              |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | Triggered after element creation               |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | Triggered before element update                |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | Triggered after element update                 |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | Triggered before element destruction           |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | Triggered after element destruction            |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | Triggered before element translation           |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | Triggered after element translation            |\n| BEFORE_DRAW              | `beforedraw`             | Triggered before drawing starts                |\n| AFTER_DRAW               | `afterdraw`              | Triggered after drawing ends                   |\n| BEFORE_RENDER            | `beforerender`           | Triggered before rendering starts              |\n| AFTER_RENDER             | `afterrender`            | Triggered after rendering completes            |\n| BEFORE_ANIMATE           | `beforeanimate`          | Triggered before animation starts              |\n| AFTER_ANIMATE            | `afteranimate`           | Triggered after animation ends                 |\n| BEFORE_LAYOUT            | `beforelayout`           | Triggered before layout starts                 |\n| AFTER_LAYOUT             | `afterlayout`            | Triggered after layout ends                    |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | Triggered before each stage in pipeline layout |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | Triggered after each stage in pipeline layout  |\n| BEFORE_TRANSFORM         | `beforetransform`        | Triggered before viewport transformation       |\n| AFTER_TRANSFORM          | `aftertransform`         | Triggered after viewport transformation        |\n| BATCH_START              | `batchstart`             | Triggered when batch operation starts          |\n| BATCH_END                | `batchend`               | Triggered when batch operation ends            |\n| BEFORE_DESTROY           | `beforedestroy`          | Triggered before chart destruction             |\n| AFTER_DESTROY            | `afterdestroy`           | Triggered after chart destruction              |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | Triggered before renderer change               |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | Triggered after renderer change                |\n\n### Container Events (ContainerEvent)\n\n| Constant Name | Event Name | Description                                   |\n| ------------- | ---------- | --------------------------------------------- |\n| KEY_DOWN      | `keydown`  | Triggered when a keyboard key is pressed down |\n| KEY_UP        | `keyup`    | Triggered when a keyboard key is released     |\n\n### Common Events (CommonEvent)\n\nThese are events without prefixes and can be used to listen to global events:\n\n| Constant Name | Event Name     | Description                                                                        |\n| ------------- | -------------- | ---------------------------------------------------------------------------------- |\n| CLICK         | `click`        | Triggered when any element is clicked                                              |\n| DBLCLICK      | `dblclick`     | Triggered when any element is double-clicked                                       |\n| POINTER_OVER  | `pointerover`  | Triggered when the pointer enters any element                                      |\n| POINTER_LEAVE | `pointerleave` | Triggered when the pointer leaves any element                                      |\n| POINTER_ENTER | `pointerenter` | Triggered when the pointer enters any element or its child elements (non-bubbling) |\n| POINTER_MOVE  | `pointermove`  | Triggered when the pointer moves over any element                                  |\n| POINTER_OUT   | `pointerout`   | Triggered when the pointer leaves any element                                      |\n| POINTER_DOWN  | `pointerdown`  | Triggered when the pointer is pressed down on any element                          |\n| POINTER_UP    | `pointerup`    | Triggered when the pointer is released on any element                              |\n| CONTEXT_MENU  | `contextmenu`  | Triggered when the context menu is opened on any element                           |\n| DRAG_START    | `dragstart`    | Triggered when dragging any element starts                                         |\n| DRAG          | `drag`         | Triggered during any element dragging                                              |\n| DRAG_END      | `dragend`      | Triggered when any element dragging ends                                           |\n| DRAG_ENTER    | `dragenter`    | Triggered when a draggable item enters any element                                 |\n| DRAG_OVER     | `dragover`     | Triggered when a draggable item is over any element                                |\n| DRAG_LEAVE    | `dragleave`    | Triggered when a draggable item leaves any element                                 |\n| DROP          | `drop`         | Triggered when a draggable item is dropped on any element                          |\n| KEY_DOWN      | `keydown`      | Triggered when a keyboard key is pressed down                                      |\n| KEY_UP        | `keyup`        | Triggered when a keyboard key is released                                          |\n| WHEEL         | `wheel`        | Triggered when scrolling the mouse wheel                                           |\n| PINCH         | `pinch`        | Triggered when pinching or spreading fingers on a multi-touch screen               |\n\n## Tips for Use\n\n### Chain Calls\n\nG6's event API supports chain calls, allowing you to register multiple events consecutively:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Use constant enums + chain calls\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### Event Delegation\n\nYou can use the event bubbling mechanism to listen to all child element events on the parent element:\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// Handle all element click events uniformly\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('Clicked on node:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('Clicked on edge:', target.id);\n  } else {\n    console.log('Clicked on canvas blank area');\n  }\n});\n```\n\n### Event Object Properties\n\nMost event callback functions receive an event object containing the following common properties:\n\n- `target` - The element that triggered the event\n- `targetType` - The type of the element that triggered the event (node/edge/combo/canvas)\n- `originalTarget` - The original graphic that triggered the event\n- `currentTarget` - The current object that triggered the event\n- `originalEvent` - The original browser event object\n\nWith these properties, you can precisely control interactive behavior.\n","packages/site/docs/api/event.zh.md":"---\ntitle: 事件监听\norder: 11\n---\n\n## 事件系统概述\n\nG6 提供了强大的事件机制，允许你响应图表中发生的各种交互行为。例如节点点击、边悬停、画布拖拽等。通过事件系统，你可以实现复杂的交互逻辑，提升用户体验。\n\n### 事件分类\n\nG6 中的事件大致可分为以下几类：\n\n1. **元素事件**：与节点、边、Combo 相关的事件，如 `node:click`, `edge:mouseenter`\n2. **画布事件**：与整个画布相关的事件，如 `canvas:drag`, `canvas:wheel`\n3. **生命周期事件**：与图表生命周期相关的事件，如 `beforerender`, `afterrender`\n\n### 事件命名规则\n\nG6 的事件命名遵循 `[对象]:[事件]` 的格式，例如：\n\n- `node:click` - 节点点击事件\n- `edge:mouseenter` - 鼠标进入边的事件\n- `canvas:drag` - 画布拖拽事件\n\n## 最佳实践：使用常量枚举\n\nG6 提供了完整的事件常量枚举，**强烈建议**使用这些常量而非直接使用字符串事件名：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// 使用常量枚举监听事件\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**优势**：\n\n- 类型安全，避免字符串拼写错误\n- 提供智能代码提示和自动完成\n\n## API 参考\n\n### Graph.on(eventName, callback, once)\n\n监听指定的事件，当事件触发时执行回调函数。\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n| once      | 是否只监听一次           | boolean            | -      |      |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 监听节点点击事件\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // 获取被点击节点的 ID\n  console.log(`节点 ${target.id} 被点击了`);\n\n  // 获取节点数据\n  const nodeData = graph.getNodeData(target.id);\n  console.log('节点数据:', nodeData);\n\n  // 修改节点状态\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边的鼠标进入事件\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// 监听画布拖拽事件\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('画布正在被拖拽');\n});\n```\n\n### Graph.once(eventName, callback)\n\n一次性监听事件，事件触发一次后自动移除监听器。\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// 监听图表首次加载完成事件，仅执行一次\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('图表首次渲染完成');\n  // 执行一次性的初始化操作\n  highlightImportantNodes();\n});\n\n// 等待用户第一次点击某个节点后执行操作\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('用户首次点击了节点:', evt.target.id);\n  showTutorialTip('您可以拖拽节点改变位置');\n});\n```\n\n### Graph.off()\n\n移除全部事件监听器。\n\n```typescript\noff(): this;\n```\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\n// 移除所有事件监听器\ngraph.off();\nconsole.log('已移除所有事件监听器');\n```\n\n### Graph.off(eventName)\n\n移除指定事件类型的所有监听器。\n\n```typescript\noff(eventName: string): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型   | 默认值 | 必选 |\n| --------- | ---------------- | ------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 移除所有节点点击事件的监听器\ngraph.off(NodeEvent.CLICK);\nconsole.log('已移除所有节点点击事件监听器');\n\n// 在某个操作模式结束后，移除相关的临时事件监听\nfunction exitEditMode() {\n  // 移除编辑模式下的所有监听器\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('已退出编辑模式');\n}\n```\n\n### Graph.off(eventName, callback)\n\n移除特定事件的特定回调函数。\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型                     | 默认值 | 必选 |\n| --------- | ---------------- | ------------------------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string                   | -      | ✓    |\n| callback  | 要移除的回调函数 | (...args: any[]) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 定义回调函数\nconst handleNodeClick = (evt) => {\n  console.log('节点被点击:', evt.target.id);\n};\n\n// 添加监听器\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// 之后在某个时机移除这个特定的监听器\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('已移除特定的节点点击事件监听器');\n```\n\n## 事件常量枚举\n\nG6 提供了多种事件常量枚举，便于开发者使用规范的事件名称。以下是所有事件常量的详细说明：\n\n### 节点事件 (NodeEvent)\n\n| 常量名        | 事件名              | 描述                                 |\n| ------------- | ------------------- | ------------------------------------ |\n| CLICK         | `node:click`        | 点击节点时触发                       |\n| DBLCLICK      | `node:dblclick`     | 双击节点时触发                       |\n| POINTER_OVER  | `node:pointerover`  | 指针移入节点时触发                   |\n| POINTER_LEAVE | `node:pointerleave` | 指针离开节点时触发                   |\n| POINTER_ENTER | `node:pointerenter` | 指针进入节点或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `node:pointermove`  | 指针在节点上移动时触发               |\n| POINTER_OUT   | `node:pointerout`   | 指针离开节点时触发                   |\n| POINTER_DOWN  | `node:pointerdown`  | 指针在节点上按下时触发               |\n| POINTER_UP    | `node:pointerup`    | 指针在节点上抬起时触发               |\n| CONTEXT_MENU  | `node:contextmenu`  | 节点上打开上下文菜单时触发           |\n| DRAG_START    | `node:dragstart`    | 开始拖拽节点时触发                   |\n| DRAG          | `node:drag`         | 拖拽节点过程中触发                   |\n| DRAG_END      | `node:dragend`      | 拖拽节点结束时触发                   |\n| DRAG_ENTER    | `node:dragenter`    | 拖拽物进入节点时触发                 |\n| DRAG_OVER     | `node:dragover`     | 拖拽物在节点上方时触发               |\n| DRAG_LEAVE    | `node:dragleave`    | 拖拽物离开节点时触发                 |\n| DROP          | `node:drop`         | 在节点上放置拖拽物时触发             |\n\n### 边事件 (EdgeEvent)\n\n| 常量名        | 事件名              | 描述                               |\n| ------------- | ------------------- | ---------------------------------- |\n| CLICK         | `edge:click`        | 点击边时触发                       |\n| DBLCLICK      | `edge:dblclick`     | 双击边时触发                       |\n| POINTER_OVER  | `edge:pointerover`  | 指针移入边时触发                   |\n| POINTER_LEAVE | `edge:pointerleave` | 指针离开边时触发                   |\n| POINTER_ENTER | `edge:pointerenter` | 指针进入边或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `edge:pointermove`  | 指针在边上移动时触发               |\n| POINTER_OUT   | `edge:pointerout`   | 指针离开边时触发                   |\n| POINTER_DOWN  | `edge:pointerdown`  | 指针在边上按下时触发               |\n| POINTER_UP    | `edge:pointerup`    | 指针在边上抬起时触发               |\n| CONTEXT_MENU  | `edge:contextmenu`  | 边上打开上下文菜单时触发           |\n| DRAG_ENTER    | `edge:dragenter`    | 拖拽物进入边时触发                 |\n| DRAG_OVER     | `edge:dragover`     | 拖拽物在边上方时触发               |\n| DRAG_LEAVE    | `edge:dragleave`    | 拖拽物离开边时触发                 |\n| DROP          | `edge:drop`         | 在边上放置拖拽物时触发             |\n\n### Combo事件 (ComboEvent)\n\n| 常量名        | 事件名               | 描述                                  |\n| ------------- | -------------------- | ------------------------------------- |\n| CLICK         | `combo:click`        | 点击Combo时触发                       |\n| DBLCLICK      | `combo:dblclick`     | 双击Combo时触发                       |\n| POINTER_OVER  | `combo:pointerover`  | 指针移入Combo时触发                   |\n| POINTER_LEAVE | `combo:pointerleave` | 指针离开Combo时触发                   |\n| POINTER_ENTER | `combo:pointerenter` | 指针进入Combo或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `combo:pointermove`  | 指针在Combo上移动时触发               |\n| POINTER_OUT   | `combo:pointerout`   | 指针离开Combo时触发                   |\n| POINTER_DOWN  | `combo:pointerdown`  | 指针在Combo上按下时触发               |\n| POINTER_UP    | `combo:pointerup`    | 指针在Combo上抬起时触发               |\n| CONTEXT_MENU  | `combo:contextmenu`  | Combo上打开上下文菜单时触发           |\n| DRAG_START    | `combo:dragstart`    | 开始拖拽Combo时触发                   |\n| DRAG          | `combo:drag`         | 拖拽Combo过程中触发                   |\n| DRAG_END      | `combo:dragend`      | 拖拽Combo结束时触发                   |\n| DRAG_ENTER    | `combo:dragenter`    | 拖拽物进入Combo时触发                 |\n| DRAG_OVER     | `combo:dragover`     | 拖拽物在Combo上方时触发               |\n| DRAG_LEAVE    | `combo:dragleave`    | 拖拽物离开Combo时触发                 |\n| DROP          | `combo:drop`         | 在Combo上放置拖拽物时触发             |\n\n### 画布事件 (CanvasEvent)\n\n| 常量名        | 事件名                | 描述                                 |\n| ------------- | --------------------- | ------------------------------------ |\n| CLICK         | `canvas:click`        | 点击画布空白处时触发                 |\n| DBLCLICK      | `canvas:dblclick`     | 双击画布空白处时触发                 |\n| POINTER_OVER  | `canvas:pointerover`  | 指针移入画布时触发                   |\n| POINTER_LEAVE | `canvas:pointerleave` | 指针离开画布时触发                   |\n| POINTER_ENTER | `canvas:pointerenter` | 指针进入画布或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `canvas:pointermove`  | 指针在画布上移动时触发               |\n| POINTER_OUT   | `canvas:pointerout`   | 指针离开画布时触发                   |\n| POINTER_DOWN  | `canvas:pointerdown`  | 指针在画布上按下时触发               |\n| POINTER_UP    | `canvas:pointerup`    | 指针在画布上抬起时触发               |\n| CONTEXT_MENU  | `canvas:contextmenu`  | 画布上打开上下文菜单时触发           |\n| DRAG_START    | `canvas:dragstart`    | 开始拖拽画布时触发                   |\n| DRAG          | `canvas:drag`         | 拖拽画布过程中触发                   |\n| DRAG_END      | `canvas:dragend`      | 拖拽画布结束时触发                   |\n| DRAG_ENTER    | `canvas:dragenter`    | 拖拽物进入画布时触发                 |\n| DRAG_OVER     | `canvas:dragover`     | 拖拽物在画布上方时触发               |\n| DRAG_LEAVE    | `canvas:dragleave`    | 拖拽物离开画布时触发                 |\n| DROP          | `canvas:drop`         | 在画布上放置拖拽物时触发             |\n| WHEEL         | `canvas:wheel`        | 在画布上滚动鼠标滚轮时触发           |\n\n### 图表生命周期事件 (GraphEvent)\n\n| 常量名                   | 事件名                   | 描述                               |\n| ------------------------ | ------------------------ | ---------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | 画布初始化之前触发                 |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | 画布初始化之后触发                 |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | 视口尺寸变更之前触发               |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | 视口尺寸变更之后触发               |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | 元素创建之前触发                   |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | 元素创建之后触发                   |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | 元素更新之前触发                   |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | 元素更新之后触发                   |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | 元素销毁之前触发                   |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | 元素销毁之后触发                   |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | 元素平移之前触发                   |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | 元素平移之后触发                   |\n| BEFORE_DRAW              | `beforedraw`             | 绘制开始之前触发                   |\n| AFTER_DRAW               | `afterdraw`              | 绘制结束之后触发                   |\n| BEFORE_RENDER            | `beforerender`           | 渲染开始之前触发                   |\n| AFTER_RENDER             | `afterrender`            | 渲染完成之后触发                   |\n| BEFORE_ANIMATE           | `beforeanimate`          | 动画开始之前触发                   |\n| AFTER_ANIMATE            | `afteranimate`           | 动画结束之后触发                   |\n| BEFORE_LAYOUT            | `beforelayout`           | 布局开始之前触发                   |\n| AFTER_LAYOUT             | `afterlayout`            | 布局结束之后触发                   |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | 流水线布局过程中每个阶段开始前触发 |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | 流水线布局过程中每个阶段结束后触发 |\n| BEFORE_TRANSFORM         | `beforetransform`        | 可视区域变化之前触发               |\n| AFTER_TRANSFORM          | `aftertransform`         | 可视区域变化之后触发               |\n| BATCH_START              | `batchstart`             | 批处理操作开始时触发               |\n| BATCH_END                | `batchend`               | 批处理操作结束时触发               |\n| BEFORE_DESTROY           | `beforedestroy`          | 图表销毁前触发                     |\n| AFTER_DESTROY            | `afterdestroy`           | 图表销毁后触发                     |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | 渲染器变更之前触发                 |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | 渲染器变更之后触发                 |\n\n### 容器事件 (ContainerEvent)\n\n| 常量名   | 事件名    | 描述               |\n| -------- | --------- | ------------------ |\n| KEY_DOWN | `keydown` | 键盘按键按下时触发 |\n| KEY_UP   | `keyup`   | 键盘按键抬起时触发 |\n\n### 通用事件 (CommonEvent)\n\n这些是不带前缀的事件，可用于监听全局事件：\n\n| 常量名        | 事件名         | 描述                                     |\n| ------------- | -------------- | ---------------------------------------- |\n| CLICK         | `click`        | 点击任何元素时触发                       |\n| DBLCLICK      | `dblclick`     | 双击任何元素时触发                       |\n| POINTER_OVER  | `pointerover`  | 指针移入任何元素时触发                   |\n| POINTER_LEAVE | `pointerleave` | 指针离开任何元素时触发                   |\n| POINTER_ENTER | `pointerenter` | 指针进入任何元素或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `pointermove`  | 指针在任何元素上移动时触发               |\n| POINTER_OUT   | `pointerout`   | 指针离开任何元素时触发                   |\n| POINTER_DOWN  | `pointerdown`  | 指针在任何元素上按下时触发               |\n| POINTER_UP    | `pointerup`    | 指针在任何元素上抬起时触发               |\n| CONTEXT_MENU  | `contextmenu`  | 任何元素上打开上下文菜单时触发           |\n| DRAG_START    | `dragstart`    | 开始拖拽任何元素时触发                   |\n| DRAG          | `drag`         | 拖拽任何元素过程中触发                   |\n| DRAG_END      | `dragend`      | 拖拽任何元素结束时触发                   |\n| DRAG_ENTER    | `dragenter`    | 拖拽物进入任何元素时触发                 |\n| DRAG_OVER     | `dragover`     | 拖拽物在任何元素上方时触发               |\n| DRAG_LEAVE    | `dragleave`    | 拖拽物离开任何元素时触发                 |\n| DROP          | `drop`         | 在任何元素上放置拖拽物时触发             |\n| KEY_DOWN      | `keydown`      | 键盘按键按下时触发                       |\n| KEY_UP        | `keyup`        | 键盘按键抬起时触发                       |\n| WHEEL         | `wheel`        | 滚动鼠标滚轮时触发                       |\n| PINCH         | `pinch`        | 多点触控屏幕上双指捏合或张开时触发       |\n\n## 使用技巧\n\n### 链式调用\n\nG6 的事件 API 支持链式调用，可以连续注册多个事件：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 使用常量枚举+链式调用\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### 事件代理\n\n你可以利用事件冒泡机制，在父元素上监听所有子元素的事件：\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// 统一处理所有元素的点击事件\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('点击了节点:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('点击了边:', target.id);\n  } else {\n    console.log('点击了画布空白处');\n  }\n});\n```\n\n### 事件对象属性\n\n大多数事件的回调函数会接收一个事件对象，包含以下常用属性：\n\n- `target` - 触发事件的元素\n- `targetType` - 触发事件的元素类型（node/edge/combo/canvas）\n- `originalTarget` - 原始的触发事件的图形\n- `currentTarget` - 当前触发事件的对象\n- `originalEvent` - 原始的浏览器事件对象\n\n通过这些属性，你可以精确地控制交互行为。\n","packages/site/docs/api/export-image.en.md":"---\ntitle: Export Image\norder: 12\n---\n\n## Overview of Image Export\n\nG6 provides the functionality to export the graph as an image, allowing you to export the current canvas content as a DataURL format. This is convenient for saving, sharing, or further processing. The exported image will retain all visible elements on the canvas, including nodes, edges, combos, and other custom graphics.\n\n## API Reference\n\n### Graph.toDataURL(options)\n\nExport the current canvas as an image in DataURL format.\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**Parameters**\n\n| Parameter | Description                | Type                      | Default | Required |\n| --------- | -------------------------- | ------------------------- | ------- | -------- |\n| options   | Export image configuration | Partial\\<DataURLOptions\\> | -       |          |\n\n**Return Value**\n\nReturns a Promise that resolves to a DataURL string representing the image.\n\n**DataURLOptions Type Definition**\n\n| Parameter      | Type                                        | Required | Description                                                                                              |\n| -------------- | ------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |\n| mode           | 'viewport' \\| 'overall'                     | No       | Export mode <br/> - viewport: Export viewport content <br/> - overall: Export entire canvas              |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | No       | Image type <br/> - image/png: PNG format <br/> - image/jpeg: JPEG format <br/> - image/webp: WebP format |\n| encoderOptions | number                                      | No       | Image quality, only effective for image/jpeg and image/webp, range 0 ~ 1                                 |\n\n## Download Image\n\nG6 5.0 only provides an API to export the canvas as a Base64 image ([toDataURL](#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=Note}\nThe exported image content may not include the complete canvas content. The export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., which will not appear in the exported image.\n:::\n","packages/site/docs/api/export-image.zh.md":"---\ntitle: 导出图片\norder: 12\n---\n\n## 图片导出概述\n\nG6 提供了将图导出为图片的功能，可以将当前画布内容导出为 DataURL 格式，方便保存、分享或进一步处理。导出的图片会保留画布上的所有可见元素，包括节点、边、组合以及其他自定义图形。\n\n## API 参考\n\n### Graph.toDataURL(options)\n\n将当前画布导出为 DataURL 格式的图片。\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**参数**\n\n| 参数    | 描述         | 类型                      | 默认值 | 必选 |\n| ------- | ------------ | ------------------------- | ------ | ---- |\n| options | 导出图片配置 | Partial\\<DataURLOptions\\> | -      |      |\n\n**返回值**\n\n返回一个 Promise，解析为表示图片的 DataURL 字符串。\n\n**DataURLOptions 类型定义**\n\n| 参数           | 类型                                        | 必选 | 描述                                                                                             |\n| -------------- | ------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------ |\n| mode           | 'viewport' \\| 'overall'                     | 否   | 导出模式 <br/> - viewport: 导出视口内容 <br/> - overall: 导出整个画布                            |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | 否   | 图片类型 <br/> - image/png: PNG 格式 <br/> - image/jpeg: JPEG 格式 <br/> - image/webp: WebP 格式 |\n| encoderOptions | number                                      | 否   | 图片质量，仅对 image/jpeg 和 image/webp 有效，取值范围 0 ~ 1                                     |\n\n## 下载图片\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","packages/site/docs/api/graph.en.md":"---\ntitle: Graph Instance\norder: 2\n---\n\n## API Reference\n\n### Graph.destroy()\n\nDestroy the current graph instance and release all resources related to it.\n\n⚠️ **Note**: After destruction, no operations can be performed. If you need to use it again, you must create a new graph instance.\n\n```typescript\ndestroy(): void;\n```\n\n**Usage Scenarios**:\n\n- When the user closes the chart or switches to another view, this method can be called to release resources.\n- When needing to recreate a graph instance, ensure the old instance is destroyed first to avoid memory leaks.\n","packages/site/docs/api/graph.zh.md":"---\ntitle: 图实例\norder: 2\n---\n\n## API 参考\n\n### Graph.destroy()\n\n销毁当前图实例，释放与图实例相关的所有资源。\n\n⚠️ **注意**: 销毁后无法进行任何操作，如果需要重新使用，需要重新创建一个新的图实例。\n\n```typescript\ndestroy(): void;\n```\n\n**使用场景**:\n\n- 当用户关闭图表或切换到其他视图时，可以调用此方法来释放资源。\n- 在需要重新创建图实例时，确保先销毁旧的实例，以避免内存泄漏。\n","packages/site/docs/api/layout.en.md":"---\ntitle: Layout\norder: 6\n---\n\n## Overview of Layout\n\n[Layout](/en/manual/layout/overview) is a crucial part of graph visualization, determining the positioning of nodes on the canvas. G6 offers a variety of layout algorithms to meet different data structures and visualization needs. Through the layout API, you can:\n\n- Set and update the graph's layout configuration\n- Execute or stop layout calculations\n- Combine multiple layout strategies\n- Customize layout algorithms\n\nA suitable layout can clearly display the relationship patterns between nodes, enhancing the graph's readability and aesthetics.\n\n## API Reference\n\n### Graph.setLayout(layout)\n\nSet the graph's layout algorithm and configuration.\n\n⚠️ **Note**: Calling this function won't automatically re-layout, so there's need to call `graph.layout()` separately.\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                        | Type                                                                        | Default | Required |\n| --------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layout    | Layout configuration object, or a function returning a new configuration based on the previous one | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       | ✓        |\n\n**Example 1**: Set a force-directed layout\n\n```typescript\n// Set a simple force-directed layout\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // Prevent node overlap\n  nodeStrength: -50, // Repulsion between nodes, negative value for repulsion\n  edgeStrength: 0.5, // Edge strength, affects edge length\n});\n```\n\n**Example 2**: Update layout using a function\n\n```typescript\n// Update based on the current layout configuration\ngraph.setLayout((prevLayout) => {\n  // If the previous layout was force-directed, adjust its parameters\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // Increase repulsion\n      alphaDecay: 0.01, // Lower decay rate for more iteration time\n    };\n  }\n\n  // Otherwise, switch to radial layout\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**Example 3**: Set a combined layout\n\n```typescript\n// Set a combined layout - different nodes use different layout algorithms\ngraph.setLayout([\n  {\n    type: 'grid',\n    // Filter function: only nodes with type 'main' participate in the layout\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\nGet the current layout configuration.\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**Return Value**\n\n- **Type**: [LayoutOptions](#layoutoptions)\n- **Description**: The current layout configuration object\n\n**Example**\n\n```typescript\n// Get the current layout configuration\nconst currentLayout = graph.getLayout();\nconsole.log('Current layout type:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\nExecute layout calculations. When graph data changes, call this method to trigger the layout algorithm to recalculate node positions.\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter     | Description                 | Type                                                                        | Default | Required |\n| ------------- | --------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layoutOptions | Layout configuration object | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       |          |\n\nIf `layoutOptions` is provided, it takes precedence over the graph's current layout configuration.\n\n**Note**\n\nLayout calculation is an asynchronous process, especially for complex layout algorithms like force-directed layout. This method returns a Promise, which can be used to perform subsequent operations after the layout is complete.\n\n**Example 1**: Basic usage\n\n```typescript\n// Execute layout\nawait graph.layout();\nconsole.log('Layout calculation complete');\n```\n\n**Example 2**: Re-layout after adding data\n\n```typescript\n// Add new nodes and edges\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// Draw new nodes and edges\nawait graph.draw();\n\n// Recalculate layout\nawait graph.layout();\n```\n\n**Example 3**: Listen to layout events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before layout starts\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('Layout calculation starting...');\n});\n\n// After layout completes\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('Layout calculation complete');\n});\n\n// Execute layout\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\nStop an ongoing layout calculation. Mainly used to stop iterative layout algorithms like force-directed layout.\n\n```typescript\nstopLayout(): void;\n```\n\n**Note**\n\nApplicable to layouts with iterative animations, currently `force` belongs to this category. If the layout calculation takes too long, you can manually stop the iteration.\n\n**Example 1**: Basic usage\n\n```typescript\n// Stop layout after 5 seconds\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('Layout manually stopped');\n}, 5000);\n```\n\n**Example 2**: Stop layout with user interaction\n\n```typescript\n// Stop layout when the user clicks the canvas\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('User clicked canvas, layout stopped');\n});\n```\n\n## Type Definitions\n\n### LayoutOptions\n\nLayout configuration type, can be a single layout configuration or an array of layout configurations.\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\nSingle layout configuration, can be a built-in layout configuration or a custom base layout configuration.\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\nBasic configuration items common to all layout types.\n\n```typescript\ninterface BaseLayoutOptions {\n  // Layout type\n  type: string;\n\n  // Node filter function for participating in the layout\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // Whether to calculate the layout before initializing elements\n  preLayout?: boolean;\n\n  // Whether invisible nodes participate in the layout (effective when preLayout is true)\n  isLayoutInvisibleNodes?: boolean;\n\n  // Enable layout animation, for iterative layouts, animation transitions occur between iterations\n  animation?: boolean;\n\n  // Whether to run the layout in a WebWorker\n  enableWorker?: boolean;\n\n  // Number of iterations for iterative layouts\n  iterations?: number;\n\n  // Other specific layout configuration items\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nConfiguration for G6's built-in layout types, see [API - Built-in Layouts](/en/manual/layout/antv-dagre-layout) for details.\n","packages/site/docs/api/layout.zh.md":"---\ntitle: 布局\norder: 6\n---\n\n## 布局概述\n\n[布局](/manual/layout/overview) 是图可视化中至关重要的一环，它决定了节点在画布上的位置排布。G6 提供了多种布局算法，以满足不同数据结构和可视化需求。通过布局 API，你可以：\n\n- 设置和更新图的布局配置\n- 执行或停止布局计算\n- 组合多种布局策略\n- 自定义布局算法\n\n合适的布局可以清晰地展示节点间的关系模式，提高图的可读性和美观度。\n\n## API 参考\n\n### Graph.setLayout(layout)\n\n设置图的布局算法及配置。\n\n⚠️ **注意**: 调用此函数不会自动重新布局，需要单独调用 `graph.layout()`。\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**参数**\n\n| 参数   | 描述                                               | 类型                                                                        | 默认值 | 必选 |\n| ------ | -------------------------------------------------- | --------------------------------------------------------------------------- | ------ | ---- |\n| layout | 布局配置对象，或者一个基于之前配置返回新配置的函数 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      | ✓    |\n\n**示例 1**: 设置力导向布局\n\n```typescript\n// 设置简单的力导向布局\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // 防止节点重叠\n  nodeStrength: -50, // 节点间斥力，负值为斥力\n  edgeStrength: 0.5, // 边的强度，会影响边的长度\n});\n```\n\n**示例 2**: 使用函数式更新布局\n\n```typescript\n// 基于当前布局配置进行更新\ngraph.setLayout((prevLayout) => {\n  // 如果之前是力导向布局，调整其参数\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // 增加斥力\n      alphaDecay: 0.01, // 降低衰减率，让布局有更多迭代时间\n    };\n  }\n\n  // 否则切换到放射状布局\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**示例 3**: 设置组合布局\n\n```typescript\n// 设置组合布局 - 不同的节点使用不同的布局算法\ngraph.setLayout([\n  {\n    type: 'grid',\n    // 过滤函数：只有type为'main'的节点参与布局\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\n获取当前的布局配置。\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**返回值**\n\n- **类型**: [LayoutOptions](#layoutoptions)\n- **描述**: 当前的布局配置对象\n\n**示例**\n\n```typescript\n// 获取当前布局配置\nconst currentLayout = graph.getLayout();\nconsole.log('当前布局类型:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\n执行布局计算。当图数据发生变化后，调用此方法可触发布局算法重新计算节点位置。\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**参数**\n\n| 参数          | 描述         | 类型                                                                        | 默认值 | 必选 |\n| ------------- | ------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| layoutOptions | 布局配置对象 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      |      |\n\n如果传入 `layoutOptions`，则优先考虑传入的布局配置，否则使用图的当前布局配置进行布局。\n\n**说明**\n\n布局计算是一个异步过程，特别是对于复杂的布局算法（如力导向布局）。此方法返回一个 Promise，可以用于在布局完成后执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 执行布局\nawait graph.layout();\nconsole.log('布局计算完成');\n```\n\n**示例 2**: 添加数据后重新布局\n\n```typescript\n// 添加新节点和边\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// 绘制新节点和边\nawait graph.draw();\n\n// 重新计算布局\nawait graph.layout();\n```\n\n**示例 3**: 监听布局事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 布局开始前\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('布局计算开始...');\n});\n\n// 布局完成后\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('布局计算完成');\n});\n\n// 执行布局\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\n停止正在进行中的布局计算。主要用于停止迭代类型的布局算法，如力导向布局。\n\n```typescript\nstopLayout(): void;\n```\n\n**说明**\n\n适用于带有迭代动画的布局，目前有 `force` 属于此类布局。当布局计算时间过长时，可以手动停止迭代。\n\n**示例 1**: 基本使用\n\n```typescript\n// 5秒后停止布局\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('布局已手动停止');\n}, 5000);\n```\n\n**示例 2**: 结合用户交互停止布局\n\n```typescript\n// 当用户点击画布时停止布局\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('用户点击画布，布局已停止');\n});\n```\n\n## 类型定义\n\n### LayoutOptions\n\n布局配置类型，可以是单一布局配置或布局配置数组。\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\n单一布局配置，可以是内置布局配置或自定义基础布局配置。\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\n所有布局类型共有的基础配置项。\n\n```typescript\ninterface BaseLayoutOptions {\n  // 布局类型\n  type: string;\n\n  // 参与该布局的节点过滤函数\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // 是否在初始化元素前计算布局\n  preLayout?: boolean;\n\n  // 不可见节点是否参与布局（当 preLayout 为 true 时生效）\n  isLayoutInvisibleNodes?: boolean;\n\n  // 启用布局动画，对于迭代布局，会在两次迭代之间进行动画过渡\n  animation?: boolean;\n\n  // 是否在 WebWorker 中运行布局\n  enableWorker?: boolean;\n\n  // 迭代布局的迭代次数\n  iterations?: number;\n\n  // 其他特定布局的配置项\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nG6 内置的布局类型配置，具体请查看 [API - 内置布局](/manual/layout/antv-dagre-layout)。\n","packages/site/docs/api/option.en.md":"---\ntitle: Graph Options\norder: 7\n---\n\n## Overview of Graph Options\n\nThe [options](/en/manual/graph/option) of a G6 graph instance control various aspects of the graph, including canvas settings, viewport properties, data, layout, styles, interaction behaviors, plugins, and more. By configuring these options appropriately, you can flexibly customize the appearance and behavior of the graph.\n\nOptions can be specified when creating a graph instance or dynamically modified at runtime through the API. Some basic configurations (such as devicePixelRatio, container) require destroying and recreating the graph instance to take effect after modification.\n\n## API Reference\n\n### Graph.getOptions()\n\nRetrieve all configuration options of the current graph.\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**Return Value**\n\n- **Type**: [GraphOptions](/en/manual/graph/option)\n- **Description**: Complete configuration options of the current graph\n\n**Example**\n\n```typescript\n// Retrieve the current graph's options\nconst options = graph.getOptions();\nconsole.log('Current graph options:', options);\n\n// Retrieve specific options\nconsole.log('Current canvas width:', options.width);\nconsole.log('Current layout options:', options.layout);\n```\n\n### Graph.setOptions(options)\n\nUpdate the graph's configuration options.\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                    | Default | Required |\n| --------- | ------------------------- | --------------------------------------- | ------- | -------- |\n| options   | New configuration options | [GraphOptions](/en/manual/graph/option) | -       | ✓        |\n\n**Note**\n\n⚠️ **Attention**: To update basic properties like devicePixelRatio, container, etc., you need to destroy the current graph instance and recreate it. Most other configurations can be dynamically updated.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Update graph configuration\ngraph.setOptions({\n  width: 1000, // Update width\n  height: 800, // Update height\n  autoFit: 'view', // Enable auto-fit\n  animation: true, // Enable animation\n});\n```\n\n**Example 2**: Update Theme\n\n```typescript\n// Update graph theme configuration\ngraph.setOptions({\n  theme: {\n    type: 'dark', // Switch to dark theme\n    // Custom theme configuration\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**Example 3**: Update Layout Configuration\n\n```typescript\n// Update layout configuration\ngraph.setOptions({\n  layout: {\n    type: 'force', // Switch to force-directed layout\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**Example 4**: Update Default Node and Edge Configuration\n\n```typescript\n// Update default style configuration for nodes and edges\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n\n## Type Definitions\n\n### GraphOptions\n\n```typescript\ntype GraphOptions = {\n  // Whether to enable zooming\n  enableZoom?: boolean;\n\n  // Whether to enable dragging\n  enableDrag?: boolean;\n\n  // Default style for nodes\n  defaultNodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Additional configuration options for the graph\n  [configKey: string]: any;\n};\n```\n","packages/site/docs/api/option.zh.md":"---\ntitle: 图配置项\norder: 7\n---\n\n## 图配置项概述\n\nG6 图实例的 [配置项](/manual/graph/option) 控制着图的各个方面，包括画布设置、视口属性、数据、布局、样式、交互行为、插件等。通过合理配置这些选项，可以灵活定制图的外观和行为。\n\n配置项可以在图实例创建时指定，也可以通过 API 在运行时动态修改。某些基础配置（如 devicePixelRatio、container）修改后需要销毁并重新创建图实例才能生效。\n\n## API 参考\n\n### Graph.getOptions()\n\n获取当前图表的所有配置项。\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**返回值**\n\n- **类型**: [GraphOptions](/manual/graph/option)\n- **描述**: 当前图表的完整配置项\n\n**示例**\n\n```typescript\n// 获取当前图表的配置项\nconst options = graph.getOptions();\nconsole.log('当前图表配置:', options);\n\n// 获取特定配置\nconsole.log('当前画布宽度:', options.width);\nconsole.log('当前布局配置:', options.layout);\n```\n\n### Graph.setOptions(options)\n\n更新图表的配置项。\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**参数**\n\n| 参数    | 描述       | 类型                                 | 默认值 | 必选 |\n| ------- | ---------- | ------------------------------------ | ------ | ---- |\n| options | 新的配置项 | [GraphOptions](/manual/graph/option) | -      | ✓    |\n\n**说明**\n\n⚠️ **注意**: 要更新 devicePixelRatio、container 等基础属性，需要销毁当前图实例后重新创建。其他大部分配置可以动态更新。\n\n**示例 1**: 基本用法\n\n```typescript\n// 更新图表配置\ngraph.setOptions({\n  width: 1000, // 更新宽度\n  height: 800, // 更新高度\n  autoFit: 'view', // 开启自适应\n  animation: true, // 启用动画\n});\n```\n\n**示例 2**: 更新主题\n\n```typescript\n// 更新图表主题配置\ngraph.setOptions({\n  theme: {\n    type: 'dark', // 切换到暗色主题\n    // 自定义主题配置\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**示例 3**: 更新布局配置\n\n```typescript\n// 更新布局配置\ngraph.setOptions({\n  layout: {\n    type: 'force', // 切换到力导向布局\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**示例 4**: 更新节点和边的默认配置\n\n```typescript\n// 更新节点和边的默认样式配置\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n","packages/site/docs/api/plugin.en.md":"---\ntitle: Plugin\norder: 8\n---\n\n## Overview of Plugins\n\n[Plugins](/en/manual/plugin/overview) are an important mechanism in G6 for extending functionality and enhancing the interactive experience of graphs. Plugins typically provide independent functional modules, such as thumbnails, toolbars, context menus, etc. They integrate well with the main graph while maintaining modular and maintainable code.\n\nThe plugin system is designed to follow the \"plug and play\" principle, allowing dynamic addition or removal as needed.\n\n## API Reference\n\n### Graph.getPluginInstance(key)\n\nRetrieve the plugin instance specified by the key, used to access and operate the methods provided by the plugin.\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**Parameters**\n\n| Parameter | Description                     | Type   | Default | Required |\n| --------- | ------------------------------- | ------ | ------- | -------- |\n| key       | Unique identifier of the plugin | string | -       | ✓        |\n\n**Return Value**\n\n- **Type**: Plugin instance\n- **Description**: The plugin instance corresponding to the specified key\n\n**Note**\n\nMany plugins provide specific API methods, which can be directly called by obtaining the plugin instance. For example, the fullscreen plugin provides `request()` and `exit()` methods to control fullscreen status.\n\n**Example**: Operate the fullscreen plugin\n\n```typescript\n// Get the fullscreen plugin instance\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// Request to enter fullscreen\nfullscreen.request();\n\n// Exit fullscreen later\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\nRetrieve all configured plugins in the current graph.\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**Return Value**\n\n- **Type**: [PluginOptions](#pluginoptions)\n- **Description**: All configured plugins in the current graph\n\n**Example**\n\n```typescript\n// Get all plugin configurations\nconst plugins = graph.getPlugins();\n\n// View currently active plugins\nconsole.log('Current graph plugin configurations:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\nSet the graph's plugins, replacing all existing plugin configurations.\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                     | Type                                                                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| plugins   | New plugin configurations, or a function returning new configurations based on the current ones | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -       | ✓        |\n\n**Note**\n\nThe set plugins will completely replace the original plugin configurations. To add new plugins based on existing ones, you can use functional updates:\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**Example 1**: Set basic plugins\n\n```typescript\n// Set multiple basic plugins\ngraph.setPlugins([\n  // String form (using default configuration)\n  'minimap',\n\n  // Object form (custom configuration)\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**Example 2**: Use functional updates\n\n```typescript\n// Add new plugins to existing configurations\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// Replace specific plugins\ngraph.setPlugins((currentPlugins) => {\n  // Filter out existing grid plugins\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // Add new grid plugin configuration\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\nUpdate the configuration of a specified plugin, identified by the `key` of the plugin to be updated.\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                               | Type                                      | Default | Required |\n| --------- | ----------------------------------------- | ----------------------------------------- | ------- | -------- |\n| plugin    | Configuration of the plugin to be updated | [UpdatePluginOption](#updatepluginoption) | -       | ✓        |\n\n**Note**\n\nTo update a plugin, the `key` field must be specified in the original plugin configuration to accurately locate and update the plugin.\n\n**Example 1**: Update plugin configuration\n\n```typescript\n// Specify key when initially setting plugins\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// Update grid plugin configuration\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## Type Definitions\n\n### PluginOptions\n\nPlugin configuration type, representing an array of plugin configurations.\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\nCustom plugin configuration interface, used to configure plugin parameters.\n\n```typescript\ntype CustomPluginOption = {\n  // Plugin type\n  type: string;\n\n  // Plugin key, i.e., unique identifier\n  // Used to identify the plugin for further operations\n  key?: string;\n\n  // Other configuration items for different types of plugins\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\nConfiguration interface for updating plugins, used to dynamically modify plugin parameters.\n\n```typescript\ntype UpdatePluginOption = {\n  // Unique identifier of the plugin to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/plugin.zh.md":"---\ntitle: 插件\norder: 8\n---\n\n## 插件概述\n\n[插件](/manual/plugin/overview)（Plugin）是 G6 中扩展功能的重要机制，用于增强图表的功能和交互体验。插件通常提供一些独立的功能模块，如缩略图、工具栏、上下文菜单等，它们可以与图表主体良好集成，同时又保持代码的模块化和可维护性。\n\n插件系统设计遵循\"即插即用\"的原则，可以根据需要动态添加或移除。\n\n## API 参考\n\n### Graph.getPluginInstance(key)\n\n获取指定 key 的插件实例，用于访问和操作插件提供的方法。\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**参数**\n\n| 参数 | 描述             | 类型   | 默认值 | 必选 |\n| ---- | ---------------- | ------ | ------ | ---- |\n| key  | 插件的唯一标识符 | string | -      | ✓    |\n\n**返回值**\n\n- **类型**: 插件实例\n- **描述**: 指定 key 对应的插件实例\n\n**说明**\n\n许多插件提供了特定的API方法，通过获取插件实例可以直接调用这些方法。例如，全屏插件提供了 `request()` 和 `exit()` 方法来控制全屏状态。\n\n**示例**: 操作全屏插件\n\n```typescript\n// 获取全屏插件实例\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// 请求进入全屏\nfullscreen.request();\n\n// 稍后退出全屏\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\n获取当前图表中所有已配置的插件。\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**返回值**\n\n- **类型**: [PluginOptions](#pluginoptions)\n- **描述**: 当前图表中已配置的所有插件\n\n**示例**\n\n```typescript\n// 获取所有插件配置\nconst plugins = graph.getPlugins();\n\n// 查看当前激活的插件\nconsole.log('当前图表的插件配置:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\n设置图表的插件，将替换所有现有的插件配置。\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**参数**\n\n| 参数    | 描述                                             | 类型                                                                        | 默认值 | 必选 |\n| ------- | ------------------------------------------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| plugins | 新的插件配置，或一个基于当前配置返回新配置的函数 | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -      | ✓    |\n\n**说明**\n\n设置的插件会全量替换原有的插件配置。如果需要在现有插件基础上添加新插件，可以使用函数式更新方式：\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**示例 1**: 设置基本插件\n\n```typescript\n// 设置多个基本插件\ngraph.setPlugins([\n  // 字符串形式（使用默认配置）\n  'minimap',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**示例 2**: 使用函数式更新\n\n```typescript\n// 添加新插件到现有配置\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// 替换特定插件\ngraph.setPlugins((currentPlugins) => {\n  // 过滤掉现有的网格插件\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // 添加新的网格插件配置\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\n更新指定的插件配置，需要通过 `key` 标识要更新的插件。\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**参数**\n\n| 参数   | 描述           | 类型                                      | 默认值 | 必选 |\n| ------ | -------------- | ----------------------------------------- | ------ | ---- |\n| plugin | 更新的插件配置 | [UpdatePluginOption](#updatepluginoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个插件，必须在原始插件配置中指定 `key` 字段，以便能够准确找到并更新该插件。\n\n**示例 1**: 更新插件配置\n\n```typescript\n// 初始设置插件时指定 key\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// 更新网格插件配置\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## 类型定义\n\n### PluginOptions\n\n插件配置类型，表示一组插件配置的数组。\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\n自定义插件配置接口，用于配置插件参数。\n\n```typescript\ntype CustomPluginOption = {\n  // 插件类型\n  type: string;\n\n  // 插件 key，即唯一标识\n  // 用于标识插件，从而进一步操作此插件\n  key?: string;\n\n  // 针对不同类型的插件，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\n更新插件的配置接口，用于动态修改插件参数。\n\n```typescript\ntype UpdatePluginOption = {\n  // 要更新的插件的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/render.en.md":"---\ntitle: Drawing and Rendering\norder: 3\n---\n\n## Overview of Drawing and Rendering\n\nG6 provides a series of drawing and rendering-related APIs to control the display process of graphical elements. In G6, drawing and rendering are two different concepts:\n\n- **Drawing (draw)**: Responsible only for drawing graphical elements onto the canvas, without involving layout calculations.\n- **Rendering (render)**: A complete rendering process, including data processing, layout calculations, and final drawing.\n\nUnderstanding the differences between these APIs is crucial for optimizing performance and achieving specific effects.\n\n## API Reference\n\n### Graph.draw()\n\nDraw elements without performing layout calculations.\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**Note**\n\nThe `draw` method only executes the drawing process of elements and does not recalculate the layout.\n\n⚠️ **Attention**: `draw` is an asynchronous method, requiring the use of `await` or Promise chaining to ensure subsequent operations are executed after drawing is complete.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.draw();\n```\n\n**Example 2**: Redraw after modifying node styles\n\n```javascript\n// Redraw after modifying node styles\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// Only draw the updated styles without re-layout\nawait graph.draw();\n```\n\n**Example 3**: Batch update multiple elements and draw once\n\n```javascript\n// Update multiple nodes\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// Update edges\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// Draw after batch operations\nawait graph.draw();\n```\n\n**Example 4**: Use event listener to detect drawing completion\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('Drawing complete');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\nExecute the complete rendering process, including data processing, layout calculations, and drawing.\n\n```typescript\nrender(): Promise<void>;\n```\n\n**Note**\n\nThe `render` method executes the complete rendering process:\n\n1. Process data updates\n2. Draw elements onto the canvas\n3. Execute layout algorithms\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.render();\n```\n\n**Example 2**: Render after adding new data\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**Example 3**: Listen to rendering events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before rendering starts\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('Rendering starts...');\n  // Show loading indicator\n  showLoadingIndicator();\n});\n\n// After rendering completes\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('Rendering complete');\n  // Hide loading indicator\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\nClear all elements on the canvas, including nodes, edges, and other graphical elements.\n\n```typescript\nclear(): Promise<void>;\n```\n\n**Note**\n\nThis method deletes all elements in the graph but retains the canvas configuration and styles. It is an asynchronous method that returns a Promise.\n\n**Example**\n\n```typescript\n// Basic usage\nawait graph.clear();\n```\n\n## Usage Tips\n\n### Choosing between draw and render\n\n- Use `draw()` when:\n  - Only the styles or states of elements are modified, without needing to recalculate positions.\n  - Performance-sensitive, aiming to avoid unnecessary layout calculations.\n- Use `render()` when:\n  - Initializing the graph.\n  - Changing layout configurations.\n  - Adding or removing a large number of nodes/edges.\n  - Need to recalculate positions of all elements.\n","packages/site/docs/api/render.zh.md":"---\ntitle: 绘制与渲染\norder: 3\n---\n\n## 绘制与渲染概述\n\nG6 提供了一系列绘制和渲染相关的 API，用于控制图形元素的显示过程。在 G6 中，绘制和渲染是两个不同的概念：\n\n- **绘制(draw)**: 仅负责将图形元素绘制到画布上，不涉及布局计算\n- **渲染(render)**: 完整的渲染流程，包括数据处理、布局计算和最终绘制\n\n理解这些 API 的区别对于优化性能和实现特定效果至关重要。\n\n## API 参考\n\n### Graph.draw()\n\n绘制元素，但不执行布局计算。\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**说明**\n\n`draw` 方法仅执行元素的绘制过程，不会重新计算布局。\n\n⚠️ **注意**: `draw` 为异步方法，需要使用 `await` 或 Promise 链式调用来确保绘制完成后再执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 基本用法\nawait graph.draw();\n```\n\n**示例 2**: 修改节点样式后重新绘制\n\n```javascript\n// 修改节点样式后重新绘制\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 仅绘制更新后的样式，不重新布局\nawait graph.draw();\n```\n\n**示例 3**: 批量更新多个元素后一次性绘制\n\n```javascript\n// 更新多个节点\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// 更新边\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// 批量操作完成后绘制\nawait graph.draw();\n```\n\n**示例 4**: 使用事件监听绘制完成\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('绘制完成');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\n执行完整的渲染流程，包括数据处理、布局计算和绘制。\n\n```typescript\nrender(): Promise<void>;\n```\n\n**说明**\n\n`render` 方法会执行完整的渲染流程：\n\n1. 处理数据更新\n2. 绘制元素到画布上\n3. 执行布局算法\n\n**示例 1**: 基本用法\n\n```typescript\n// 基本用法\nawait graph.render();\n```\n\n**示例 2**: 添加新数据后渲染\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**示例 3**: 监听渲染事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 渲染开始前\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('渲染开始...');\n  // 显示加载指示器\n  showLoadingIndicator();\n});\n\n// 渲染完成后\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('渲染完成');\n  // 隐藏加载指示器\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\n清空画布上的所有元素，包括节点、边和其他图形元素。\n\n```typescript\nclear(): Promise<void>;\n```\n\n**说明**\n\n此方法会删除图中的所有元素，但保留画布配置和样式。这是一个异步方法，返回一个 Promise。\n\n**示例**\n\n```typescript\n// 基本用法\nawait graph.clear();\n```\n\n## 使用技巧\n\n### draw 与 render 的选择\n\n- 使用 `draw()` 当:\n  - 仅修改了元素样式或状态，不需要重新计算位置\n  - 性能敏感，希望避免不必要的布局计算\n- 使用 `render()` 当:\n  - 初始化图表\n  - 更改了布局配置\n  - 添加或删除了大量节点/边\n  - 需要重新计算所有元素位置\n","packages/site/docs/api/theme.en.md":"---\ntitle: Theme\norder: 9\n---\n\n## Overview of Theme\n\nG6 allows users to customize the appearance of graphs through themes. Themes can be used to define colors, shapes, and styles for nodes, edges, and other graph elements.\n\n## API Reference\n\n### Graph.getTheme()\n\nGet the theme\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>Related Parameters</summary>\n\n**Return Value**:\n\n- **Type:** false \\| 'light' \\| 'dark' \\| string\n\n- **Description:** Current theme\n\n</details>\n\n### Graph.setTheme(theme)\n\nSet the theme\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**Example**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>Related Parameters</summary>\n\n<table><thead><tr><th>\n\nParameter\n\n</th><th>\n\nType\n\n</th><th>\n\nDescription\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) => false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\nTheme name\n\n</td></tr>\n</tbody></table>\n\n**Return Value**:\n\n- **Type:** void\n\n</details>\n\n## Type Definitions\n\n### ThemeOptions\n\n```typescript\ntype ThemeOptions = {\n  // Colors used in the theme\n  colors: string[];\n\n  // Node style settings\n  nodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Edge style settings\n  edgeStyle?: {\n    stroke: string;\n  };\n\n  // Additional configuration options for the theme\n  [configKey: string]: any;\n};\n```\n","packages/site/docs/api/theme.zh.md":"---\ntitle: 主题\norder: 9\n---\n\n## API 参考\n\n### Graph.getTheme()\n\n获取主题\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>相关参数</summary>\n\n**返回值**：\n\n- **类型：** false \\| 'light' \\| 'dark' \\| string\n\n- **描述：** 当前主题\n\n</details>\n\n### Graph.setTheme(theme)\n\n设置主题\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**示例**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>相关参数</summary>\n\n<table><thead><tr><th>\n\n参数\n\n</th><th>\n\n类型\n\n</th><th>\n\n描述\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) =&gt; false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\n主题名\n\n</td></tr>\n</tbody></table>\n\n**返回值**：\n\n- **类型：** void\n\n</details>\n","packages/site/docs/api/transform.en.md":"---\ntitle: Data Transformation\norder: 10\n---\n\n## Overview of Data Transformation\n\n[Data Transformation](/en/manual/transform/overview) is a powerful feature in G6 that allows for processing and transforming data during the graph rendering process. With data transformers, you can achieve various data processing needs, such as:\n\n- Data Filtering: Filter nodes and edges to be displayed based on conditions\n- Data Calculation: Generate new attributes based on original data, such as calculating node size based on the number of connections, without polluting the original data\n- Data Aggregation: Aggregate a large number of nodes into fewer nodes to improve the performance of large-scale graphs\n\nData transformation occurs at specific stages of the rendering process, allowing flexible changes to the final presentation without modifying the original data source.\n\n## API Reference\n\n### Graph.getTransforms()\n\nRetrieve all configured data transformers in the current graph.\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**Return Value**\n\n- **Type**: [TransformOptions](#transformoptions)\n- **Description**: All configured data transformers in the current graph\n\n**Example**\n\n```typescript\n// Retrieve all data transformers\nconst transforms = graph.getTransforms();\nconsole.log('Data transformers in the current graph:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\nSet the data transformers for the graph, replacing all existing transformers.\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**Parameters**\n\n| Parameter  | Description                                                                                               | Type                                                                                  | Default | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------- | -------- |\n| transforms | New data transformer configurations, or a function returning new configurations based on the current ones | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -       | ✓        |\n\n**Note**\n\nData transformers can process data at different stages of the graph rendering process. The set data transformations will completely replace the original ones. To add new data transformations based on existing ones, you can use functional updates.\n\n**Example 1**: Set basic data transformations\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**Example 2**: Set data transformations with configurations\n\n```typescript\ngraph.setTransforms([\n  // String form (using default configuration)\n  'process-parallel-edges',\n\n  // Object form (custom configuration)\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // Distance between parallel edges\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new data transformations to existing configurations\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\nUpdate the configuration of a specified data transformer, identified by the `key` of the transformer to be updated.\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                         | Type                                            | Default | Required |\n| --------- | --------------------------------------------------- | ----------------------------------------------- | ------- | -------- |\n| transform | Configuration of the data transformer to be updated | [UpdateTransformOption](#updatetransformoption) | -       | ✓        |\n\n**Note**\n\nTo update a data transformer, the `key` field must be specified in the original data transformer configuration to accurately locate and update the transformer.\n\n**Example**: Update data transformer configuration\n\n```typescript\n// Specify key when initially setting data transformers\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// Update distance between parallel edges\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## Type Definitions\n\n### TransformOptions\n\nData transformer configuration type, representing an array of data transformer configurations.\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\nCustom data transformer configuration interface, used to configure data processing parameters.\n\n```typescript\ntype CustomTransformOption = {\n  // Data processing type\n  type: string;\n\n  // Unique identifier for the data transformer\n  key?: string;\n\n  // Other configuration items for different types of data processing\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\nConfiguration interface for updating data transformers, used to dynamically modify data processing parameters.\n\n```typescript\ntype UpdateTransformOption = {\n  // Unique identifier of the data transformer to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/transform.zh.md":"---\ntitle: 数据处理\norder: 10\n---\n\n## 数据处理概述\n\n[数据处理](/manual/transform/overview)（Transform）是 G6 中一项强大的功能，允许在图渲染过程中对数据进行处理和转换。通过数据处理器，您可以实现各种数据处理需求，比如：\n\n- 数据过滤：根据条件筛选需要显示的节点和边\n- 数据计算：基于原始数据生成新的属性，如根据节点连接数计算节点大小，但不污染原始数据\n- 数据聚合：将大量节点聚合为少量节点，提高大规模图表的性能\n\n数据处理发生在渲染流程的特定阶段，可以灵活地改变最终呈现的结果，而无需修改原始数据源。\n\n## API 参考\n\n### Graph.getTransforms()\n\n获取当前图表中所有已配置的数据处理器。\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**返回值**\n\n- **类型**: [TransformOptions](#transformoptions)\n- **描述**: 当前图表中已配置的所有数据处理器\n\n**示例**\n\n```typescript\n// 获取当前所有数据处理器\nconst transforms = graph.getTransforms();\nconsole.log('当前图表的数据处理器:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\n设置图表的数据处理器，将替换所有现有的数据处理器。\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**参数**\n\n| 参数       | 描述                                                   | 类型                                                                                  | 默认值 | 必选 |\n| ---------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------ | ---- |\n| transforms | 新的数据处理器配置，或一个基于当前配置返回新配置的函数 | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -      | ✓    |\n\n**说明**\n\n数据处理器能够在图渲染过程的不同阶段对数据进行处理。设置的数据处理会全量替换原有的数据处理，如果需要在现有数据处理基础上添加新的数据处理，可以使用函数式更新方式。\n\n**示例 1**: 设置基本数据处理\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**示例 2**: 设置带配置的数据处理\n\n```typescript\ngraph.setTransforms([\n  // 字符串形式（使用默认配置）\n  'process-parallel-edges',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // 平行边之间的距离\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的数据处理到现有配置\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\n更新指定的数据处理器配置，需要通过 `key` 标识要更新的数据处理。\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**参数**\n\n| 参数      | 描述               | 类型                                            | 默认值 | 必选 |\n| --------- | ------------------ | ----------------------------------------------- | ------ | ---- |\n| transform | 更新的数据处理配置 | [UpdateTransformOption](#updatetransformoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个数据处理器，必须在原始数据处理配置中指定 `key` 字段，以便能够准确找到并更新该数据处理。\n\n**示例**: 更新数据处理配置\n\n```typescript\n// 初始设置数据处理时指定 key\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// 更新平行边距离\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## 类型定义\n\n### TransformOptions\n\n数据处理器配置类型，表示一组数据处理配置的数组。\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\n自定义数据处理配置接口，用于配置数据处理参数。\n\n```typescript\ntype CustomTransformOption = {\n  // 数据处理类型\n  type: string;\n\n  // 数据处理唯一标识\n  key?: string;\n\n  // 针对不同类型的数据处理，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\n更新数据处理的配置接口，用于动态修改数据处理参数。\n\n```typescript\ntype UpdateTransformOption = {\n  // 要更新的数据处理的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","packages/site/docs/api/viewport.en.md":"---\ntitle: Viewport Operations\norder: 4\n---\n\n## Overview of Viewport Operations\n\nG6 provides a series of viewport operation APIs to control the zooming, panning, and rotating of the canvas. These operations help users better view and interact with graphical content. Through viewport operations, you can achieve the following functions:\n\n- Zoom the canvas to view details or the global view\n- Pan the canvas to view different areas\n- Rotate the canvas to get different perspectives\n- Automatically fit content to the viewport\n\n### Categories of Viewport Operations\n\nViewport operations in G6 are mainly divided into the following categories:\n\n1. **Zoom Operations**: such as `zoomTo`, `zoomBy`\n2. **Pan Operations**: such as `translateTo`, `translateBy`\n3. **Rotate Operations**: such as `rotateTo`, `rotateBy`\n4. **Fit Operations**: such as `fitView`, `fitCenter`\n5. **Viewport Information Retrieval**: such as `getZoom`, `getPosition`\n\n## API Reference\n\n### Graph.zoomTo(zoom, animation, origin)\n\nZoom the canvas to a specified scale (absolute zoom).\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                                    | Type                                                            | Default | Required |\n| --------- | -------------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| zoom      | Target zoom scale (1 = original size, >1 zoom in, <1 zoom out) | number                                                          | -       | ✓        |\n| animation | Animation configuration                                        | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates)                       | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in to 2x\ngraph.zoomTo(2);\n\n// Zoom out to 0.5x with animation\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// Zoom in with the viewport center as the origin\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\nZoom based on the current zoom scale (relative zoom).\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                              | Type                                                            | Default | Required |\n| --------- | ---------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ratio     | Zoom ratio (>1 zoom in, <1 zoom out)     | number                                                          | -       | ✓        |\n| animation | Animation configuration                  | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in by 1.2x based on the current scale\ngraph.zoomBy(1.2);\n\n// Zoom out to 0.8x based on the current scale with animation\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\nPan the graph to a specified position (absolute pan).\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                 | Type                                                            | Default | Required |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| position  | Target position coordinates | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan to a specified position\ngraph.translateTo([100, 100]);\n\n// Pan with animation\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\nPan the graph by a specified distance relative to the current position (relative pan).\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| offset    | Pan offset              | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan right by 100 pixels and down by 50 pixels\ngraph.translateBy([100, 50]);\n\n// Relative pan with animation\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\nRotate the canvas to a specified angle (absolute rotation).\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Target rotation angle (radians)              | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate to 45 degrees\ngraph.rotateTo(Math.PI / 4);\n\n// Rotate to 90 degrees with animation\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\nRotate based on the current angle (relative rotation).\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Rotation angle increment (radians)           | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate clockwise by 30 degrees relative to the current angle\ngraph.rotateBy(Math.PI / 6);\n\n// Relative rotation with animation\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\nScale the graph to fit the appropriate size and pan to the center of the viewport.\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| options   | Fit options             | FitViewOptions                                                  | -       |          |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**FitViewOptions Type Description**\n\n| Property  | Type                   | Default    | Description                                       |\n| --------- | ---------------------- | ---------- | ------------------------------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | Fit timing: only when overflow or always          |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | Fit direction: x-axis, y-axis, or both directions |\n\n**Example**\n\n```typescript\n// Basic usage\ngraph.fitView();\n\n// Configure fit options\ngraph.fitView(\n  {\n    when: 'always', // Always fit\n    direction: 'both', // Fit in both directions\n  },\n  {\n    duration: 1000, // With animation\n  },\n);\n\n// Fit in the x direction only when content overflows\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\nPan the graph to the center of the viewport.\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Center the graph\ngraph.fitCenter();\n\n// Center with animation\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\nGet the current zoom scale.\n\n```typescript\ngetZoom(): number;\n```\n\n**Example**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('Current zoom scale:', currentZoom);\n```\n\n### Graph.getPosition()\n\nGet the position of the graph (position of the canvas origin in the viewport coordinate system).\n\n```typescript\ngetPosition(): Point;\n```\n\n**Example**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('Current position:', position);\n```\n\n### Graph.getRotation()\n\nGet the current rotation angle.\n\n```typescript\ngetRotation(): number;\n```\n\n**Example**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('Current rotation angle (radians):', rotation);\nconsole.log('Current rotation angle (degrees):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\nGet the viewport coordinates of the viewport center.\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('Viewport center coordinates:', center);\n```\n\n### Graph.getViewportCenter()\n\nGet the canvas coordinates of the viewport center.\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('Canvas coordinates of the viewport center:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\nSet the zoom range of the current graph.\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**Parameters**\n\n| Parameter | Description | Type                          | Default | Required |\n| --------- | ----------- | ----------------------------- | ------- | -------- |\n| zoomRange | Zoom range  | [number, number] \\| undefined | -       | ✓        |\n\n**Example**\n\n```typescript\n// Limit the zoom range between 0.5x and 2x\ngraph.setZoomRange([0.5, 2]);\n\n// Remove zoom restrictions\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\nGet the zoom range of the current graph.\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**Example**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('Current zoom range:', range);\n```\n\n### Graph.resize()\n\nResize the canvas to the size of the graph container.\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\nResize the canvas to the specified width and height.\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description   | Type   | Default | Required |\n| --------- | ------------- | ------ | ------- | -------- |\n| width     | Target width  | number | -       | ✓        |\n| height    | Target height | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set the canvas size to 800x600\ngraph.resize(800, 600);\n```\n\n## Type Definitions\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Whether to enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### Point\n\nCoordinate point type.\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\nView fit options.\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // Fit timing\n  direction?: 'x' | 'y' | 'both'; // Fit direction\n}\n```\n","packages/site/docs/api/viewport.zh.md":"---\ntitle: 视口操作\norder: 4\n---\n\n## 视口操作概述\n\nG6 提供了一系列视口操作 API，用于控制画布的缩放、平移和旋转。这些操作可以帮助用户更好地查看和交互图形内容。通过视口操作，你可以实现以下功能：\n\n- 缩放画布以查看细节或全局视图\n- 平移画布以查看不同区域\n- 旋转画布以获得不同视角\n- 自动适配内容到视口\n\n### 视口操作分类\n\nG6 的视口操作主要分为以下几类：\n\n1. **缩放操作**：如 `zoomTo`、`zoomBy`\n2. **平移操作**：如 `translateTo`、`translateBy`\n3. **旋转操作**：如 `rotateTo`、`rotateBy`\n4. **自适应操作**：如 `fitView`、`fitCenter`\n5. **视口信息获取**：如 `getZoom`、`getPosition`\n\n## API 参考\n\n### Graph.zoomTo(zoom, animation, origin)\n\n缩放画布至指定比例（绝对缩放）。\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                                          | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| zoom      | 目标缩放比例 (1 = 原始大小, >1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)                          | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 放大到2倍\ngraph.zoomTo(2);\n\n// 带动画效果的缩小到0.5倍\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// 以视口中心点为原点放大\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\n基于当前缩放比例进行缩放（相对缩放）。\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                        | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ratio     | 缩放比例 (>1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)        | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 在当前比例基础上放大1.2倍\ngraph.zoomBy(1.2);\n\n// 在当前比例基础上缩小到0.8倍，带动画\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\n将图平移至指定位置（绝对平移）。\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述         | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------ | --------------------------------------------------------------- | ------ | ---- |\n| position  | 目标位置坐标 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 平移到指定位置\ngraph.translateTo([100, 100]);\n\n// 带动画效果的平移\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\n将图相对当前位置平移指定距离（相对平移）。\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述       | 类型                                                            | 默认值 | 必选 |\n| --------- | ---------- | --------------------------------------------------------------- | ------ | ---- |\n| offset    | 平移偏移量 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置   | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 向右平移100像素，向下平移50像素\ngraph.translateBy([100, 50]);\n\n// 带动画效果的相对平移\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\n旋转画布至指定角度（绝对旋转）。\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 目标旋转角度(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 旋转到45度\ngraph.rotateTo(Math.PI / 4);\n\n// 带动画效果的旋转到90度\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\n基于当前角度进行旋转（相对旋转）。\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 旋转角度增量(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 相对当前角度顺时针旋转30度\ngraph.rotateBy(Math.PI / 6);\n\n// 带动画效果的相对旋转\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\n将图缩放至合适大小并平移至视口中心。\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| options   | 适配选项 | FitViewOptions                                                  | -      |      |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**FitViewOptions 类型说明**\n\n| 属性      | 类型                   | 默认值     | 描述                         |\n| --------- | ---------------------- | ---------- | ---------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | 适配时机：仅溢出时或始终适配 |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | 适配方向：x轴、y轴或两个方向 |\n\n**示例**\n\n```typescript\n// 基本使用\ngraph.fitView();\n\n// 配置适配选项\ngraph.fitView(\n  {\n    when: 'always', // 始终进行适配\n    direction: 'both', // 在两个方向上适配\n  },\n  {\n    duration: 1000, // 带动画效果\n  },\n);\n\n// 仅在内容溢出时适配x方向\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\n将图平移至视口中心。\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 居中显示\ngraph.fitCenter();\n\n// 带动画效果的居中\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\n获取当前缩放比例。\n\n```typescript\ngetZoom(): number;\n```\n\n**示例**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('当前缩放比例:', currentZoom);\n```\n\n### Graph.getPosition()\n\n获取图的位置（画布原点在视口坐标系下的位置）。\n\n```typescript\ngetPosition(): Point;\n```\n\n**示例**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('当前位置:', position);\n```\n\n### Graph.getRotation()\n\n获取当前旋转角度。\n\n```typescript\ngetRotation(): number;\n```\n\n**示例**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('当前旋转角度(弧度):', rotation);\nconsole.log('当前旋转角度(度):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\n获取视口中心的视口坐标。\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('视口中心坐标:', center);\n```\n\n### Graph.getViewportCenter()\n\n获取视口中心的画布坐标。\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('视口中心的画布坐标:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\n设置当前图的缩放区间。\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                          | 默认值 | 必选 |\n| --------- | -------- | ----------------------------- | ------ | ---- |\n| zoomRange | 缩放区间 | [number, number] \\| undefined | -      | ✓    |\n\n**示例**\n\n```typescript\n// 限制缩放范围在0.5到2倍之间\ngraph.setZoomRange([0.5, 2]);\n\n// 移除缩放限制\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\n获取当前图的缩放区间。\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**示例**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('当前缩放区间:', range);\n```\n\n### Graph.resize()\n\n调整画布大小为图容器大小。\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\n调整画布大小为指定宽高。\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述     | 类型   | 默认值 | 必选 |\n| ------ | -------- | ------ | ------ | ---- |\n| width  | 目标宽度 | number | -      | ✓    |\n| height | 目标高度 | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置画布大小为800x600\ngraph.resize(800, 600);\n```\n\n## 类型定义\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### Point\n\n坐标点类型。\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\n视图适配选项。\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // 适配时机\n  direction?: 'x' | 'y' | 'both'; // 适配方向\n}\n```\n","packages/site/docs/backup/CameraSetting.en.md":"---\ntitle: CameraSetting\n---\n\n## Options\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _string_\n\nPlugin type\n\n### aspect\n\n> _number \\| 'auto'_\n\nCamera viewport aspect ratio, only valid in perspective camera.\n\n- number : Specific aspect ratio\n\n- `'auto'` : Automatically set to the aspect ratio of the canvas\n\n### azimuth\n\n> _number_\n\nAzimuth\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\nCamera type\n\n- `'orbiting'`: Fixed viewpoint, change camera position\n\n- `'exploring'`: Similar to orbiting, but allows the camera to rotate between the North Pole and the South Pole\n\n- `'tracking'`: Fixed camera position, change viewpoint\n\n### distance\n\n> _number_ **Default:** `500`\n\nThe distance from the camera to the target\n\n### elevation\n\n> _number_\n\nElevation\n\n### far\n\n> _number_\n\nThe position of the far plane\n\n### fov\n\n> _number_\n\nCamera field of view, only valid in perspective camera\n\n### maxDistance\n\n> _number_\n\nMaximum distance\n\n### minDistance\n\n> _number_\n\nMinimum distance\n\n### near\n\n> _number_\n\nThe position of the near plane\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\nProjection mode, perspective projection is only valid in 3D scenes\n\n- `'perspective'` : perspective projection\n\n- `'orthographic'` : Orthogonal projection\n\n### roll\n\n> _number_\n\nRoll\n\n## API\n","packages/site/docs/backup/CameraSetting.zh.md":"---\ntitle: CameraSetting 相机设置\n---\n\n## 配置项\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _`camera-setting` \\| string_\n\n⚠️ **注意**：\n\n- 相机设置插件必须在 3D 场景下使用\n- 此插件在使用前需要自行注册：\n\n```javascript\nimport { register, CameraSetting, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting); // type: 'camera-setting'\n```\n\n### aspect\n\n> _number \\| `'auto'`_\n\n相机视口宽高比，仅在透视相机下有效\n\n- number : 具体的宽高比\n\n- `'auto'` : 自动设置为画布的宽高比\n\n### azimuth\n\n> _number_\n\n方位角\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\n相机类型\n\n- `'orbiting'`: 固定视点，改变相机位置\n- `'exploring'`: 类似 orbiting，但允许相机在北极和南极之间旋转\n- `'tracking'`: 固定相机位置，改变视点\n\n### distance\n\n> _number_ **Default:** `500`\n\n相机距离目标的距离\n\n### elevation\n\n> _number_\n\n仰角\n\n### far\n\n> _number_\n\n远平面位置\n\n### fov\n\n> _number_\n\n相机视角，仅在透视相机下有效\n\n### maxDistance\n\n> _number_\n\n最大视距\n\n### minDistance\n\n> _number_\n\n最小视距\n\n### near\n\n> _number_\n\n近平面位置\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\n投影模式，透视投影仅在 3D 场景下有效\n\n- `'perspective'` : 透视投影\n- `'orthographic'` : 正交投影\n\n### roll\n\n> _number_\n\n滚转角\n\n## API\n","packages/site/docs/manual/animation/animation.en.md":"---\ntitle: Animation Overview\norder: 1\n---\n\n## Overview\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nAnimation refers to the state changes of elements over a period of time, such as the position, size, and color of nodes. In G6, animations are often used to enhance user experience and improve the coherence and smoothness of the graph update process.\n\nG6 provides a set of animation paradigms to describe element animations and has built-in some common animation effects. Users can achieve different animation effects by configuring animation parameters.\n\nThe implementation of an animation paradigm is as follows:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\nThe aforementioned animation paradigm indicates that when the `x` and `y` attributes of an element change, an animation will be executed.\n\n## Configure Animation\n\nIn G6, animation configuration is divided into global configuration and local configuration. Global configuration is mainly used to set whether animations are enabled globally, the duration of animations, and other parameters. Local configuration is primarily used to set the animation effects for elements.\n\n### Disabled Global Animation\n\nTo disable global animations, you can pass the `animation` option when instantiating the `Graph`:\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### Configure Global Animation\n\nIf you want to enable animations and also configure the default duration for the animations, you can pass the `animation` option:\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### Configure Element Animation\n\nFor individual elements, you can configure animations at different stages. For example, if you want an element to have a fade-in and fade-out effect when it enters and exits, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\nIf you want to update the position of an element with a translation transition, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\nIf you wish to disable animations for an element, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## Animation Paradigm\n\nThe animation configuration mentioned in the previous section actually used the built-in animation paradigm. This section introduces how to customize the animation paradigm.\n\n:::info{title=Tip}\nBefore writing an animation paradigm, it is necessary to understand the compositional structure of an element. For details, please refer to the [Element](/en/manual/element/overview) section.\n:::\n\nThe [Element](/en/manual/element/overview) section mentioned that elements in G6 are composed of one or more atomic graphics. Therefore, the animation of an element is essentially a combination of these atomic shape animations.\n\nThus, the animation paradigm is an array that describes the animation effects of each atomic shape within the element. For the element itself, it is also a special composite shape and thus has basic shape attributes such as `x`, `y`, etc.\n\nTherefore, you can directly write an animation paradigm for the element itself:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## Custom Animation\n\nIf the built-in animations do not meet your requirements, you can create custom animations. For details, please refer to [Custom Animation](/en/manual/animation/custom-animation).\n\n## Animation Priority\n\nAnimation priority refers to the precedence between global animation configuration and element-specific animation configuration. It can be summarized as follows:\n\n| Global Animation Config | Local Animation Config | Whether to Execute Animation                                                                     |\n| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------ |\n| ✅ true                 | ✅ true                | ✅ Execute animation with default configuration                                                  |\n| ✅ true                 | ❌ false               | ❌ Won't execute animation                                                                       |\n| ✅ true                 | ✅ Custom Animation    | ✅ Execute animation with local animation configuration                                          |\n| ❌ false                | ✅ true                | ❌ Won't execute animation                                                                       |\n| ❌ false                | ❌ false               | ❌ Won't execute animation                                                                       |\n| ❌ false                | ✅ Custom Animation    | ❌ Won't execute animation                                                                       |\n| ✅ Custom Animation     | ✅ true                | ✅ Execute animation with global animation configuration                                         |\n| ✅ Custom Animation     | ✅ Custom Animation    | ✅ Execute animation, local animation configuration overrides the global animation configuration |\n| ✅ Custom Animation     | ❌ false               | ❌ Won't execute animation                                                                       |\n\n## Persistent Animation\n\nIf you want elements to have persistent animations, such as the undulating effect of nodes or the ant line effect of edges, this can be achieved by customizing the elements. Below is an implementation of an edge with an Ant Line animation provided:\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\nThe `onCreate` is a lifecycle hook used to execute animations when an element is created.\n\nConfigure the edge style in the options as follows:\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\nThe `lineDash` is an array for `lineDashOffset`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\nThe `lineDashOffset` is the offset for `lineDash`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\nNode Style Configuration:\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","packages/site/docs/manual/animation/animation.zh.md":"---\ntitle: 动画总览\norder: 1\n---\n\n## 概述\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n动画是指元素在一段时间内的状态变化，例如节点的位置、大小、颜色等。在 G6 中，动画通常用于增强用户体验，提升图更新过程的连贯性和流畅度。\n\nG6 提供了一套动画范式来描述元素动画，并内置了一些常用的动画效果，用户可以通过配置动画参数来实现不同的动画效果。\n\n一个动画范式的实现如下：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n上述动画范式表示当元素的 `x` 和 `y` 属性发生变化时，会执行动画。\n\n## 配置动画\n\nG6 中动画配置分为全局配置和局部配置，全局配置主要用于配置全局是否开启动画、动画时长等参数，局部配置主要用于配置元素的动画效果。\n\n### 关闭全局动画\n\n若要关闭全局动画，可以在实例化 `Graph` 时传入 `animation` 配置项：\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### 配置全局动画\n\n如果要启用动画且同时配置动画的默认播放时长，可以传入 `animation` 配置项：\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### 配置元素动画\n\n对于单个元素，可以配置其在不同阶段的动画。例如希望元素在进场和退场时具有淡入淡出效果，可以以如下方式配置：\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\n如果希望更新元素位置时是以平移过渡的方式，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\n如果希望关闭元素的动画，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## 动画范式\n\n上一节中提到的动画配置实际上使用了内置的动画范式，本节介绍如何自定义动画范式。\n\n:::info{title=提示}\n在编写动画范式之前需要了解元素的组成结构，具体请参考[元素](/manual/element/overview)一节\n:::\n\n[元素](/manual/element/overview)一节中提到：G6 中的元素是由一个或多个原子图形组合而成。因此元素的动画本质上是这些原子图形动画的组合。\n\n因此动画范式是一个数组，用于描述元素中各原子图形的动画效果。对于元素本身来说，其也是一个特殊的复合图形，因此具有基本的图形属性，如 `x`、`y` 等。\n\n因此可以直接为元素本身编写动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## 自定义动画\n\n如果内置动画无法满足需求，可以自定义动画，具体请参考[自定义动画](/manual/animation/custom-animation)。\n\n## 动画优先级\n\n动画优先级是指全局动画配置和元素动画配置之前的优先级，可以归纳如下：\n\n| 全局动画配置 | 局部动画配置 | 是否执行动画                                      |\n| ------------ | ------------ | ------------------------------------------------- |\n| ✅ true      | ✅ true      | ✅ 执行动画，以默认动画配置执行                   |\n| ✅ true      | ❌ false     | ❌ 不执行该类元素动画                             |\n| ✅ true      | ✅ 配置动画  | ✅ 执行动画，以局部动画配置执行                   |\n| ❌ false     | ✅ true      | ❌ 不执行任何动画                                 |\n| ❌ false     | ❌ false     | ❌ 不执行任何动画                                 |\n| ❌ false     | ✅ 配置动画  | ❌ 不执行任何动画                                 |\n| ✅ 配置动画  | ✅ true      | ✅ 执行动画，以全局动画配置执行                   |\n| ✅ 配置动画  | ✅ 配置动画  | ✅ 执行动画，将局部动画配置覆盖全局动画配置后执行 |\n| ✅ 配置动画  | ❌ false     | ❌ 不执行该类元素动画                             |\n\n## 持续动画\n\n如果希望元素具有持续动画，例如节点的波动效果、边的蚂蚁线效果等，可以通过自定义元素方式实现，下面提供一个具有蚂蚁线(Ant Line)动画的边的实现：\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\n其中 `onCreate` 是一个生命周期钩子，用于在元素创建时执行动画。\n\n在 options 中配置边样式：\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\n其中 `lineDash` 是 `lineDashOffset` 的数组，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\n其中 `lineDashOffset` 是 `lineDash` 的偏移量，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\n节点样式配置：\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","packages/site/docs/manual/animation/custom-animation.en.md":"---\ntitle: Custom Animation\norder: 2\n---\n\n## Overview\n\n## Implement Animation\n\nFor circular node (Circle) elements, the main shape is a circle. Now, let's create an animation for it so that when the size of the node changes, it transitions with a scaling animation:\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nNow let's create a graph instance and update the element size to trigger the update animation:\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### Principle Analysis\n\nWhen animating an element, the element converts its animation frame parameters into animation frame parameters for its individual sub-graphics and executes the corresponding animations.\n\nIn the example above, by updating the node size, an animation was performed on the node, and its animation frame parameters were:\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\nAfter obtaining the attribute, the node element converts it into animation frame parameters for the main shape (circle):\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\nTherefore, what is ultimately happening here is that a transition animation is being performed on the circle, changing its radius from 10 to 20.\n\n#### Composite Animation\n\nBy directly combining the position change animation with the size change animation into a single animation paradigm, you can obtain a composite animation paradigm:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nAnd update both the position and size of the node simultaneously:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\nAdd color transition:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\nExecute node update:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","packages/site/docs/manual/animation/custom-animation.zh.md":"---\ntitle: 自定义动画\norder: 2\n---\n\n## 概述\n\n## 实现动画\n\n对于圆形节点（Circle）元素，其主图形是一个圆形，现在为其编写一个动画，当节点的尺寸发生变化时，能够以缩放的方式进行过渡动画：\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n下面我们创建一个图实例并更新元素尺寸来触发更新动画：\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### 原理分析\n\n当对一个元素执行动画时，该元素会将其动画帧参数转化为其各个子图形上的动画帧参数，并执行对应的动画。\n\n在上面的例子中，通过更新节点尺寸(size)，对该节点执行了动画，其动画帧参数为：\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\n节点元素拿到该属性后，将其转化为主图形（圆形）的动画帧参数：\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\n因此这里最终是对圆形执行了半径从 10 到 20 的过渡动画。\n\n#### 复合动画\n\n直接将位置变化动画和尺寸变化动画合并到一个动画范式即可得到复合动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n并同时更新该节点的位置和尺寸：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\n加入颜色过渡：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\n执行节点更新：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","packages/site/docs/manual/behavior/AutoAdaptLabel.en.md":"---\ntitle: AutoAdaptLabel\norder: 1\n---\n\n## Overview\n\nAuto-adapt label display is a dynamic label management strategy designed to intelligently adjust which labels should be displayed or hidden based on factors such as spatial allocation of the current visible range and node importance. By analyzing the visible area in real-time, it ensures that users receive the most relevant and clear information display in different interaction scenarios, while avoiding visual overload and information redundancy.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Node size changes\n- Graph scaling\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // Throttle time\n      padding: 10, // Extra spacing when detecting overlap\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                      | Type                                                                                                                              | Default            | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- |\n| type      | Interaction type name                                                                                                                                                                                                                                                                            | string                                                                                                                            | `auto-adapt-label` | √        |\n| enable    | Whether to enable this interaction                                                                                                                                                                                                                                                               | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                                                   | true               |          |\n| throttle  | Label update throttle time (ms)                                                                                                                                                                                                                                                                  | number                                                                                                                            | 100                |          |\n| padding   | Extra spacing when detecting label overlap                                                                                                                                                                                                                                                       | number \\| number[]                                                                                                                | 0                  |          |\n| sort      | Custom sorting function, sorting elements from high to low importance, with higher importance elements having higher label display priority. Generally, combo > node > edge                                                                                                                      | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                |                    |          |\n| sortNode  | Sort nodes from high to low importance, with higher importance nodes having higher label display priority. Several built-in [centrality algorithms](#nodecentralityoptions) are available, or a custom sorting function can be used. Note that if `sort` is set, `sortNode` will not take effect | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/en/manual/data#nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |          |\n| sortEdge  | Sort edges from high to low importance, with higher importance edges having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortEdge` will not take effect                                                                  | (edgeA: [EdgeData](/en/manual/data#edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                    |                    |          |\n| sortCombo | Sort groups from high to low importance, with higher importance groups having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortCombo` will not take effect                                                               | (comboA: [ComboData](/en/manual/data#combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |          |\n\n### NodeCentralityOptions\n\nMethods for measuring node centrality\n\n- `'degree'`: Degree centrality, measured by the degree of the node (number of connected edges). Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measured by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measured by the reciprocal of the sum of the shortest path lengths from the node to all other nodes. Nodes with high closeness centrality can usually reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measured by the degree of connection of the node to other central nodes. Nodes with high eigenvector centrality are usually connected to other important nodes\n- `'pagerank'`: PageRank centrality, measured by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to webpage ranking algorithms\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md":"---\ntitle: 标签自适应显示 AutoAdaptLabel\norder: 1\n---\n\n## 概述\n\n标签自适应显示是一种动态标签管理策略，旨在根据当前可视范围的空间分配、节点重要性等因素，智能调整哪些标签应显示或隐藏。通过对可视区域的实时分析，确保用户在不同的交互场景下获得最相关最清晰的信息展示，同时避免视觉过载和信息冗余。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 节点尺寸变化\n- 图形缩放\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // 节流时间\n      padding: 10, // 检测重叠时的额外间距\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                        | 类型                                                                                                                                   | 默认值             | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ---- |\n| type      | 交互类型名称                                                                                                                                                                                | string                                                                                                                                 | `auto-adapt-label` | √    |\n| enable    | 是否启用该交互                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                                      | true               |      |\n| throttle  | 标签更新节流时间（ms）                                                                                                                                                                      | number                                                                                                                                 | 100                |      |\n| padding   | 标签检测重叠时的额外间距                                                                                                                                                                    | number \\| number[]                                                                                                                     | 0                  |      |\n| sort      | 自定义排序函数，根据元素的重要性从高到低排序，重要性越高的元素其标签显示优先级越高。一般情况下 combo > node > edge                                                                          | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                     |                    |      |\n| sortNode  | 根据节点的重要性从高到低排序，重要性越高的节点其标签显示优先级越高。内置几种[中心性算法](#nodecentralityoptions)，也可以自定义排序函数。需要注意，如果设置了 `sort`，则 `sortNode` 不会生效 | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/manual/data#节点数据nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |      |\n| sortEdge  | 根据边的重要性从高到低排序，重要性越高的边其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortEdge` 不会生效                                               | (edgeA: [EdgeData](/manual/data#边数据edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                      |                    |      |\n| sortCombo | 根据群组的重要性从高到低排序，重要性越高的群组其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortCombo` 不会生效                                          | (comboA: [ComboData](/manual/data#组合数据combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |      |\n\n### NodeCentralityOptions\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/BrushSelect.en.md":"---\ntitle: BrushSelect\norder: 2\n---\n\n## Overview\n\nBrush select allows users to click and drag a box to enclose elements, selecting the elements within the box.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Quickly selecting a batch of elements\n- Quickly deselecting a batch of elements\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Type                                                                             | Default                   | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | -------- |\n| type           | Interaction type name. This plugin is built-in, and you can use it with `type: 'brush-select'`.                                                                                                                                                                                                                                                                                                                                                                                                                              | `brush-select` \\| string                                                         | `brush-select`            | ✓        |\n| animation      | Whether to enable animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | boolean                                                                          | false                     |          |\n| enable         | Whether to enable brush select functionality                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)  | true                      |          |\n| enableElements | Types of elements that can be selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |          |\n| immediately    | Whether to select immediately, only effective when [selection mode](#mode) is `default`, [example](#immediately)                                                                                                                                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |          |\n| mode           | Selection mode, [example](#mode)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |          |\n| onSelect       | Callback for selected element state                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |          |\n| state          | Switch to this state when selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |          |\n| style          | Specify the style of the selection box, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                  | See below                 |          |\n| trigger        | Press this shortcut key in combination with a mouse click to perform selection **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means selection can be performed with a mouse click without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: [], // No need to press other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nFour selection modes are built-in:\n\n- `union`: Retain the current state of selected elements and add the specified state.\n- `intersect`: If the selected elements already have the specified state, retain it; otherwise, clear the state.\n- `diff`: Invert the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Attribute         | Description               | Type                                     | Default   |\n| ----------------- | ------------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style               | string                                   |           |\n| fill              | Fill color                | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity              | number \\| string                         | 0.1       |\n| isBillboard       | Enable billboard mode     | boolean                                  |           |\n| isSizeAttenuation | Enable size attenuation   | boolean                                  |           |\n| lineCap           | Line end style            | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash configuration        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash offset               | number                                   |           |\n| lineJoin          | Line join style           | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width                | number \\| string                         | 1         |\n| opacity           | Overall opacity           | number \\| string                         |           |\n| radius            | Rectangle corner radius   | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur degree        | number                                   |           |\n| shadowColor       | Shadow color              | string                                   |           |\n| shadowOffsetX     | Shadow X direction offset | number                                   |           |\n| shadowOffsetY     | Shadow Y direction offset | number                                   |           |\n| stroke            | Stroke color              | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity            | number \\| string                         |           |\n| visibility        | Visibility                | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level           | number                                   | 2         |\n\n**Example**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/BrushSelect.zh.md":"---\ntitle: 框选 BrushSelect\norder: 2\n---\n\n## 概述\n\n鼠标点击拖一个框笼罩元素，框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素\n- 快速取消选中一批元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                                                                                                                                                                                                                                                                                                                                            | 类型                                                                             | 默认值                    | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | ---- |\n| type           | 交互类型名称。此插件已内置，你可以通过 `type: 'brush-select'` 来使用它。                                                                                                                                                                                                                                                                                                        | `brush-select` \\| string                                                         | `brush-select`            | ✓    |\n| animation      | 是否启用动画                                                                                                                                                                                                                                                                                                                                                                    | boolean                                                                          | false                     |      |\n| enable         | 是否启用框选功能                                                                                                                                                                                                                                                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                | true                      |      |\n| enableElements | 可框选的元素类型                                                                                                                                                                                                                                                                                                                                                                | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |      |\n| immediately    | 是否及时框选, 仅在 [框选模式 mode](#mode) 为 `default` 时生效，[示例](#immediately)                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |      |\n| mode           | 框选的选择模式，[示例](#mode)                                                                                                                                                                                                                                                                                                                                                   | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |      |\n| onSelect       | 框选元素状态回调                                                                                                                                                                                                                                                                                                                                                                | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |      |\n| state          | 被选中时切换到该状态                                                                                                                                                                                                                                                                                                                                                            | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |      |\n| style          | 指定框选时的框样式，[配置项](#style)                                                                                                                                                                                                                                                                                                                                            |                                                                                  | 见下文                    |      |\n| trigger        | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n内置支持四种框选的选择模式：\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ClickSelect.en.md":"---\ntitle: ClickSelect\norder: 3\n---\n\n## Overview\n\nWhen an element is clicked, it will be highlighted.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Focusing on elements\n- Viewing element details\n- Viewing element relationships\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['click-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // Selection spread range\n      state: 'active', // Selected state\n      neighborState: 'neighborActive', // Neighbor node attached state\n      unselectedState: 'inactive', // Unselected node state\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option          | Description                                                                                                                                                                                                                                                        | Type                                                                            | Default        | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | -------------- | -------- |\n| type            | Behavior type name. This behavior is built-in, and you can use it with `type: 'click-select'`.                                                                                                                                                                     | `click-select` \\| string                                                        | `click-select` | ✓        |\n| animation       | Whether to enable animation effects when switching element states                                                                                                                                                                                                  | boolean                                                                         | true           |          |\n| degree          | Controls the highlight spread range, [example](#degree)                                                                                                                                                                                                            | number \\| (event:[Event](/en/api/event#event-object-properties)) => number      | 0              |          |\n| enable          | Whether to enable the click element function, supports dynamic control through functions, [example](#enable)                                                                                                                                                       | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean) | true           |          |\n| multiple        | Whether to allow multiple selections                                                                                                                                                                                                                               | boolean                                                                         | false          |          |\n| state           | The state applied when an element is selected                                                                                                                                                                                                                      | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| neighborState   | The state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements, [example](#neighborstate)                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| unselectedState | The state applied to all other elements except the selected element and its affected neighbor elements when an element is selected, [example](#unselectedState)                                                                                                    | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        |                |          |\n| onClick         | Callback when an element is clicked                                                                                                                                                                                                                                | (event: [Event](/en/api/event#event-object-properties)) => void                 |                |          |\n| trigger         | Press this shortcut key in combination with a mouse click to perform multi-selection, key reference: _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                        | `['shift']`    |          |\n\n### degree\n\nControls the highlight spread range\n\n- For nodes, `0` means only the current node is selected, `1` means the current node and its directly adjacent nodes and edges are selected, and so on.\n- For edges, `0` means only the current edge is selected, `1` means the current edge and its directly adjacent nodes are selected, and so on.\n\n> In the following example, when `degree: 0` only the <span style='color:#E4504D'>red</span> point is highlighted;\n> When `degree: 1` the <span style='color:#E4504D'>red</span> and <span style='color:#FFC40C'>orange</span> points are highlighted.\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\nWhether to enable the click element function\n\nIt can be dynamically controlled through functions, for example, only enabled when a node is selected.\n\n```js\n{\n  //⚠️ Note, you need to set both the node and the canvas, otherwise the user will not listen to the event when clicking the canvas\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\nSimilarly, if you only want edges to be selected:\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\nThe state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // State attached to the directly clicked node\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\nWhen an element is selected, the state applied to all other elements except the selected element and the spread neighbor elements.\n\nBuilt-in states: `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Example\n\n### Click to select nodes and their directly connected nodes\n\n**Clicking a node** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#0f0'>active</span>\n<br>\n**Adjacent nodes** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // Selected node state\n      active: {\n        fill: '#0f0',\n      },\n      // Adjacent node state\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n      // Unselected node state\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ClickSelect.zh.md":"---\ntitle: 点击选中 ClickSelect\norder: 3\n---\n\n## 概述\n\n当鼠标点击元素时，会使元素高亮。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 聚焦元素\n- 查看元素详情\n- 查看元素关系\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['click-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // 选中扩散范围\n      state: 'active', // 选中的状态\n      neighborState: 'neighborActive', // 相邻节点附着状态\n      unselectedState: 'inactive', // 未选中节点状态\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项          | 说明                                                                                                                                                                                                       | 类型                                                                     | 默认值         | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------- | ---- |\n| type            | 交互类型名称。此交互已内置，你可以通过 `type: 'click-select'` 来使用它。                                                                                                                                   | `click-select` \\| string                                                 | `click-select` | ✓    |\n| animation       | 是否在元素状态切换时启用动画效果                                                                                                                                                                           | boolean                                                                  | true           |      |\n| degree          | 控制了高亮扩散范围，[示例](#degree)                                                                                                                                                                        | number \\| (event:[Event](/api/event#事件对象属性)) => number             | 0              |      |\n| enable          | 是否启用点击元素的功能，支持通过函数的方式动态控制是否启用，[示例](#enable)                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)        | true           |      |\n| multiple        | 是否允许多选                                                                                                                                                                                               | boolean                                                                  | false          |      |\n| state           | 当元素被选中时应用的状态                                                                                                                                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| neighborState   | 当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素，[示例](#neighborstate)                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| unselectedState | 当有元素被选中时，除了选中元素及其受影响的邻居元素外，其他所有元素应用的状态，[示例](#unselectedState)                                                                                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` |                |      |\n| onClick         | 点击元素时的回调                                                                                                                                                                                           | (event: [Event](/api/event#事件对象属性)) => void                        |                |      |\n| trigger         | 按下该快捷键配合鼠标点击进行多选，按键参考： _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                 | `['shift']`    |      |\n\n### degree\n\n控制了高亮扩散范围\n\n- 对于节点来说，`0` 表示只选中当前节点，`1` 表示选中当前节点及其直接相邻的节点和边，以此类推。\n- 对于边来说，`0` 表示只选中当前边，`1` 表示选中当前边及其直接相邻的节点，以此类推。\n\n> 如下示例，当 `degree: 0` 仅高亮<span style='color:#E4504D'>红色</span>点;\n> 当 `degree: 1` 高亮<span style='color:#E4504D'>红色</span>和<span style='color:#FFC40C'>橙色</span>点。\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\n是否启用点击元素的功能\n\n可以通过函数的方式动态控制是否启用，例如只有节点被选中时才启用。\n\n```js\n{\n  //⚠️ 注意，这里需要同时设置节点和画布，否则用户点击画布时将不会监听到事件\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\n同理，如果只希望边能被选中：\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\n当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // 被直接点击的节点附着的状态\n      state: 'active',\n      // 相邻的节点附着的状态\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\n当有元素被选中时，除了被选中元素和扩散的邻居元素外，其他所有元素应用的状态。\n\n内置状态： `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 示例\n\n### 点击选中节点及其直接相连的节点\n\n**点击节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#0f0'>active</span>\n<br>\n**相邻节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // 选中节点状态\n      active: {\n        fill: '#0f0',\n      },\n      // 相邻节点状态\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // 相邻节点附着状态\n      neighborState: 'neighborActive',\n      // 未选中节点状态\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CollapseExpand.en.md":"---\ntitle: CollapseExpand\norder: 4\n---\n\n## Overview\n\nCollapseExpand is a built-in behavior in G6 used to implement the expand/collapse functionality for nodes or combos. Through double-click (default) or single-click actions, users can flexibly control the expand and collapse states of graph elements, effectively managing the visualization hierarchy of the graph structure and reducing visual complexity.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Managing large hierarchical graphs, enabling layered browsing of tree or network graphs\n- Simplifying the display of complex graphs, expanding areas of interest as needed\n- Hiding branch nodes that are temporarily not needed, focusing on important information\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates to the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // Change the trigger method to single-click\n      animation: true, // Enable animation effects\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                         | Type                                                                     | Default Value     | Required |\n| ---------- | --------------------------------------------------- | ------------------------------------------------------------------------ | ----------------- | -------- |\n| type       | Behavior type name                                  | `collapse-expand` \\| string                                              | `collapse-expand` | ✓        |\n| animation  | Enable expand/collapse animation effects            | boolean                                                                  | true              |          |\n| enable     | Enable expand/collapse functionality                | boolean \\| ((event: [/en/api/event#event-object-properties]) => boolean) | true              |          |\n| trigger    | Trigger method, can be single-click or double-click | `click` \\| `dblclick`                                                    | `dblclick`        |          |\n| onCollapse | Callback function when collapse is completed        | (id: string) => void                                                     | -                 |          |\n| onExpand   | Callback function when expand is completed          | (id: string) => void                                                     | -                 |          |\n| align      | Align with the target element to avoid view offset  | boolean                                                                  | true              |          |\n\n## Code Examples\n\n### Basic Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // other configurations...\n});\n```\n\n### Use Single-Click to Trigger Expand/Collapse\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // Change the default double-click trigger to single-click\n    },\n  ],\n});\n```\n\n### Custom Expand/Collapse Callback\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`Node ${id} has collapsed`);\n        // Execute custom logic\n      },\n      onExpand: (id) => {\n        console.log(`Node ${id} has expanded`);\n        // Execute custom logic\n      },\n    },\n  ],\n});\n```\n\n### Conditional Enablement of Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // Enable expand/collapse functionality only when the target is a node type\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Disable Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // Disable expand/collapse animation effects\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. How to determine if a node is collapsed?\n\nYou can check the `collapsed` property in the node data:\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. How to programmatically expand or collapse a node?\n\nIn addition to being triggered by user interaction, you can also directly control using [collapseElement](/en/api/element#graphcollapseelementid-options) or [expandElement](/en/api/element#graphexpandelementid-options):\n\n```javascript\n// Collapse node\ngraph.collapseElement('nodeId', { animation: true });\n\n// Expand node\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CollapseExpand.zh.md":"---\ntitle: 展开/收起元素 CollapseExpand\norder: 4\n---\n\n## 概述\n\nCollapseExpand 是 G6 中用于实现节点或组合（Combo）展开/收起功能的内置交互。通过双击（默认）或单击操作，用户可以灵活控制图元素的展开与收起状态，有效管理图结构的可视化层次，降低视觉复杂度。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 管理大型层次结构图，实现树状图或网络图的分层浏览\n- 简化复杂图的展示，按需展开关注区域\n- 隐藏暂时不需要查看的分支节点，聚焦于重要信息\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一 behavior：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // 修改触发方式为单击\n      animation: true, // 启用动画效果\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                           | 类型                                                                      | 默认值            | 必选 |\n| ---------- | ------------------------------ | ------------------------------------------------------------------------- | ----------------- | ---- |\n| type       | 交互类型名称                   | `collapse-expand` \\| string                                               | `collapse-expand` | ✓    |\n| animation  | 是否启用展开/收起动画效果      | boolean                                                                   | true              |      |\n| enable     | 是否启用展开/收起功能          | boolean \\| ((event: [IPointerEvent](/api/event#事件对象属性)) => boolean) | true              |      |\n| trigger    | 触发方式，可选单击或双击       | `click` \\| `dblclick`                                                     | `dblclick`        |      |\n| onCollapse | 完成收起时的回调函数           | (id: string) => void                                                      | -                 |      |\n| onExpand   | 完成展开时的回调函数           | (id: string) => void                                                      | -                 |      |\n| align      | 是否对准目标元素，避免视图偏移 | boolean                                                                   | true              |      |\n\n## 代码示例\n\n### 基础展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // 其他配置...\n});\n```\n\n### 使用单击触发展开/收起\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // 将默认的双击触发改为单击触发\n    },\n  ],\n});\n```\n\n### 自定义展开/收起回调\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`节点 ${id} 已收起`);\n        // 执行自定义逻辑\n      },\n      onExpand: (id) => {\n        console.log(`节点 ${id} 已展开`);\n        // 执行自定义逻辑\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // 只有当目标是节点类型时才启用展开/收起功能\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 关闭动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // 关闭展开/收起动画效果\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 如何判断一个节点是否处于收起状态？\n\n可以通过检查节点数据中的 `collapsed` 属性：\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. 如何以编程方式展开或收起节点？\n\n除了通过用户交互触发，你还可以使用 [collapseElement](/api/element#graphcollapseelementid-options) 或 [expandElement](/api/element#graphexpandelementid-options) 直接控制：\n\n```javascript\n// 收起节点\ngraph.collapseElement('nodeId', { animation: true });\n\n// 展开节点\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CreateEdge.en.md":"---\ntitle: CreateEdge\norder: 5\n---\n\n## Overview\n\nCreateEdge is a built-in behavior in G6 for interactively creating edges on the canvas. After the user triggers the behavior (click or drag), the edge will follow the mouse movement and connect to the target node to complete the creation. If canceled, it will be automatically removed.\n\nAdditionally, this behavior supports customizing the style of the edge, such as color, line style, arrow, etc., to meet different visualization needs.\n\nThe elements that can be connected by this behavior are `node` and `combo`.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Visualization scenarios that require interactive creation of connections between nodes, such as flowcharts, knowledge graphs, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration\n\n```javascript\n// Use default configuration\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['create-edge'], // Directly add, use default configuration\n});\n\n// Or use custom configuration\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // Behavior configuration, create edge by clicking\n      style: {}, // Custom edge style\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                 | Type                                                                                                     | Default       | Required |\n| -------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type     | Behavior type name                                                                                          | string                                                                                                   | `create-edge` | √        |\n| trigger  | The way to trigger the creation of a new edge: `click` means click to trigger; `drag` means drag to trigger | `click` \\| `drag`                                                                                        | `drag`        |          |\n| enable   | Whether to enable this behavior                                                                             | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                          | true          |          |\n| onCreate | Callback function for creating an edge, returns edge data                                                   | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => [EdgeData](/en/manual/data#edge-data-edgedata) | -             |          |\n| onFinish | Callback function for successfully creating an edge                                                         | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => void                                           | -             |          |\n| style    | Style of the newly created edge, [configuration options](#style)                                            | See below                                                                                                | -             |          |\n\n### style\n\nConfigure the style of the newly created edge, for detailed configuration options, please refer to [Element - Edge - General Edge Properties - Style](/en/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## Code Examples\n\n### Basic Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### Custom Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  // Other configurations,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: 'red',\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### Create Edge by Clicking\n\n```javascript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/CreateEdge.zh.md":"---\ntitle: 创建边 CreateEdge\norder: 5\n---\n\n## 概述\n\nCreateEdge 是 G6 中用于实现画布中交互式创建边（Edge）的内置交互。用户触发交互（点击或拖拽）后，边会随鼠标移动，连接到目标节点即完成创建，若取消则自动移除。\n\n此外，该交互支持自定义边的样式，如颜色、线条样式、箭头等，以适应不同的可视化需求。\n\n该交互支持连接的元素为 `node` 和 `combo`。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要交互式创建节点间连接关系的可视化场景，如流程图、知识图谱等\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n```javascript\n// 使用默认配置\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['create-edge'], // 直接添加，使用默认配置\n});\n\n// 或使用自定义配置\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // 交互配置，通过点击创建边\n      style: {}, // 边自定义样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                        | 类型                                                                                       | 默认值        | 必选 |\n| -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------- | ---- |\n| type     | 交互类型名称                                                | string                                                                                     | `create-edge` | √    |\n| trigger  | 触发新建边的方式：`click` 表示点击触发；`drag` 表示拖拽触发 | `click` \\| `drag`                                                                          | `drag`        |      |\n| enable   | 是否启用该交互                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                          | true          |      |\n| onCreate | 创建边回调函数，返回边数据                                  | (edge: [EdgeData](/manual/data#边数据edgedata)) => [EdgeData](/manual/data#边数据edgedata) | -             |      |\n| onFinish | 成功创建边回调函数                                          | (edge: [EdgeData](/manual/data#边数据edgedata)) => void                                    | -             |      |\n| style    | 新建边的样式，[配置项](#style)                              | 见下面                                                                                     | -             |      |\n\n### style\n\n配置新创建边的样式，详细配置项请参考 [元素 - 边 - 通用边属性 - 样式](/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## 代码示例\n\n### 基础创建边功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### 自定义创建边功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: red,\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### 使用点击创建边\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragCanvas.en.md":"---\ntitle: DragCanvas\norder: 6\n---\n\n## Overview\n\nDragCanvas is a built-in behavior in G6 for implementing canvas dragging functionality, supporting panning the entire canvas by dragging with a mouse or touching the screen. This is the most basic and commonly used navigation behavior in graph visualization, allowing users to freely explore graph content beyond the current viewport.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Navigating and browsing large charts to view content outside the current viewport\n- Adjusting the view focus to move areas of interest to the center of the viewport\n- Combining with zoom interactions to achieve a complete canvas navigation experience\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // Only allow horizontal dragging\n      key: 'drag-behavior', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                          | Type                                                                                                                                                               | Default                                                                                                           | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | -------- |\n| type        | Behavior type name                                                                                                                                                                                                   | string                                                                                                                                                             | `drag-canvas`                                                                                                     | ✓        |\n| enable      | Whether to enable this behavior                                                                                                                                                                                      | boolean \\| ((event: [Event](/en/api/event#event-object-properties) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(Only enabled when clicking on the canvas) |          |\n| animation   | Drag animation configuration, only effective when using keyboard movement                                                                                                                                            | [ViewportAnimationEffectTiming](/en/api/graph#viewportanimationeffecttiming)                                                                                       | -                                                                                                                 |          |\n| direction   | Allowed drag direction, optional values are: <br/>- Set to `'both'` (default): Allow dragging in any direction <br/>- Set to `'x'`: Only allow horizontal dragging <br/>- Set to `'y'`: Only allow vertical dragging | `'x'` \\| `'y'` \\| `'both'`                                                                                                                                         | `'both'` (no direction restriction)                                                                               |          |\n| range       | Draggable viewport range (in viewport size units), [example](#range)                                                                                                                                                 | number \\| number[]                                                                                                                                                 | Infinity                                                                                                          |          |\n| sensitivity | Distance to trigger a single keyboard movement                                                                                                                                                                       | number                                                                                                                                                             | 10                                                                                                                |          |\n| trigger     | Keyboard keys to trigger dragging, [example](#trigger)                                                                                                                                                               | object                                                                                                                                                             | -                                                                                                                 |          |\n| onFinish    | Callback function when dragging is completed                                                                                                                                                                         | () => void                                                                                                                                                         | -                                                                                                                 |          |\n\n### range\n\n`range` is used to control the draggable range of the canvas:\n\n- Set as a single number: Use the same value for all four directions\n- Set as an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can drag 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can drag 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], 0 means no dragging, Infinity means unlimited dragging.\n\n### trigger\n\n`trigger` allows you to configure keyboard keys to control canvas movement:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for moving up\n    down: ['ArrowDown'], // Shortcut key for moving down\n    left: ['ArrowLeft'], // Shortcut key for moving left\n    right: ['ArrowRight'] // Shortcut key for moving right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Dragging Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### Only Allow Horizontal Dragging\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // Only allow horizontal dragging\n    },\n  ],\n});\n```\n\n### Limit Dragging Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // Limit dragging range to 1.5 viewport sizes\n    },\n  ],\n});\n```\n\n### Control Movement with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // Add smooth animation effect\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. Difference between DragCanvas and other behaviors\n\n- `DragCanvas` is used for dragging the entire canvas view\n- `DragElement` is used for dragging individual graph elements (nodes/edges/combinations)\n- `ScrollCanvas` is used for scrolling the canvas with the mouse wheel without changing the zoom ratio\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragCanvas.zh.md":"---\ntitle: 拖拽画布 DragCanvas\norder: 6\n---\n\n## 概述\n\nDragCanvas 是 G6 中用于实现画布拖拽功能的内置交互，支持通过鼠标或触摸屏幕拖动来平移整个画布。这是图可视化中最基础且常用的导航交互，让用户能够自由探索超出当前视口的图内容。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 导航和浏览大型图表，查看当前视口外的内容\n- 调整视图焦点，将感兴趣的区域移动到视口中心\n- 与缩放交互结合，实现完整的画布导航体验\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // 只允许水平方向拖拽\n      key: 'drag-behavior', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                                                                   | 类型                                                                                                                                                 | 默认值                                                                                      | 必选 |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                                                           | string                                                                                                                                               | `drag-canvas`                                                                               | ✓    |\n| enable      | 是否启用该交互                                                                                                                                         | boolean \\| ((event: [Event](/api/event#事件对象属性) \\| [KeyboardEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(仅在点击画布时启用) |      |\n| animation   | 拖拽动画配置，仅在使用按键移动时有效                                                                                                                   | [ViewportAnimationEffectTiming](/api/graph#viewportanimationeffecttiming)                                                                            | -                                                                                           |      |\n| direction   | 允许的拖拽方向，可选值有：<br/>- 设为 `'both'`（默认）：允许在任意方向拖拽 <br/>- 设为 `'x'`：只允许水平方向拖拽 <br/>- 设为 `'y'`：只允许垂直方向拖拽 | `'x'` \\| `'y'` \\| `'both'`                                                                                                                           | `'both'` (不限制方向)                                                                       |      |\n| range       | 可拖拽的视口范围(以视口大小为单位)，[示例](#range)                                                                                                     | number \\| number[]                                                                                                                                   | Infinity                                                                                    |      |\n| sensitivity | 触发一次按键移动的距离                                                                                                                                 | number                                                                                                                                               | 10                                                                                          |      |\n| trigger     | 触发拖拽的键盘按键，[示例](#trigger)                                                                                                                   | object                                                                                                                                               | -                                                                                           |      |\n| onFinish    | 拖拽完成时的回调函数                                                                                                                                   | () => void                                                                                                                                           | -                                                                                           |      |\n\n### range\n\n`range` 用于控制画布可拖拽的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以拖拽2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可拖拽1个视口，左右方向可拖拽2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能拖拽，Infinity表示无限拖拽。\n\n### trigger\n\n`trigger` 允许你配置键盘按键来控制画布移动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上移动的快捷键\n    down: ['ArrowDown'], // 向下移动的快捷键\n    left: ['ArrowLeft'], // 向左移动的快捷键\n    right: ['ArrowRight'] // 向右移动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础拖拽功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### 只允许水平拖拽\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // 只允许水平拖拽\n    },\n  ],\n});\n```\n\n### 限制拖拽范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // 限制拖拽范围为1.5个视口大小\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制移动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // 添加平滑动画效果\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. DragCanvas与其他交互的区别\n\n- `DragCanvas` 用于拖拽整个画布视图\n- `DragElement` 用于拖拽单个图元素（节点/边/组合）\n- `ScrollCanvas` 用于滚轮滚动画布，不改变缩放比例\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/DragElement.en.md":"---\ntitle: DragElement\norder: 7\n---\n\n## Overview\n\nDragElement is a built-in behavior in G6 for implementing **element dragging** functionality. It has the following core features:\n\n1. **Support for multiple element types**: Supports dragging of both nodes and combos simultaneously\n2. **Intelligent multi-selection**: Supports dragging multiple selected elements at the same time\n3. **Visual feedback**: Provides various visual feedback mechanisms such as ghost nodes, edge visibility, mouse styles, etc.\n4. **Flexible drag effects**: Supports various drag operation effects such as move, link, free drag, etc.\n5. **Parent-child relationship handling**: Automatically handles element hierarchy during dragging, especially when dealing with combo structures\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // Enable ghost node\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type       | Behavior type name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | `drag-element`                                 | ✓        |\n| key        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| enable     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| animation  | Whether to enable drag animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | boolean                                                  | true                                           |          |\n| 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`                                     |          |\n| dropEffect | Defines the operation effect after dragging ends, optional values are: <br/>- `link`: Set the dragged element as a child of the target element <br/>- `move`: Move the element and automatically update the size of the parent element (such as combo) <br/>- `none`: Only update the position of the drag target without performing other operations                                                                                                                                                           | `link` \\| `move` \\| `none`                               | `move`                                         |          |\n| hideEdge   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |          |\n| shadow     | Whether to enable ghost nodes, which use a shape to follow the mouse movement. [Customize ghost node style](#shadow-style-configuration) ⚠️Note: React nodes do not support enabling                                                                                                                                                                                                                                                                                                                            | boolean                                                  | false                                          |          |\n| cursor     | Customize the mouse style during dragging, [configuration options](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                     | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n### shadow Style Configuration\n\nWhen `shadow: true` is enabled, you can customize the style of the ghost node with the following properties:\n\n| Option               | Description                       | Type                                | Default                                     |\n| -------------------- | --------------------------------- | ----------------------------------- | ------------------------------------------- |\n| shadowFill           | Ghost node fill color             | string                              | `#F3F9FF`                                   |\n| shadowFillOpacity    | Ghost node fill color opacity     | number                              | 0.5                                         |\n| shadowStroke         | Ghost node stroke color           | string                              | `#1890FF`                                   |\n| shadowStrokeOpacity  | Ghost node stroke opacity         | number                              | 0.9                                         |\n| shadowLineDash       | Ghost node dash configuration     | number[]                            | [5, 5]                                      |\n| shadowZIndex         | Ghost node rendering level        | number                              | 100                                         |\n| shadowWidth          | Ghost node width                  | number                              | Width of the target element's bounding box  |\n| shadowHeight         | Ghost node height                 | number                              | Height of the target element's bounding box |\n| shadowOpacity        | Overall opacity of the ghost node | number                              |                                             |\n| shadowLineWidth      | Ghost node line width             | number                              |                                             |\n| shadowLineCap        | Ghost node line cap style         | `'butt'` \\| `'round'` \\| `'square'` |                                             |\n| shadowLineJoin       | Ghost node line join style        | `'miter'` \\| `'round'` \\| `'bevel'` |                                             |\n| shadowLineDashOffset | Ghost node dash offset            | number                              |                                             |\n| shadowCursor         | Ghost node mouse style            | string                              |                                             |\n| shadowVisibility     | Ghost node visibility             | `'visible'` \\| `'hidden'`           |                                             |\n\nExample configuration:\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // Customize ghost node style\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> Note: The ghost node style inherits from [BaseStyleProps](/en/manual/element/shape/properties#baseshapestyle), the above configuration items are obtained by adding the `shadow` prefix to the property name.\n\n## Code Examples\n\n### Multi-selection Dragging\n\nNeed to cooperate with the `click-select` behavior to achieve multi-selection, and then associate the selected state through the `state` parameter:\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // All nodes in the selected state will be moved simultaneously during dragging\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/DragElement.zh.md":"---\ntitle: 拖拽元素 DragElement\norder: 7\n---\n\n## 概述\n\nDragElement 是 G6 中用于实现 **元素拖拽** 功能的内置交互。它具有以下核心特性：\n\n1. **多元素类型支持**：可以同时支持节点（Node）和组合（Combo）的拖拽\n2. **智能多选**：支持同时拖拽多个选中状态的元素\n3. **视觉反馈**：提供幽灵节点、边的显隐、鼠标样式等多种视觉反馈机制\n4. **灵活的拖拽效果**：支持移动、链接、自由拖拽等多种拖拽操作效果\n5. **父子关系处理**：自动处理拖拽过程中的元素层级关系，特别是在处理 Combo 结构时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // 启用拖拽幽灵节点\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type       | 交互类型名称                                                                                                                                                                                                                                                                                                                                            | string                                                   | `drag-element`                                 | ✓    |\n| key        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| enable     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| animation  | 是否启用拖拽动画                                                                                                                                                                                                                                                                                                                                        | boolean                                                  | true                                           |      |\n| state      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| dropEffect | 定义拖拽结束后的操作效果，可选值有：<br/>- `link`: 将拖拽元素设置为目标元素的子元素 <br/>- `move`: 移动元素并自动更新父元素（如 Combo）的尺寸 <br/>- `none`: 仅更新拖拽目标的位置，不执行其他操作                                                                                                                                                       | `link` \\| `move` \\| `none`                               | `move`                                         |      |\n| hideEdge   | 控制拖拽过程中边的显示状态，可选值有： <br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                     | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |      |\n| shadow     | 是否启用幽灵节点，即用一个图形代替节点跟随鼠标移动。[自定义幽灵节点样式](#shadow-样式配置) ⚠️注意：React 节点不支持启用                                                                                                                                                                                                                                 | boolean                                                  | false                                          |      |\n| cursor     | 自定义鼠标样式，[配置项](#cursor)                                                                                                                                                                                                                                                                                                                       | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n### shadow 样式配置\n\n当启用 `shadow: true` 时，可以通过以下属性自定义幽灵节点的样式：\n\n| 配置项               | 说明                   | 类型                                | 默认值               |\n| -------------------- | ---------------------- | ----------------------------------- | -------------------- |\n| shadowFill           | 幽灵节点填充色         | string                              | `#F3F9FF`            |\n| shadowFillOpacity    | 幽灵节点填充色透明度   | number                              | 0.5                  |\n| shadowStroke         | 幽灵节点描边颜色       | string                              | `#1890FF`            |\n| shadowStrokeOpacity  | 幽灵节点描边透明度     | number                              | 0.9                  |\n| shadowLineDash       | 幽灵节点虚线配置       | number[]                            | [5, 5]               |\n| shadowZIndex         | 幽灵节点渲染层级       | number                              | 100                  |\n| shadowWidth          | 幽灵节点宽度           | number                              | 目标元素的包围盒宽度 |\n| shadowHeight         | 幽灵节点高度           | number                              | 目标元素的包围盒高度 |\n| shadowOpacity        | 幽灵节点整体透明度     | number                              |                      |\n| shadowLineWidth      | 幽灵节点线宽度         | number                              |                      |\n| shadowLineCap        | 幽灵节点线段端点样式   | `'butt'` \\| `'round'` \\| `'square'` |                      |\n| shadowLineJoin       | 幽灵节点线段连接处样式 | `'miter'` \\| `'round'` \\| `'bevel'` |                      |\n| shadowLineDashOffset | 幽灵节点虚线偏移量     | number                              |                      |\n| shadowCursor         | 幽灵节点鼠标样式       | string                              |                      |\n| shadowVisibility     | 幽灵节点可见性         | `'visible'` \\| `'hidden'`           |                      |\n\n示例配置：\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // 自定义幽灵节点样式\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> 注意：幽灵节点样式继承自 [BaseStyleProps](/manual/element/shape/properties#baseshapestyle)，上述配置项是在属性名前添加 `shadow` 前缀得到的。\n\n## 代码示例\n\n### 多选推拽\n\n需要配合 `click-select` 行为实现多选，然后通过 `state` 参数关联选中状态：\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // 拖拽时会同时移动所有 selected 状态的节点\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/DragElementForce.en.md":"---\ntitle: DragElementForce\norder: 8\n---\n\n## Overview\n\nDragElementForce 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.\n\n<img alt=\"Effect of DragElementForce\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // Fix node position after dragging\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type                                       | Behavior type name, set `type: 'drag-element-force'` to enable this behavior                                                                                                                                                                                                                                                                                                                                                                                                                                    | string                                                   | `drag-element-force`                           | ✓        |\n| key                                        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| fixed                                      | Whether to keep the node position fixed after dragging ends, boolean values represent: <br/>- true: After dragging ends, the node's position will remain fixed and not be affected by the layout algorithm <br/>- false: After dragging ends, the node's position will continue to be affected by the layout algorithm                                                                                                                                                                                          | boolean                                                  | false                                          |          |\n| enable                                     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| 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`                                     |          |\n| hideEdge                                   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                          |\n| cursor                                     | Customize the mouse style during dragging, [example](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                                   | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger                                    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n## FAQ\n\n### 1. What is the difference between DragElementForce and DragElement?\n\n- `DragElementForce` is specifically used for `d3-force` or `d3-force-3d` layouts, and recalculates the layout in real-time during dragging\n- `DragElement` is a general drag interaction and does not trigger layout recalculation\n\n## Practical Example\n\n### Mesh Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### Fix Dragged Nodes\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Shadow Style\n\n### shadow{[BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#%E7%BB%98%E5%9B%BE%E5%B1%9E%E6%80%A7)}\n\n<details><summary>An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.</summary>\n\nTextStyleProps includes the following properties:\n\n- fill\n- fontSize\n- fontWeight\n- ...\n\nicon{TextStyleProps} means you need to use the following property names:\n\n- iconFill\n- iconFontSize\n- iconFontWeight\n- ...\n\n</details>\n","packages/site/docs/manual/behavior/DragElementForce.zh.md":"---\ntitle: 力导向拖拽元素 DragElementForce\norder: 8\n---\n\n## 概述\n\nDragElementForce 是 G6 中用于实现 `d3-force` 和 `d3-force-3d` 布局下节点拖拽的内置交互。在拖拽过程中会 **实时重新计算布局**，使得图的布局能够动态调整以适应节点的新位置。\n\n<img alt=\"力导向拖拽元素效果图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // 拖拽后固定节点位置\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                                     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type                                       | 交互类型名称，这里设置 `type: 'drag-element-force'` 启用此交互                                                                                                                                                                                                                                                                                          | string                                                   | `drag-element-force`                           | ✓    |\n| key                                        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| fixed                                      | 在拖拽结束后，节点是否保持固定位置，布尔值代表：<br/>- true: 在拖拽结束后，节点的位置将保持固定，不受布局算法的影响 <br/>- false: 在拖拽结束后，节点的位置将继续受到布局算法的影响                                                                                                                                                                      | boolean                                                  | false                                          |      |\n| enable                                     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| state                                      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| hideEdge                                   | 控制拖拽过程中边的显示状态，可选值有：<br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                      | `none` \\| `all` \\| `in` \\| `out` \\| `both`                                      | `none`                                                                                                                                                                                                                                                                                                                                                  |                                                          |\n| cursor                                     | 自定义鼠标样式，[示例](#cursor)                                                                                                                                                                                                                                                                                                                         | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger                                    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n## 常见问题\n\n### 1. DragElementForce 和 DragElement 有什么区别？\n\n- `DragElementForce` 专门用于 `d3-force` 或 `d3-force-3d` 布局，拖拽时会实时重新计算布局\n- `DragElement` 是通用的拖拽交互，不会触发布局重新计算\n\n## 实际案例\n\n### 网格效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### 固定被拖拽的节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FixElementSize.en.md":"---\ntitle: FixElementSize\norder: 9\n---\n\n## Overview\n\nFixElementSize is a built-in interaction provided by G6, used to **maintain the size of certain elements within nodes unchanged during the zooming process.** It enhances visual consistency and operability during zooming.\nBy listening to viewport changes, it automatically scales elements marked as \"fixed size\" to ensure they maintain a relatively constant display size at different zoom levels. It supports global enablement and also allows control over specific elements or nodes as needed.\n\n## Use Cases\n\nThis interaction is mainly used for:\n\n- Graphical elements or embedded components (buttons, labels, etc.) that need to maintain a fixed visual size\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // Enable this interaction\n      state: 'selected', // State of elements to fix size\n      reset: true, // Restore style when elements are redrawn\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                    | Type                                                                         | Default                                                                                             | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------- |\n| type        | Interaction type name                                                                                                                                                                                          | string                                                                       | `fix-element-size`                                                                                  | ✓        |\n| enable      | Whether to enable this interaction, [example](#enable)                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean) | true                                                                                                |          |\n| reset       | Whether to restore style when elements are redrawn                                                                                                                                                             | boolean                                                                      | `false`                                                                                             |          |\n| state       | Specify the state of elements to fix size                                                                                                                                                                      | string                                                                       | \"\"                                                                                                  |          |\n| node        | Node configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed, [example](#node)                                     | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| nodeFilter  | Node filter, used to filter which nodes maintain a fixed size during zooming                                                                                                                                   | (datum: [NodeData](/manual/data#nodedata)) => boolean                        | `() => true`                                                                                        |          |\n| edge        | Edge configuration item, used to define which attributes maintain a fixed visual size. By default, the lineWidth and labelFontSize attributes are fixed, usage is the same as [node configuration item](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |          |\n| edgeFilter  | Edge filter, used to filter which edges maintain a fixed size during zooming                                                                                                                                   | (datum: [EdgeData](/manual/data#edgedata)) => boolean                        | `() => true`                                                                                        |          |\n| combo       | Combo configuration item, used to define which attributes maintain a fixed visual size. By default, the entire Combo will be fixed, usage is the same as [node configuration item](#node)                      | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| comboFilter | Combo filter, used to filter which Combos maintain a fixed size during zooming                                                                                                                                 | (datum: [ComboData](/manual/data#combodata)) => boolean                      | `() => true`                                                                                        |          |\n\n### enable\n\nWhether to enable the fixed element size interaction. By default, it is enabled when zooming out the canvas\n\nBy default, it is enabled when zooming out the canvas, set `enable: (event) => event.data.scale < 1`; if you want to enable it when zooming in, set `enable: (event) => event.data.scale > 1`; if you want to enable it when both zooming in and out, set `enable: true`\n\n### node\n\nNode configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed\n\n**Example**\n\nIf you want to fix the lineWidth of the main shape of the node during zooming, you can configure it like this:\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\nIf you want to keep the size of the element label unchanged during zooming, you can configure it like this:\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| Parameter | Description                                                                                                                                                        | Type                                                   | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | ------- | -------- |\n| shape     | Specify the shape to fix size, it can be the class name of the shape, or a function that receives all shapes constituting the element and returns the target shape | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -       | ✓        |\n| fields    | Specify the fields of the shape to fix size. If not specified, the entire shape size is fixed by default                                                           | string[]                                               | -       | ✘        |\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FixElementSize.zh.md":"---\ntitle: 缩放画布时固定元素大小 FixElementSize\norder: 9\n---\n\n## 概述\n\nFixElementSize 是 G6 提供的一种内置交互，用于在视图缩放过程中，**保持节点中某些元素的尺寸不随缩放变化。** 提升缩放过程中的视觉一致性与可操作性。\n通过监听视口变化，自动对标记为“固定尺寸”的元素进行缩放补偿，确保它们在不同缩放级别下保持相对恒定的显示尺寸。支持全局启用，也支持按需控制具体元素或节点的适配行为。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要固定视觉大小的图形元素或嵌入式组件（按钮、标签等）\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // 开启该交互\n      state: 'selected', // 要固定大小的元素状态\n      reset: true, // 元素重绘时还原样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                              | 类型                                                              | 默认值                                                                                              | 必选 |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                      | string                                                            | `fix-element-size`                                                                                  | √    |\n| enable      | 是否启用该交互，[示例](#enable)                                                                                   | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean) | true                                                                                                |      |\n| reset       | 元素重绘时是否还原样式                                                                                            | boolean                                                           | `false`                                                                                             |      |\n| state       | 指定要固定大小的元素状态                                                                                          | string                                                            | \"\"                                                                                                  |      |\n| node        | 节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定，[示例](#node)   | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| nodeFilter  | 节点过滤器，用于过滤哪些节点在缩放过程中保持固定大小                                                              | (datum: [NodeData](/manual/data#节点数据nodedata)) => boolean     | `() => true`                                                                                        |      |\n| edge        | 边配置项，用于定义哪些属性在视觉上保持固定大小。默认固定 lineWidth、labelFontSize 属性，用法同[node配置项](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |      |\n| edgeFilter  | 边过滤器，用于过滤哪些边在缩放过程中保持固定大小                                                                  | (datum: [EdgeData](/manual/data#边数据edgedata)) => boolean       | `() => true`                                                                                        |      |\n| combo       | Combo 配置项，用于定义哪些属性在视觉上保持固定大小。默认整个 Combo 将被固定，用法同[node配置项](#node)            | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| comboFilter | Combo 过滤器，用于过滤哪些 Combo 在缩放过程中保持固定大小                                                         | (datum: [ComboData](/manual/data#组合数据combodata)) => boolean   | `() => true`                                                                                        |      |\n\n### enable\n\n是否启用固定元素大小交互。默认在缩小画布时启用\n\n默认在缩小画布时启用，设置 `enable: (event) => event.data.scale < 1`；如果希望在放大画布时启用，设置 `enable: (event) => event.data.scale > 1`；如果希望在放大缩小画布时都启用，设置 `enable: true`\n\n### node\n\n节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定\n\n**示例**\n\n如果在缩放过程中希望固定节点主图形的 lineWidth，可以这样配置：\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\n如果在缩放过程中想保持元素标签大小不变，可以这样配置：\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| 参数   | 描述                                                                                                 | 类型                                                   | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------ | ---- |\n| shape  | 指定要固定大小的图形，可以是图形的类名字，或者是一个函数，该函数接收构成元素的所有图形并返回目标图形 | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -      | ✓    |\n| fields | 指定要固定大小的图形属性字段。如果未指定，则默认固定整个图形的大小                                   | string[]                                               | -      | ✘    |\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FocusElement.en.md":"---\ntitle: FocusElement\norder: 10\n---\n\n## Overview\n\nFocusElement is a built-in behavior in G6 used to implement the element focusing feature, allowing elements to be focused to the center of the view by clicking on them. This behavior helps users quickly locate and focus on specific graph elements.\n\n## Use Cases\n\n- Quickly center the focused nodes or edges in the display\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                                                                                                 | Type                                                            | Default                                | Required |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | -------- |\n| type      | Behavior type name                                                                                                                                                                                                                                                                                                                                                          | string                                                          | `focus-element`                        | ✓        |\n| animation | Focus animation settings                                                                                                                                                                                                                                                                                                                                                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |          |\n| enable    | Whether to enable the focus feature                                                                                                                                                                                                                                                                                                                                         | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |          |\n| trigger   | Press this shortcut key in combination with mouse perform foucs element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | [`shift`]                              |          |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## Code Examples\n\n### Basic Focus Feature\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### Custom Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### Conditional Focus Enablement\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // Enable focus only for nodes, not edges\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/FocusElement.zh.md":"---\ntitle: 聚焦元素 FocusElement\norder: 10\n---\n\n## 概述\n\nFocusElement 是 G6 中用于实现元素聚焦功能的内置交互，支持通过点击元素将其聚焦到视图中心。这个交互可以帮助用户快速定位和关注特定的图元素。\n\n## 使用场景\n\n- 快速将关注的节点或边居中显示\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                                                                                           | 类型                                                            | 默认值                                 | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | ---- |\n| type      | 交互类型名称                                                                                                                                                                                                                                                   | string                                                          | `focus-element`                        | ✓    |\n| animation | 聚焦动画效果设置                                                                                                                                                                                                                                               | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |      |\n| enable    | 是否启用聚焦功能                                                                                                                                                                                                                                               | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |      |\n| trigger   | 同时按下快捷键才能聚焦元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | []                                     |      |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## 代码示例\n\n### 基础聚焦功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### 自定义动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用聚焦\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // 只对节点启用聚焦，边不聚焦\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/HoverActivate.en.md":"---\ntitle: HoverActivate\norder: 11\n---\n\n## Overview\n\nHoverActivate is a built-in behavior in G6 used to implement the hover activation effect on elements. When the mouse hovers over nodes or edges, it automatically triggers visual feedback such as highlighting and displaying. This behavior is an important means of enhancing data exploration in graph visualization, helping users quickly focus on target elements and obtain related information.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly locating elements of interest in complex relationship graphs\n- Displaying additional information of nodes through hover\n- Highlighting connection paths by activating edges when analyzing relationships between nodes\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option        | Description                                 | Type                                           | Default          | Required |\n| ------------- | ------------------------------------------- | ---------------------------------------------- | ---------------- | -------- |\n| type          | Behavior type name                          | string                                         | `hover-activate` | ✓        |\n| animation     | Whether to enable animation                 | boolean                                        | true             |          |\n| enable        | Whether to enable hover feature             | boolean \\| ((event: IPointerEvent) => boolean) | true             |          |\n| degree        | Degree of relationship to activate elements | number \\| ((event: IPointerEvent) => number);  | 0                |          |\n| direction     | Specify edge direction                      | `both` \\| `in` \\| `out`                        | `both`           |          |\n| state         | State of activated elements                 | string                                         | `active`         |          |\n| inactiveState | State of inactive elements                  | string                                         | -                |          |\n| onHover       | Callback when element is hovered            | (event: IPointerEvent) => void                 | -                |          |\n| onHoverEnd    | Callback when hover ends                    | (event: IPointerEvent) => void                 | -                |          |\n\n### enable\n\n`enable` is used to control whether to enable hover highlighting of elements, and can receive a function for dynamic control\n\nFor example: Enable hover highlighting only for nodes\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hover Usage\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n### Node Trigger Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### Flowchart Node Hover Next Node Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/behavior/HoverActivate.zh.md":"---\ntitle: 悬停激活 HoverActivate\norder: 11\n---\n\n## 概述\n\nHoverActivate 是 G6 中用于实现元素悬停激活效果的内置交互，当鼠标悬停在节点或边上时，会自动触发高亮、显示等视觉反馈。该交互是图可视化中增强数据探索的重要手段，有助于用户快速聚焦目标元素并获取相关信息。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 在复杂关系图中快速定位关注元素\n- 通过悬停信息展示节点额外信息\n- 分析节点间关联关系时，通过激活边凸显连接路径\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项        | 说明                 | 类型                                           | 默认值           | 必选 |\n| ------------- | -------------------- | ---------------------------------------------- | ---------------- | ---- |\n| type          | 交互类型名称         | string                                         | `hover-activate` | ✓    |\n| animation     | 是否开启动画效果     | boolean                                        | true             |      |\n| enable        | 是否开启悬浮元素功能 | boolean \\| ((event: IPointerEvent) => boolean) | true             |      |\n| degree        | 激活元素的n度关系    | number \\| ((event: IPointerEvent) => number);  | 0                |      |\n| direction     | 指定边方向           | `both` \\| `in` \\| `out`                        | `both`           |      |\n| state         | 激活元素的状态       | string                                         | `active`         |      |\n| inactiveState | 不激活元素的状态     | string                                         | -                |      |\n| onHover       | 当元素被悬停时的回调 | (event: IPointerEvent) => void                 | -                |      |\n| onHoverEnd    | 当悬停结束时的回调   | (event: IPointerEvent) => void                 | -                |      |\n\n### enable\n\n`enable` 用于控制是否开启元素的悬浮高亮，可接收一个函数来动态控制\n\n例如：只有节点开启悬浮高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础悬浮用法\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n### 节点触发高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### 流程图移入节点 下一步节点高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/behavior/LassoSelect.en.md":"---\ntitle: LassoSelect\norder: 12\n---\n\n## Overview\n\nClick and drag the mouse to draw an **irregular** box to enclose elements, and the elements within the selected range will be selected.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly selecting a batch of elements, making it easier to avoid elements you don't want to select\n- Quickly deselecting a batch of elements, making it easier to avoid elements you want to keep\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                      | Description                                                                                                                                                                                                                               | Type                                                                                                                           | Default                   | Required |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | -------- |\n| type                        | Behavior type name. This plugin is built-in, you can use it by `type: 'lasso-select'`.                                                                                                                                                    | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓        |\n| animation                   | Whether to enable animation                                                                                                                                                                                                               | boolean                                                                                                                        | false                     |          |\n| enable                      | Whether to enable lasso selection                                                                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean)                                                   | true                      |          |\n| enableElements              | Types of elements that can be selected                                                                                                                                                                                                    | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |          |\n| [immediately](#immediately) | Whether to select immediately, only effective when [selection mode](#mode) is `default`                                                                                                                                                   | boolean                                                                                                                        | false                     |          |\n| [mode](#mode)               | Selection mode                                                                                                                                                                                                                            | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |          |\n| onSelect                    | Callback for selected element state                                                                                                                                                                                                       | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |          |\n| state                       | State to switch to when selected                                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |          |\n| [style](#style)             | Style of the box during selection                                                                                                                                                                                                         | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [Default](#style)         |          |\n| trigger                     | Press this shortcut key along with mouse click to select **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: [], // No need for other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nSelection mode\n\n- `union`: Keep the current state of selected elements and add the specified state.\n- `intersect`: Retain the specified state if the selected elements already have it; otherwise, clear the state.\n- `diff`: Toggle the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Property          | Description             | Type                                     | Default   |\n| ----------------- | ----------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style             | string                                   |           |\n| fill              | Fill color              | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity            | number \\| string                         | 0.1       |\n| isBillboard       | Billboard mode          | boolean                                  |           |\n| isSizeAttenuation | Size attenuation        | boolean                                  |           |\n| lineCap           | Line cap style          | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash line config        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash line offset        | number                                   |           |\n| lineJoin          | Line join style         | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width              | number \\| string                         | 1         |\n| opacity           | Overall opacity         | number \\| string                         |           |\n| radius            | Rectangle corner radius | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur level       | number                                   |           |\n| shadowColor       | Shadow color            | string                                   |           |\n| shadowOffsetX     | Shadow X offset         | number                                   |           |\n| shadowOffsetY     | Shadow Y offset         | number                                   |           |\n| stroke            | Stroke color            | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity          | number \\| string                         |           |\n| visibility        | Visibility              | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level         | number                                   | 2         |\n\n**Example**:\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\nPress this shortcut key along with mouse click to select, if set to an **empty array**, it means mouse click to select without needing to press other keys.\n\nNote that setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to be disabled. They cannot be configured simultaneously.\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/LassoSelect.zh.md":"---\ntitle: 套索选择 LassoSelect\norder: 12\n---\n\n## 概述\n\n鼠标点击拖出一个 **不规则的** 框框笼罩元素，精准框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素，并且更容易的避开不想选的元素\n- 快速取消选中一批元素，并且更容易的避开想保留的元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                      | 说明                                                                                                                                                                                                          | 类型                                                                                                                           | 默认值                    | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---- |\n| type                        | 交互类型名称。此插件已内置，你可以通过 `type: 'lasso-select'` 来使用它。                                                                                                                                      | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓    |\n| animation                   | 是否启用动画                                                                                                                                                                                                  | boolean                                                                                                                        | false                     |      |\n| enable                      | 是否启用框选功能                                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                              | true                      |      |\n| enableElements              | 可框选的元素类型                                                                                                                                                                                              | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |      |\n| [immediately](#immediately) | 是否及时框选, 仅在[框选模式 mode](#mode)为 `default` 时生效                                                                                                                                                   | boolean                                                                                                                        | false                     |      |\n| [mode](#mode)               | 框选的选择模式                                                                                                                                                                                                | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |      |\n| onSelect                    | 框选元素状态回调                                                                                                                                                                                              | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |      |\n| state                       | 被选中时切换到该状态                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |      |\n| [style](#style)             | 框选时的 框样式                                                                                                                                                                                               | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [默认值](#style)          |      |\n| trigger                     | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n框选的选择模式\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\n按下该快捷键配合鼠标点击进行框选，若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合。\n\n注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md":"---\ntitle: OptimizeViewportTransform\norder: 13\n---\n\n## Overview\n\nOptimizeViewportTransform is a built-in behavior in G6 used to enhance the performance of large-scale graph behaviors.\n\nThis behavior implements a **selective rendering strategy**, temporarily hiding non-critical visual elements during viewport transformations (such as dragging, zooming, scrolling, etc.) to significantly reduce rendering computation load, improve frame rate, and response speed. After the viewport transformation operation ends, the system automatically restores the visibility of all elements after a set delay to ensure complete visual presentation.\n\nThis behavior is implemented based on the [event system](/en/api/event) by listening to the `GraphEvent.BEFORE_TRANSFORM` and `GraphEvent.AFTER_TRANSFORM` events, precisely capturing the start and end timing of viewport transformations, and dynamically controlling element visibility. Therefore, it must be used in conjunction with viewport operation behaviors (such as `drag-canvas`, `zoom-canvas`, or `scroll-canvas`) to be effective.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Smooth behavior of large-scale graphs (thousands of nodes/edges)\n- Performance-sensitive application scenarios\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // Specify an identifier for the behavior for dynamic updates\n      debounce: 300, // Set a longer debounce time\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                          | Type                                   | Default                       | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | -------- |\n| type     | Behavior type name                                                                                                   | string                                 | `optimize-viewport-transform` | ✓        |\n| enable   | Whether to enable this behavior                                                                                      | boolean \\| ((event: Event) => boolean) | true                          |          |\n| debounce | How long after the operation ends to restore the visibility of all elements (milliseconds)                           | number                                 | 200                           |          |\n| shapes   | Specify the graphical elements that should remain visible during canvas operations, [configuration options](#shapes) | function                               | `(type) => type === 'node'`   |          |\n\n### Shapes\n\n`shapes` is used to specify the graphical elements that need to remain visible during canvas operations. By default, nodes are always visible, while edges and combos are temporarily hidden during canvas operations to improve performance.\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // Dynamically decide whether to remain visible based on element type and graphical object\n    if (type === 'node') return true; // All nodes remain visible\n    if (type === 'edge' && shape.get('importante')) return true; // Important edges remain visible\n    return false; // Other graphics are hidden\n  };\n}\n```\n\n[Example](#keep-specific-elements-visible)\n\n## Code Examples\n\n### Basic Optimization Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### Custom Debounce Time\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // Set a longer debounce time, restoring visibility of all elements 0.5 seconds after the operation stops\n    },\n  ],\n});\n```\n\n### Keep Specific Elements Visible\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 Try dragging the canvas to see the effect\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Enable/Disable Optimization Based on Graph Element Count\n\nYou can dynamically decide whether to enable optimization based on the number of graph elements:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // Enable optimization when exceeding 500 elements\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. When should this behavior be used?\n\nWhen the graph contains a large number of nodes and edges (usually more than 500 elements), using this behavior can significantly improve operational smoothness. It is especially useful in environments with high performance requirements or limited hardware performance.\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md":"---\ntitle: 优化视口变换 OptimizeViewportTransform\norder: 13\n---\n\n## 概述\n\nOptimizeViewportTransform 是 G6 中用于提升大规模图表交互性能的内置交互。\n\n该交互通过实现**选择性渲染策略**，在视口变换过程中（即用户进行拖拽、缩放、滚动等操作时）临时隐藏非关键视觉元素，从而显著降低渲染计算负载，提高帧率和响应速度。当视口变换操作结束后，系统会在设定的延迟时间后自动恢复所有元素的可见性，确保完整的视觉呈现。\n\n此交互基于 [事件系统](/api/event) 实现，通过监听 `GraphEvent.BEFORE_TRANSFORM` 和 `GraphEvent.AFTER_TRANSFORM` 事件，精确捕捉视口变换的开始和结束时机，进而执行元素可见性的动态控制。因此，必须与视口操作类交互（如 `drag-canvas`、`zoom-canvas` 或 `scroll-canvas`）配合使用才能发挥作用。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 大规模图表（上千节点/边）的流畅交互\n- 性能敏感的应用场景\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // 为交互指定标识符，方便动态更新\n      debounce: 300, // 设置更长的防抖时间\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                          | 类型                                   | 默认值                        | 必选 |\n| -------- | ------------------------------------------------------------- | -------------------------------------- | ----------------------------- | ---- |\n| type     | 交互类型名称                                                  | string                                 | `optimize-viewport-transform` | ✓    |\n| enable   | 是否启用该交互                                                | boolean \\| ((event: Event) => boolean) | true                          |      |\n| debounce | 操作结束后多长时间恢复显示所有元素（毫秒）                    | number                                 | 200                           |      |\n| shapes   | 指定在操作画布过程中始终保持可见的图形元素，[配置项](#shapes) | function                               | `(type) => type === 'node'`   |      |\n\n### Shapes\n\n`shapes` 用于指定在画布操作过程中需要保持可见的图形元素。默认情况下，节点始终可见，而边和组合在操作画布时会被临时隐藏以提升性能。\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // 根据元素类型和图形对象动态决定是否保持可见\n    if (type === 'node') return true; // 所有节点保持可见\n    if (type === 'edge' && shape.get('importante')) return true; // 重要的边保持可见\n    return false; // 其他图形隐藏\n  };\n}\n```\n\n[示例](#保持特定元素可见)\n\n## 代码示例\n\n### 基础优化功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### 自定义防抖时间\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // 设置更长的防抖时间，在操作停止后0.5秒才恢复显示所有元素\n    },\n  ],\n});\n```\n\n### 保持特定元素可见\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 试试拖拽一下画布，看看效果吧\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 根据图表元素数量动态启用/禁用优化\n\n可以根据图表元素数量动态决定是否启用优化：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // 超出500个元素时启用优化\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 什么情况下应该使用此交互？\n\n当图表包含大量节点和边（通常超过500个元素）时，使用此交互可以显著提升操作流畅度。在性能要求高或硬件性能有限的环境中尤其有用。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ScrollCanvas.en.md":"---\ntitle: ScrollCanvas\norder: 14\n---\n\n## Overview\n\nScrollCanvas is a built-in behavior in G6 used to implement the canvas scrolling feature, supporting panning the canvas using the mouse wheel or keyboard arrow keys. This interaction is particularly useful for browsing larger charts, allowing users to explore different areas of the chart without changing the zoom level.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large chart content that exceeds the visible area\n- Exploring different parts of the graph while maintaining the current zoom level\n- Precisely adjusting the view position, especially when precise scrolling is needed in one-dimensional directions\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n      direction: 'y', // Allow only vertical scrolling\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                         | Type                                                                                                                                                                                          | Default                          | Required |\n| -------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------- |\n| type           | Behavior type name                                                                  | string                                                                                                                                                                                        | `scroll-canvas`                  | ✓        |\n| enable         | Whether to enable this behavior                                                     | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                             |          |\n| direction      | Allowed scrolling direction, [configuration options](#direction)                    | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (no direction limit) |          |\n| range          | Scrollable viewport range (in viewport size units), [configuration options](#range) | number \\| number[]                                                                                                                                                                            | 1                                |          |\n| sensitivity    | Scrolling sensitivity, the larger the value, the faster the scrolling               | number                                                                                                                                                                                        | 1                                |          |\n| trigger        | Keyboard shortcuts to trigger scrolling, [configuration options](#trigger)          | object                                                                                                                                                                                        | -                                |          |\n| onFinish       | Callback function when scrolling is finished                                        | () => void                                                                                                                                                                                    | -                                |          |\n| preventDefault | Whether to prevent the browser's default event                                      | boolean                                                                                                                                                                                       | true                             |          |\n\n### Direction\n\n`direction` is used to limit the scrolling direction:\n\n- Not set or set to `undefined`: Allow scrolling in any direction\n- Set to `'x'`: Allow only horizontal scrolling\n- Set to `'y'`: Allow only vertical scrolling\n\nThis is useful in specific visualization scenarios, such as in timeline charts where only horizontal scrolling may be needed.\n\n### Range\n\n`range` is used to control the scrollable range of the canvas:\n\n- Set to a single number: Use the same value for all four directions\n- Set to an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can scroll 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can scroll 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], where 0 means no scrolling, and Infinity means unlimited scrolling.\n\n### Trigger\n\n`trigger` allows you to configure keyboard arrow keys to control canvas scrolling:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for scrolling up\n    down: ['ArrowDown'], // Shortcut key for scrolling down\n    left: ['ArrowLeft'], // Shortcut key for scrolling left\n    right: ['ArrowRight'] // Shortcut key for scrolling right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Scrolling Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### Allow Only Horizontal Scrolling\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // Allow only horizontal scrolling\n    },\n  ],\n});\n```\n\n### Custom Scrolling Sensitivity and Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // Increase scrolling sensitivity\n      range: [0.5, 2, 0.5, 2], // Smaller limits up and down, larger limits left and right\n    },\n  ],\n});\n```\n\n### Control Scrolling with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What is the difference between ScrollCanvas and ZoomCanvas?\n\n- `ScrollCanvas` is used to pan the canvas without changing the zoom level\n- `ZoomCanvas` is used to zoom the canvas, changing the view's zoom level\n\nThey are often used together to provide complete canvas navigation functionality:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ScrollCanvas.zh.md":"---\ntitle: 滚动画布 ScrollCanvas\norder: 14\n---\n\n## 概述\n\nScrollCanvas 是 G6 中用于实现画布滚动功能的内置交互，支持通过鼠标滚轮或键盘方向键平移画布。这种交互方式对于浏览较大的图表特别有用，能让用户在不改变缩放比例的情况下探索图表的不同区域。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览超出可视区域的大型图表内容\n- 在保持当前缩放比例的情况下探索图的不同部分\n- 精确调整查看位置，尤其是在一维方向上需要精确滚动时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n      direction: 'y', // 只允许垂直方向滚动\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                 | 类型                                                                                                                                                                                          | 默认值                   | 必选 |\n| -------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ---- |\n| type           | 交互类型名称                                         | string                                                                                                                                                                                        | `scroll-canvas`          | ✓    |\n| enable         | 是否启用该交互                                       | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                     |      |\n| direction      | 允许的滚动方向，[配置项](#direction)                 | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (不限制方向) |      |\n| range          | 可滚动的视口范围(以视口大小为单位)，[配置项](#range) | number \\| number[]                                                                                                                                                                            | 1                        |      |\n| sensitivity    | 滚动灵敏度，值越大滚动速度越快                       | number                                                                                                                                                                                        | 1                        |      |\n| trigger        | 触发滚动的键盘快捷键，[配置项](#trigger)             | object                                                                                                                                                                                        | -                        |      |\n| onFinish       | 滚动完成时的回调函数                                 | () => void                                                                                                                                                                                    | -                        |      |\n| preventDefault | 是否阻止浏览器默认事件                               | boolean                                                                                                                                                                                       | true                     |      |\n\n### Direction\n\n`direction` 用于限制滚动的方向：\n\n- 不设置或设为 `undefined`：允许在任意方向滚动\n- 设为 `'x'`：只允许水平方向滚动\n- 设为 `'y'`：只允许垂直方向滚动\n\n这在特定的可视化场景下很有用，例如在时间轴图表中可能只需要水平滚动。\n\n### Range\n\n`range` 用于控制画布可滚动的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以滚动2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可滚动1个视口，左右方向可滚动2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能滚动，Infinity表示无限滚动。\n\n### Trigger\n\n`trigger` 允许你配置键盘方向键来控制画布滚动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上滚动的快捷键\n    down: ['ArrowDown'], // 向下滚动的快捷键\n    left: ['ArrowLeft'], // 向左滚动的快捷键\n    right: ['ArrowRight'] // 向右滚动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础滚动功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### 只允许水平滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // 只允许水平滚动\n    },\n  ],\n});\n```\n\n### 自定义滚动灵敏度和范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // 提高滚动灵敏度\n      range: [0.5, 2, 0.5, 2], // 上下方向限制较小，左右方向限制较大\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. ScrollCanvas 和 ZoomCanvas 有什么区别？\n\n- `ScrollCanvas` 用于平移画布，不改变缩放比例\n- `ZoomCanvas` 用于缩放画布，改变视图的缩放比例\n\n两者常结合使用，提供完整的画布导航功能：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ZoomCanvas.en.md":"---\ntitle: ZoomCanvas\nordeR: 15\n---\n\n## Overview\n\nZoomCanvas is a built-in behavior in G6 used to implement the canvas zooming feature, supporting zooming in and out of the canvas using the mouse wheel or keyboard shortcuts. This is one of the most commonly used interactions in graph visualization, helping users view both the overall structure and local details of the graph.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large-scale graph data, freely switching between the whole and details\n- Focusing on specific areas for detailed analysis\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                            | Type                                                                                | Default             | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------------- | -------- |\n| type           | Behavior type name                                                                                     | string                                                                              | `zoom-canvas`       | ✓        |\n| animation      | Zoom animation effect settings                                                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |          |\n| enable         | Whether to enable this behavior                                                                        | boolean \\| ((event: Event) => boolean)                                              | true                |          |\n| origin         | Zoom center point (viewport coordinates)                                                               | [Point](/api/viewport#point)                                                        | -                   |          |\n| onFinish       | Callback function when zooming is finished                                                             | () => void                                                                          | -                   |          |\n| preventDefault | Whether to prevent the browser's default event                                                         | boolean                                                                             | true                |          |\n| sensitivity    | Zoom sensitivity, the larger the value, the faster the zoom                                            | number                                                                              | 1                   |          |\n| trigger        | How to trigger zooming, supports mouse wheel and keyboard shortcuts, [configuration options](#trigger) | string[] \\| object                                                                  | -                   |          |\n\n### Trigger\n\n`trigger` has two usage methods, suitable for different scenarios:\n\n#### Method 1: Modifier keys combined with the mouse wheel\n\nIf you want to trigger zooming only when certain keys are pressed while scrolling the mouse wheel, you can configure it like this:\n\n```javascript\n{\n  trigger: ['Control']; // Hold down the Control key and scroll the mouse wheel to zoom\n}\n```\n\nCommon modifier keys include:\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> Not sure what value corresponds to a keyboard key? Refer to [MDN Key Values](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).\n\n#### Method 2: Pure keyboard shortcuts\n\nIf you want to control zooming entirely using the keyboard, you can set up key combinations:\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // Zoom in shortcut\n    zoomOut: ['Control', '-'], // Zoom out shortcut\n    reset: ['Control', '0']    // Reset zoom ratio shortcut\n  }\n}\n```\n\n## Code Examples\n\n### Basic Zoom Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### Custom Zoom Center\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n### Custom Zoom Sensitivity\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n    },\n  ],\n});\n```\n\n### Zoom with Shift + Mouse Wheel\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // Hold down the Shift key and scroll to zoom\n    },\n  ],\n});\n```\n\n### Control Zoom with Keyboard Shortcuts\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = to zoom in\n        zoomOut: ['Control', '-'], // Ctrl + - to zoom out\n        reset: ['Control', '0'], // Ctrl + 0 to reset\n      },\n    },\n  ],\n});\n```\n\n### Supports pinch-to-zoom on mobile devices\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // Other configurations for the PC side...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What if the canvas zoom exceeds the expected range?\n\nTo avoid excessive zooming in or out, you can set zoom limits:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  zoomRange: [0.5, 3], // Allow zooming out to 50% and zooming in to 300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. How to use it with other interactions?\n\nZooming and dragging are common combinations for a complete navigation experience:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. Conflicts when using two-finger touchpad input and scroll-canvas simultaneously\n\nOn a touchpad, both two-finger swipe (for scrolling) and pinch (for zooming) gestures are often interpreted as `wheel` events.\n\nBecause both `zoom-canvas` and `scroll-canvas` respond to `wheel` events by default, using them together can cause conflicts, such as a single gesture triggering both scrolling and zooming.\n\nYou can resolve this by checking the `event.ctrlKey` property. On most platforms, a pinch gesture sets `event.ctrlKey` to `true`, while a swipe does not. This allows you to conditionally enable `zoom-canvas` only for pinch gestures.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // When ctrlKey is true, it performs a two-finger pinch or spread operation; when false, it performs a two-finger swipe operation.\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/ZoomCanvas.zh.md":"---\ntitle: 缩放画布 ZoomCanvas\nordeR: 15\n---\n\n## 概述\n\nZoomCanvas 是 G6 中用于实现画布缩放功能的内置交互，支持通过鼠标滚轮或键盘快捷键调整画布缩放比例。这是图可视化中最常用的交互之一，能帮助用户查看图的整体结构和局部细节。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览大规模图数据，在整体与细节之间自由切换\n- 聚焦到特定区域进行详细分析\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                     | 类型                                                                                | 默认值              | 必选 |\n| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------- | ---- |\n| type           | 交互类型名称                                             | string                                                                              | `zoom-canvas`       | ✓    |\n| animation      | 缩放动画效果设置                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |      |\n| enable         | 是否启用该交互                                           | boolean \\| ((event: Event) => boolean)                                              | true                |      |\n| origin         | 缩放中心点(视口坐标)                                     | [Point](/api/viewport#point)                                                        | -                   |      |\n| onFinish       | 缩放完成时的回调函数                                     | () => void                                                                          | -                   |      |\n| preventDefault | 是否阻止浏览器默认事件                                   | boolean                                                                             | true                |      |\n| sensitivity    | 缩放灵敏度，值越大缩放速度越快                           | number                                                                              | 1                   |      |\n| trigger        | 触发缩放的方式，支持滚轮和键盘快捷键，[配置项](#trigger) | string[] \\| object                                                                  | -                   |      |\n\n### Trigger\n\n`trigger`有两种使用方式，分别适用于不同场景：\n\n#### 方式一：与滚轮结合的修饰键\n\n当你希望只有在按下某些键的同时滚动滚轮才触发缩放时，可以这样配置：\n\n```javascript\n{\n  trigger: ['Control']; // 按住 Control 键同时滚动鼠标滚轮才能缩放\n}\n```\n\n常见的修饰键有：\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> 不知道键盘按键对应什么值？请参考 [MDN Key Values](https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values)。\n\n#### 方式二：纯键盘快捷键\n\n当你希望完全使用键盘控制缩放操作时，可以设置组合键：\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // 放大快捷键\n    zoomOut: ['Control', '-'], // 缩小快捷键\n    reset: ['Control', '0']    // 重置缩放比例快捷键\n  }\n}\n```\n\n## 代码示例\n\n### 基础缩放功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 自定义缩放中心\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n### 自定义缩放灵敏度\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n    },\n  ],\n});\n```\n\n### 使用Shift+滚轮进行缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // 按住 Shift 键同时滚动才能缩放\n    },\n  ],\n});\n```\n\n### 使用键盘快捷键控制缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = 放大\n        zoomOut: ['Control', '-'], // Ctrl + - 缩小\n        reset: ['Control', '0'], // Ctrl + 0 重置\n      },\n    },\n  ],\n});\n```\n\n### 支持移动端双指缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // PC 端其他配置...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 画布缩放超出了预期范围怎么办？\n\n为避免缩放过大或过小，可以设置缩放限制：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  zoomRange: [0.5, 3], // 允许缩小到50%和放大到300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. 如何与其他交互结合使用？\n\n缩放与拖拽是常见的组合，实现完整的导航体验：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. 触控板双指操作下，与 scroll-canvas 同时使用时的冲突\n\n在触控板上，双指滑动（用于滚动）和双指捏合（用于缩放）手势通常都会被解析为 `wheel` 事件。\n\n由于 `zoom-canvas` 和 `scroll-canvas` 默认都会响应 `wheel` 事件，当它们同时使用时会产生冲突，例如一个手势会同时触发滚动和缩放。\n\n你可以通过检查 `event.ctrlKey` 属性来解决这个问题。在多数平台上，捏合手势会使 `event.ctrlKey` 为 `true`，而滑动则不会。这允许你有条件地仅为捏合手势启用 `zoom-canvas`。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // ctrlKey 为 true 时，是双指捏合或扩张操作，false 时是双指滑动操作\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/behavior/custom-behavior.en.md":"---\ntitle: Custom Behavior\norder: 16\n---\n\n## Overview\n\nCustom behavior allows users to define one or more related interaction behaviors as a complete interaction based on the comprehensive [event mechanism](/en/api/event) provided by G6, thereby achieving interaction logic that fits business scenarios.\n\n### Execution Logic of Behavior\n\nTypically:\n\n1. Listen for user interaction events\n\n2. Update the canvas or perform other operations based on the events\n\nFor example, the `DragCanvas` behavior listens for pointer drag events and updates the camera position based on the drag distance.\n\n### Difference Between Behavior and Plugin\n\n- Both behavior and plugin base classes are derived from the [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) base class within G6, so the implementation methods for behavior and plugin are basically the same.\n- However, based on the concept of visualization, behavior is usually used to handle user interaction events, while plugins are usually used to handle canvas rendering logic, additional component rendering, etc.\n\n:::info{title=Tip}\nDue to conceptual distinctions, behavior instances cannot be obtained, while plugin instances can be obtained ([getPluginInstance](/en/api/plugin#graphgetplugininstancekey)).\n:::\n\n## When to Use Custom Behavior?\n\n- **Purpose**:\n\n  When users need to implement interaction logic that fits business scenarios, we usually need to cooperate with G6's event system to respond to related events and execute the required interaction logic.\n\n- **Without Custom Behavior**:\n\n  If custom behavior is not used, users need to perform a series of event listening and response processing through `graph.on` after creating a Graph instance, making code logic processing and orchestration extremely difficult.\n\n- **Advantages of Behavior**:\n\n  Each behavior is an independent code module, and the existence of the behavior system facilitates users to decouple business logic, avoid code bloat, and facilitate subsequent maintenance.\n\n- **Conclusion**:\n\n  > 1. When users need to implement any interaction logic, they should first consider custom behavior.\n  > 2. When built-in behavior cannot fully meet business needs, users can also adjust and modify through custom behavior (inheriting built-in behavior).\n  >\n  > _(If the features supported by built-in behavior are more general, or if there are bugs in built-in behavior, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Implementing Behavior\n\nThe implementation of a behavior is quite flexible, and you can implement your behavior in your preferred style.\n\nBelow is a simple custom behavior implementation. When the user clicks on the canvas, a node is added to the canvas (the fill color of the added node can be defined through behavior configuration):\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // Unbind events when destroyed\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In the example code, we implemented a `ClickAddNode` behavior, which adds an event listener to the Graph in the constructor. When the user clicks on the canvas, a node is added at the click position, and the fill color of the added node can be configured.\n- `BaseBehavior` is the base class for all behaviors, and each custom behavior needs to inherit this base class.\n\n> Click on the blank area of the canvas below to add a node, and switch the right panel to configure the node color.\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=Tip}\nThe above example is the simplest behavior implementation. In actual development, you may also need to handle logic such as enabling and disabling behaviors.\n\nIn addition, there may be event conflicts between multiple behaviors, and you need to handle these conflicts carefully.\n:::\n\n## Registering Behavior\n\nRegister through the register method provided by G6\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## Configuring Behavior\n\nYou can pass in the behavior type name or configuration parameter object in `behaviors`, such as the above ClickAddNode. See [Configuring Behavior](/en/manual/behavior/overview#配置和使用) for details.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/custom-behavior.zh.md":"---\ntitle: 自定义交互\norder: 16\n---\n\n## 概述\n\n自定义交互允许用户基于 G6 提供的完善的[事件机制](/api/event)，把一个或多个相关的交互行为定义为一个完整的交互，以此实现符合业务场景的交互逻辑。\n\n### 交互的执行逻辑\n\n通常为：\n\n1. 监听用户交互事件\n\n2. 根据事件更新画布或执行其他操作\n\n例如 `DragCanvas` 交互监听指针拖拽事件，根据拖拽的距离更新相机的位置。\n\n### 交互与插件的区别\n\n- 交互和插件的基类都是由 G6 内部的 [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) 基类派生而来，因此交互和插件的实现方式基本相同\n- 但基于可视化的概念区分，交互通常用于处理用户交互事件，而插件通常用于处理画布的渲染逻辑、额外组件渲染等\n\n:::info{title=提示}\n因概念上的区分，交互实例不可获取，插件实例可获取（ [getPluginInstance](/api/plugin#graphgetplugininstancekey) ）\n:::\n\n## 什么时候需要自定义交互？\n\n- **目的**：\n\n  当用户在实现符合业务场景的交互逻辑时，我们通常需要配合 G6 的事件系统，对相关事件作出响应，执行需要的交互逻辑。\n\n- **不使用自定义交互**：\n\n  如果不使用自定义交互，用户需要在创建 Graph 实例后，通过 `graph.on` 进行一系列的事件监听和响应处理，代码逻辑处理和编排会显得异常艰难。\n\n- **交互的优势**：\n\n  每个交互行为都是独立的代码模块，交互系统的存在方便用户解耦业务逻辑、避免代码臃肿以及方便用户后续维护等。\n\n- **结论**：\n\n  > 1、当用户需要实现任何交互逻辑时，应当首先考虑自定义交互。\n  >\n  > 2、当内置交互无法完全满足业务需求时，用户也可以通过自定义交互（继承内置交互）进行调整和修改。\n  >\n  > _（如果需要内置交互支持的特性是较通用的，或者内置交互存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 实现交互\n\n一个交互的实现相当灵活，你可以以你喜欢的风格实现你的交互。\n\n下面是一个简单的自定义交互实现，当用户点击画布时，会在画布上添加一个节点（可通过交互配置定义所添加节点的填充颜色）：\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // 销毁时解绑事件\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在示例代码中，我们实现了一个 `ClickAddNode` 交互，该交互在构造函数中添加了 Graph 的事件监听，当用户点击画布时，会在点击位置添加一个节点，并且支持配置所添加节点的填充颜色。\n- `BaseBehavior` 是所有交互的基类，每个自定义交互都需要继承这个基类实现。\n\n> 点击下面画布中的空白位置以添加一个节点，可切换右侧面板配置节点颜色\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=提示}\n上述示例是一个最简单的交互实现，实际开发过程中，你可能还需要处理交互的启用与禁用等逻辑。\n\n此外，多个交互之间可能会有事件冲突，你需要小心处理这些冲突。\n:::\n\n## 注册交互\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## 配置交互\n\n可在 `behaviors` 中传入交互类型名称或配置参数对象，比如上面的 ClickAddNode ，详见[配置交互](/manual/behavior/overview#配置和使用)\n\n```typescript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","packages/site/docs/manual/behavior/overview.en.md":"---\ntitle: Behavior Overview\norder: 0\n---\n\n## What is Behavior\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nBehavior refers to the interactive operations between users and chart elements, such as dragging the canvas, selecting nodes, zooming the view, etc. Good behavior design allows users to explore and understand graph data more intuitively. **Proper configuration of behaviors is a key step in building efficient and usable charts**.\n\n### Changes in G6 5.0 Behavior System\n\nG6 5.0 removed the concept of \"Behavior Mode\" (Mode), and directly lists the required behavior behaviors in `behaviors`, simplifying the configuration. This makes behavior configuration more intuitive and easier to get started with.\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## Built-in Behaviors\n\nG6 provides a variety of built-in behaviors that are **ready to use without registration**:\n\n| Category            | Behavior Name                                                                  | Registration Type             | Function Description                                         |\n| ------------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------------------------------ |\n| Navigation          |                                                                                |                               |                                                              |\n|                     | [Drag Canvas](/en/manual/behavior/drag-canvas)                                 | `drag-canvas`                 | Drag the entire canvas view                                  |\n|                     | [Zoom Canvas](/en/manual/behavior/zoom-canvas)                                 | `zoom-canvas`                 | Zoom the canvas view                                         |\n|                     | [Scroll Canvas](/en/manual/behavior/scroll-canvas)                             | `scroll-canvas`               | Scroll the canvas using the wheel                            |\n|                     | [Optimize Viewport Transform](/en/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | Optimize view transform performance                          |\n| Selection           |                                                                                |                               |                                                              |\n|                     | [Click Select](/en/manual/behavior/click-select)                               | `click-select`                | Click to select graph elements                               |\n|                     | [Brush Select](/en/manual/behavior/brush-select)                               | `brush-select`                | Select elements by dragging a rectangular area               |\n|                     | [Lasso Select](/en/manual/behavior/lasso-select)                               | `lasso-select`                | Freely draw an area to select elements                       |\n| Editing             |                                                                                |                               |                                                              |\n|                     | [Create Edge](/en/manual/behavior/create-edge)                                 | `create-edge`                 | Interactively create new edges                               |\n|                     | [Drag Element](/en/manual/behavior/drag-element)                               | `drag-element`                | Drag nodes or combos                                         |\n|                     | [Force-directed Drag](/en/manual/behavior/drag-element-force)                  | `drag-element-force`          | Drag nodes in force-directed layout                          |\n| Data Exploration    |                                                                                |                               |                                                              |\n|                     | [Collapse/Expand](/en/manual/behavior/collapse-expand)                         | `collapse-expand`             | Expand or collapse subtree nodes                             |\n|                     | [Focus Element](/en/manual/behavior/focus-element)                             | `focus-element`               | Focus on specific elements and automatically adjust the view |\n|                     | [Hover Activate](/en/manual/behavior/hover-activate)                           | `hover-activate`              | Highlight elements when hovering                             |\n| Visual Optimization |                                                                                |                               |                                                              |\n|                     | [Fix Element Size](/en/manual/behavior/fix-element-size)                       | `fix-element-size`            | Fix the element size to a specified value                    |\n|                     | [Auto-adapt Label](/en/manual/behavior/auto-adapt-label)                       | `auto-adapt-label`            | Automatically adjust label position                          |\n\nFor detailed configuration of each behavior, refer to the [Built-in Behavior Documentation](/en/manual/behavior/drag-canvas).\n\n:::warning{title=Behavior Compatibility}\nSome behaviors may overlap in triggering mechanisms, such as `brush-select` and `drag-canvas` both using mouse dragging. In such cases, you can avoid conflicts by modifying the trigger key (e.g., hold `Shift` to drag and select).\n:::\n\n## Custom Behaviors\n\nWhen built-in behaviors cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend by inheriting built-in behaviors\n- Create entirely new behavior behaviors\n\nUnlike built-in behaviors, **custom behaviors need to be registered before use**. For detailed tutorials, refer to the [Custom Behavior](/en/manual/behavior/custom-behavior) documentation.\n\n## Configuration and Usage\n\n### Basic Configuration\n\nThe simplest way is to directly specify the required behaviors through the `behaviors` array when initializing the graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### Configure Behavior Parameters\n\nFor behaviors that require custom parameters, you can configure properties using the `object` form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // Configure sensitivity\n      key: 'zoom-behavior', // Specify a key for the behavior for subsequent updates\n    },\n  ],\n});\n```\n\n### Dynamically Update Behaviors\n\nG6 supports dynamically managing behavior behaviors during the runtime of the graph instance to meet complex behavior needs:\n\nYou can adjust behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method:\n\n```javascript\n// Add new behavior\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// Remove behavior\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\nYou can update the configuration of behaviors using the [updateBehavior](/en/api/behavior#graphupdatebehaviorbehavior) method:\n\n```javascript\n// Update a single behavior\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // Disable the behavior\n});\n```\n\n:::warning{title=Note}\nWhen using the `updateBehavior` method, you need to specify a unique `key` for the behavior during initialization.\n:::\n\n### Uninstall Behaviors\n\nYou can also uninstall behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method by setting the behavior configuration list to empty:\n\n```javascript\ngraph.setBehaviors([]);\n```\n\nFor more behavior-related APIs, refer to the [Behavior API Documentation](/en/api/behavior).\n\n## Behavior and Events\n\nBehaviors are essentially implemented through event listening and response. Although built-in behaviors have encapsulated common behavior behaviors, you can also directly implement custom behavior logic through the event API.\n\n### Event Listening Example\n\n```javascript\n// Use event constants (recommended)\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// Listen for node clicks\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen for edge hover\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\nThe event system is the foundation for implementing behaviors. Mastering the event API is crucial for understanding and extending behavior behaviors. For more event-related information, refer to the [Event Documentation](/en/api/event).\n","packages/site/docs/manual/behavior/overview.zh.md":"---\ntitle: 交互总览\norder: 0\n---\n\n## 什么是交互\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n交互(Behavior)是指用户与图表元素之间的互动操作，如拖拽画布、选择节点、缩放视图等。良好的交互设计能让用户更直观地探索和理解图数据。**合理配置交互是构建高效可用图表的关键环节**。\n\n### G6 5.0 交互系统变化\n\nG6 5.0 移除了 \"交互模式\"(Mode) 概念，直接在 `behaviors` 中列出需要的交互行为，简化了配置方式。这使得交互配置更加直观，上手更加简单。\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## 内置交互\n\nG6 提供了多种开箱即用的内置交互，**无需注册，直接配置即可使用**：\n\n| 分类     | 交互名称                                                     | 注册类型                      | 功能描述                   |\n| -------- | ------------------------------------------------------------ | ----------------------------- | -------------------------- |\n| 导航     |                                                              |                               |                            |\n|          | [拖拽画布](/manual/behavior/drag-canvas)                     | `drag-canvas`                 | 拖动整个画布视图           |\n|          | [缩放画布](/manual/behavior/zoom-canvas)                     | `zoom-canvas`                 | 缩放画布视图               |\n|          | [滚动画布](/manual/behavior/scroll-canvas)                   | `scroll-canvas`               | 使用滚轮滚动画布           |\n|          | [优化视口变换](/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | 优化视图变换性能           |\n| 选择     |                                                              |                               |                            |\n|          | [点击选择](/manual/behavior/click-select)                    | `click-select`                | 点击选择图元素             |\n|          | [框选](/manual/behavior/brush-select)                        | `brush-select`                | 通过拖拽矩形区域选择元素   |\n|          | [套索选择](/manual/behavior/lasso-select)                    | `lasso-select`                | 自由绘制区域选择元素       |\n| 编辑     |                                                              |                               |                            |\n|          | [创建边](/manual/behavior/create-edge)                       | `create-edge`                 | 交互式创建新的边           |\n|          | [拖拽元素](/manual/behavior/drag-element)                    | `drag-element`                | 拖动节点或组合             |\n|          | [力导向拖拽](/manual/behavior/drag-element-force)            | `drag-element-force`          | 力导向布局中拖动节点       |\n| 数据探索 |                                                              |                               |                            |\n|          | [折叠/展开](/manual/behavior/collapse-expand)                | `collapse-expand`             | 展开或收起子树节点         |\n|          | [聚焦元素](/manual/behavior/focus-element)                   | `focus-element`               | 聚焦特定元素，自动调整视图 |\n|          | [悬停激活](/manual/behavior/hover-activate)                  | `hover-activate`              | 鼠标悬停时高亮元素         |\n| 视觉优化 |                                                              |                               |                            |\n|          | [固定元素大小](/manual/behavior/fix-element-size)            | `fix-element-size`            | 将元素大小固定为指定值     |\n|          | [自适应标签](/manual/behavior/auto-adapt-label)              | `auto-adapt-label`            | 自动调整标签位置           |\n\n各交互的详细配置可参考 [内置交互文档](/manual/behavior/drag-canvas)。\n\n:::warning{title=交互兼容性}\n某些交互在触发机制上可能存在重叠，如 `brush-select` 和 `drag-canvas` 都使用鼠标拖拽。这种情况下可以通过修改触发按键（如按住 `Shift` 拖拽选择）来避免冲突。\n:::\n\n## 自定义交互\n\n当内置交互无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置交互进行扩展\n- 创建全新的交互行为\n\n与内置交互不同，**自定义交互需要先注册后使用**。详细教程请参考 [自定义交互](/manual/behavior/custom-behavior) 文档。\n\n## 配置和使用\n\n### 基本配置\n\n最简单的方式是在图实例初始化时，通过 `behaviors` 数组直接指定需要的交互：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### 配置交互参数\n\n对于需要自定义参数的交互，可以使用 `object` 的形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // 配置灵敏度\n      key: 'zoom-behavior', // 为交互指定key，便于后续更新\n    },\n  ],\n});\n```\n\n### 动态更新交互\n\nG6 支持在图实例运行期间动态管理交互行为，满足复杂交互需求：\n\n可以通过 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法调整交互：\n\n```javascript\n// 添加新交互\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// 移除交互\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\n可以使用 [updateBehavior](/api/behavior#graphupdatebehaviorbehavior) 方法更新交互的配置：\n\n```javascript\n// 更新单个交互\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // 禁用该交互\n});\n```\n\n:::warning{title=注意}\n使用`updateBehavior`方法时，需要在初始化时为交互指定唯一的`key`。\n:::\n\n### 卸载交互\n\n使用 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法同样可以卸载交互，将交互配置列表置为空即可：\n\n```javascript\ngraph.setBehaviors([]);\n```\n\n更多与交互相关的 API 请参考 [交互 API 文档](/api/behavior)。\n\n## 交互与事件\n\n交互本质上是通过事件监听和响应来实现的。虽然内置交互已经封装了常见的交互行为，但你也可以通过事件 API 直接实现自定义交互逻辑。\n\n### 事件监听示例\n\n```javascript\n// 使用事件常量（推荐）\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// 监听节点点击\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边悬停\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\n事件系统是实现交互的基础，掌握事件 API 对于理解和扩展交互行为至关重要。更多事件相关信息，请参考 [事件文档](/api/event)。\n","packages/site/docs/manual/contribute.en.md":"---\ntitle: contribute\norder: 14\n---\n\nTo contribute, you need to understand G6's code structure and development workflow. The code repository for G6 is located at: https://github.com/antvis/G6\n\nIf you want to fix a bug or add a new feature, you need to first fork a copy of the code to your repository, then make modifications in your repository, and finally submit a Pull Request (PR) to the G6 repository.\n\n## Project Structure\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 Core Implementation</small>\n          <ul>\n            <li>\n              __tests__\n              <small>Testing and Development Environment</small>\n              <ul>\n                <li>\n                  assets\n                  <small>Test Static Resources</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bugfix Test Case</small>\n                </li>\n                <li>\n                  dataset\n                  <small>Test Dataset</small>\n                </li>\n                <li>\n                  demos\n                  <small>Development Demos</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>Test Snapshots</small>\n                </li>\n                <li>\n                  perf\n                  <small>Performance Test Case</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>Performance Test Reports</small>\n                </li>\n                <li>\n                  unit\n                  <small>Test Cases</small>\n                </li>\n                <li>\n                  utils\n                  <small>Test Utility Functions</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>Animation Executors and Built-in Animations</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>Built-in Interactions</small>   \n                </li>\n                <li>\n                  constants\n                  <small>Constants and Enumeration Values</small>   \n                </li>\n                <li>\n                  elements\n                  <small>Built-in Elements</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>Built-in Combos</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>Built-in Edges</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>Built-in Nodes</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>Composite Shapes</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>Layout References and Encapsulation</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>Built-in Palettes</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>Built-in Plugins</small>   \n                </li>\n                <li>\n                  registry\n                  <small>Registry Module</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph and Core Controller</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification Type Definitions</small>   \n                </li>\n                <li>\n                  themes\n                  <small>Built-in Themes</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>Built-in Data Transformations</small>   \n                </li>\n                <li>\n                  types\n                  <small>Type Definitions</small>   \n                </li>\n                <li>\n                  utils\n                  <small>Utility Functions</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>Export Items</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>Pre-operations</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>Development Environment Vite Configuration</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D Extension</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D Behaviors</small>\n            </li>\n            <li>\n              elements\n              <small>3D Elements</small>\n            </li>\n            <li>\n              plugins\n              <small>3D Plugins</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D Renderer</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React Node Extension</small>\n          <ul>\n            <li>\n              elements\n              <small>React Elements</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph Encapsulation</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>Official Website and Documentation</small>\n          <ul>\n            <li>\n              docs\n              <small>Tutorials and API</small>\n            </li>\n            <li>\n              examples\n              <small>Graph Examples</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>Configuration File</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## Development Process\n\n1. Fork and Pull the Code\n\nFork the G6 repository on Github to your account, then clone it locally.\n\n```bash\n# Navigate to your workspace\ncd /path/to/your/workspace\n\n# Navigate to the G6 directory\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. Install Dependencies\n\n:::warning{title=Warning}\nPlease ensure your local environment meets the following requirements:\n\n- [Node.js](https://nodejs.org/) version >= 18\n- [pnpm](https://pnpm.io/) version >= 8\n\n:::\n\n```bash\n# Enter the G6 code directory\ncd G6\n\n# Install Dependencies\npnpm install\n```\n\n3. Start the Development Environment\n\n```bash\n# Enter the g6 code directory.\ncd ./packages/g6\n\n# Start the development environment\npnpm dev\n```\n\nAt this point, you can access G6's development environment and preview the examples by visiting http://127.0.0.1:8080 in your web browser.\n\n4. Develop New Features or Fix Bugs\n\nSwitch to a development branch:\n\n```bash\ngit checkout -b [branch name]\n```\n\nMake code modifications according to your needs and test locally.\n\n5. Write Test Cases\n\nIn the `packages/g6/__tests__/unit` directory, write test cases to ensure your code behaves as expected.\n\nValidate Your Code with Tests：\n\n```bash\npnpm test\n```\n\n6. Submit a Pull Request (PR)\n\n```bash\n# Stage changes\ngit add .\n\n# Commit Changes\ngit commit -m \"[commit type]: commit message\"\n\n# Push to Your Repository\ngit push\n```\n\nSubmit a Pull Request (PR) to the G6 repository on GitHub.\n\n## Testing and Coverage\n\nG6 utilizes Jest for conducting unit tests, with the test cases situated in the `packages/g6/__tests__/unit` directory.\n\nWe require that all code submissions must pass tests to ensure code quality.\n\nThe coverage rate for the current PR (Pull Request) submission is advised not to fall below the coverage rate of the existing codebase, and it is <text style=\"color: red;\">not to fall below 90%</text>.\n\n### Update Test Snapshots\n\nG6 extends Jest tests and provides the `toMatchSnapshot` assertion for generating and comparing snapshots.\n\nIf the current possible modification affects the generation of some screenshots, it is necessary to check whether there are failed test cases by executing `pnpm test`.\n\nWhen a failed test case is found, the console will print the path of the failed test, as well as the path information of the benchmark screenshot and the current screenshot. You can hold the `Ctrl` or `Command` key and click the path to view the specific test case or screenshot.\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\nIf it is confirmed that this modification is correct, then please manually delete the corresponding benchmark screenshots and regenerate the screenshots:\n\n**Regenerate all screenshots**:\n\n1. Delete all files in the `packages/g6/__tests__/unit/snapshots` directory\n2. Execute `pnpm test`\n\n**Regenerate a single screenshot**:\n\n1. Delete the corresponding file in the `packages/g6/__tests__/snapshots` directory (test cases in the `unit` directory will generate the corresponding directory under `snapshots`)\n2. Execute `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## Code Standards\n\nThe G6 code adheres to the following standards:\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## Commit Conventions\n\nG6 adopts the [Conventional Commits](https://www.conventionalcommits.org/) specification, and the commit message format is as follows:\n\n```\n<type>[optional scope]: <description>\n```\n\nThe type field can be one of the following:\n\n- feat: A new feature\n- fix: A bug fix\n- docs: Documentation update\n- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)\n- refactor: Code change that neither fixes a bug nor adds a feature\n- perf: A code change that improves performance\n- test: Adding missing or correcting existing tests\n- build: Changes that affect the build system or external dependencies\n- ci: Changes to our CI configuration files and scripts\n- chore: Other changes that don't modify src or test files\n- revert: Reverts a previous commit\n\nFor example:\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\nPlease ensure that your commit messages conform to the standards, and try to use English descriptions whenever possible. This helps us better manage the code.\n\n## Pull Request (PR) Standards\n\nAfter completing the above steps, you can submit a PR to the G6 repository. Please ensure that your PR adheres to the following standards:\n\n- A single PR should address only one issue.\n- The title of the PR should be concise and clear.\n- The description of the PR should be clear and detailed. If the changes involve the user interface, please include screenshots.\n- The PR must pass CI (Continuous Integration) checks.\n\n## Code Review\n\nAfter your PR is submitted, we will review your code. Please be patient and await the results of the review. If there are any areas that require modification, we will point them out within the PR.\n\n## Release Process\n\nWe regularly release new versions. If your PR is for a non-urgent bug fix, it will be included in the next release. If your PR addresses an urgent bug fix, we will release a new version as soon as possible.\n\nThis project uses changeset to manage version release, and the specific release process is as follows:\n\n1. Complete related development work\n2. Create a branch from v5 (any name you want)\n3. Run `npm run version` command, fill in the information according to the prompt, and the version number will be updated automatically\n4. Commit the changes to the remote repository\n5. Create a PR on GitHub, add the `publish` label, and merge the branch to v5\n6. After the branch is merged, GitHub Actions will be triggered automatically, and the package will be published to npm\n7. After the release, the Release note needs to be updated. Execute \"pnpm tag\" in the packages/g6\n8. Fill in the tag information on the newly opened Github link. First, select the previous tag, and then select the current tag to obtain the changes. After confirming that there are no issues, release it.\n","packages/site/docs/manual/contribute.zh.md":"---\ntitle: 参与贡献\norder: 14\n---\n\n要参与贡献，你需要了解 G6 的代码结构和开发流程。G6 的代码仓库地址是：https://github.com/antvis/G6\n\n如果你想要修复一个 bug 或者增加一个新功能，你需要先 fork 一份代码到你的仓库，然后在你的仓库中进行修改，最后提交 PR 到 G6 的仓库。\n\n## 项目结构\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 核心实现</small>\n          <ul>\n            <li>\n              __tests__\n              <small>测试及开发环境</small>\n              <ul>\n                <li>\n                  assets\n                  <small>测试静态资源</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bug 修复测试用例</small>\n                </li>\n                <li>\n                  dataset\n                  <small>测试数据集</small>\n                </li>\n                <li>\n                  demos\n                  <small>开发示例</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>测试截图</small>\n                </li>\n                <li>\n                  perf\n                  <small>性能测试用例</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>性能测试报告</small>\n                </li>\n                <li>\n                  unit\n                  <small>测试用例</small>\n                </li>\n                <li>\n                  utils\n                  <small>测试工具函数</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>动画执行器及内置动画</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>内置交互</small>   \n                </li>\n                <li>\n                  constants\n                  <small>常量及枚举值</small>   \n                </li>\n                <li>\n                  elements\n                  <small>内置元素</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>内置组合</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>内置边</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>内置节点</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>复合图形</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>布局引用及封装</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>内置色板</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>内置插件</small>   \n                </li>\n                <li>\n                  registry\n                  <small>注册模块</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph 及核心控制器</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification 类型定义</small>   \n                </li>\n                <li>\n                  themes\n                  <small>内置主题</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>内置数据转换</small>   \n                </li>\n                <li>\n                  types\n                  <small>类型定义</small>   \n                </li>\n                <li>\n                  utils\n                  <small>工具函数</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>导出项</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>预操作</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>开发环境 Vite 配置</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D 扩展</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D 交互</small>\n            </li>\n            <li>\n              elements\n              <small>3D 元素</small>\n            </li>\n            <li>\n              plugins\n              <small>3D 插件</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D 渲染器</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React 节点扩展</small>\n          <ul>\n            <li>\n              elements\n              <small>React 元素</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph 封装</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>官网及文档</small>\n          <ul>\n            <li>\n              docs\n              <small>教程及 API</small>\n            </li>\n            <li>\n              examples\n              <small>图表示例</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>配置文件</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## 开发流程\n\n1. Fork 并拉取代码\n\n在 Github 中 Fork [G6](https://github.com/antvis/G6) 到你的仓库，并拉取到本地。\n\n```bash\n# 进入你的工作目录\ncd /path/to/your/workspace\n\n# 克隆 G6 代码\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. 安装依赖\n\n:::warning{title=注意}\n请验证你的本地环境是否符合要求：\n\n- [Node.js](https://nodejs.org/) 版本 >= 18\n- [pnpm](https://pnpm.io/) 版本 >= 8\n\n:::\n\n```bash\n# 进入 G6 代码目录\ncd G6\n\n# 安装依赖\npnpm install\n```\n\n3. 启动开发环境\n\n```bash\n# 进入 G6 代码目录\ncd ./packages/g6\n\n# 启动开发环境\npnpm dev\n```\n\n此时，你可以在浏览器中访问 `http://127.0.0.1:8080` 查看 G6 的开发环境并预览开发示例。\n\n4. 开发新功能或修复 bug\n\n切换到开发分支：\n\n```bash\ngit checkout -b [branch name]\n```\n\n根据你的需求，修改代码并在本地测试。\n\n5. 编写测试用例\n\n在 `packages/g6/__tests__/unit` 目录下编写测试用例，确保你的代码符合预期。\n\n确保你的代码通过测试：\n\n```bash\npnpm test\n```\n\n6. 提交 PR\n\n```bash\n# 添加修改\ngit add .\n\n# 提交修改\ngit commit -m \"[commit type]: commit message\"\n\n# 推送到你的仓库\ngit push\n```\n\n在 Github 中提交 PR 到 G6 仓库。\n\n## 测试与覆盖率\n\nG6 使用 Jest 进行单元测试，测试用例位于 `packages/g6/__tests__/unit` 目录下。\n\n我们要求所有的代码提交都需要通过测试，确保代码质量。\n\n当前 PR 提交的覆盖率不建议低于当前代码库的覆盖率，且<text style=\"color: red;\">不得低于 90%</text>。\n\n### 更新测试截图\n\nG6 扩展了 Jest 测试，提供了 `toMatchSnapshot` 断言用于生成以及对比快照。\n\n如果当前可能修改影响了部分截图的生成，需要通过执行 `pnpm test` 检查是否有测试用例失败。\n\n当发现测试失败的用例时，控制台会打印出失败的测试路径，以及基准截图和当前截图的路径信息。你可以按住 `Ctrl` 或 `Command` 键并点击路径，查看具体的测试用例或截图。\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\n如果确认本次修改是正确的，那么请手动删除对应的基准截图，并重新生成截图：\n\n**重新生成全部截图**：\n\n1. 删除 `packages/g6/__tests__/unit/snapshots` 目录下的所有文件\n2. 执行 `pnpm test`\n\n**重新生成单个截图**：\n\n1. 删除 `packages/g6/__tests__/snapshots` 目录下对应的文件（`unit`目录下测试用例会在`snapshots`下生成对应的目录）\n2. 执行 `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## 代码规范\n\nG6 编码尊循以下规范：\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## 提交规范\n\nG6 采用 [Conventional Commits](https://www.conventionalcommits.org/) 规范，提交信息格式如下：\n\n```\n<type>[optional scope]: <description>\n```\n\ntype 有以下几种：\n\n- feat: 新功能\n- fix: 修复 bug\n- docs: 文档更新\n- style: 代码格式（不影响代码运行的变动）\n- refactor: 重构\n- perf: 性能优化\n- test: 测试\n- build: 构建工具相关的变动\n- ci: CI 配置\n- chore: 其他无关紧要的变动\n- revert: 撤销\n\n例如：\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\n请确保你的提交信息符合规范，并尽量使用英文描述，这样有助于我们更好地管理代码。\n\n## PR 规范\n\n完成上述步骤后，你可以提交 PR 到 G6 仓库。请确保你的 PR 符合以下规范：\n\n- 一个 PR 只解决一个问题\n- PR 的标题简洁明了\n- PR 的描述清晰详细，涉及视图的变动请附上截图\n- PR 必需能够通过 CI 检查\n\n## 代码 Review\n\nPR 提交后，我们会对你的代码进行 Review。请耐心等待 Review 结果，如果有需要修改的地方，我们会在 PR 中提出。\n\n## 发布流程\n\n我们会定期发布新版本，如果你的 PR 是非紧急缺陷修复，我们会在下一个版本中发布。如果你的 PR 是紧急缺陷修复，我们会尽快发布新版本。\n\n本项目通过 changeset 来管理版本发布，具体的发布流程如下：\n\n1. 完成相关的开发工作\n2. 从 v5 分支创建一个分支（任意分支名均可）\n3. 根目录执行 `npm run version` 命令，根据提示填写相关信息，会自动更新版本号\n4. 将变更提交到远程仓库\n5. 在 GitHub 上创建一个 PR，并添加 `publish` 标签，将该分支合并到 v5 分支\n6. 分支合并后，会自动触发 GitHub Actions，发布到 npm\n7. 发布后，需更新 Release note，在 packages/g6 目录下执行 pnpm tag\n8. 在新打开的 Github 链接填写 tag 信息，先选择前一个 tag, 然后选择当前 tag 后得到变更，确认没有问题后发布\n","packages/site/docs/manual/data.en.md":"---\ntitle: Data\norder: 1\n---\n\n## Overview\n\nG6 is a data-driven charting library, where data is one of the most important concepts. In G6, data is the core of the chart, and both display and interaction are based on data.\n\nCommon graph data formats include:CSV, [DOT](https://graphviz.org/doc/info/lang.html), GDF, GML, [GraphML](http://graphml.graphdrawing.org/), [GEXF](https://gexf.net/) etc。\n\nG6 uses JSON format to describe the graph structure, which includes information about nodes and edges. Here is a simple JSON data example:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\" }, { \"id\": \"node2\" }],\n  \"edges\": [{ \"source\": \"node1\", \"target\": \"node2\" }]\n}\n```\n\nCompared to the other formats mentioned above, the JSON format has a more intuitive and understandable data structure. It is also more flexible, allowing for easy expansion of node and edge attributes.\n\nIt is a data exchange format widely supported by computers, so you do not have to worry about data format compatibility issues.\n\n## Data Structure\n\nIn G6, graph data consists of three parts: `nodes` (node data), `edges` (edge data), and `combos` (combo data). Each part corresponds to different elements in the graph, and their types and data determine how the graph is displayed.\n\n```ts\ninterface GraphData {\n  nodes: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data (optional)\n  combos?: ComboData[]; // Combo data (optional)\n}\n```\n\n### Node Data\n\nA node is the basic building block of a graph and represents an entity within the graph. Each node has a unique `id` used to identify it, and nodes can also have data, styles, and states.\n\n| Attribute                                 | Type               | Description                                                                                                        |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the node, used to distinguish different nodes                                                |\n| type                                      | _string_           | Node type. It can be the type of built-in Node, or the custom Node                                                 |\n| data                                      | _Object_           | Custom data for the node, such as name, description, etc. Can be accessed in style mappings via callback functions |\n| style                                     | _Object_           | Node style, including position, size, color, and other visual properties                                           |\n| states                                    | _string[]_         | Initial states for the node, such as selected, active, hover, etc.                                                 |\n| combo                                     | _string_ \\| _null_ | ID of the combo the node belongs to. Used to organize hierarchical relationships. If none, it is null              |\n| children                                  | _string[]_         | Collection of child node IDs, used only in tree diagrams                                                           |\n\n**Example:**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### Edge Data\n\nAn edge connects nodes and represents the relationship between them. Each edge is associated with two nodes (source and target), and edges themselves can have data, styles, and states. Edge data is often used to represent logical relationships, such as user connections in social networks or step flows in flowcharts.\n\n| Attribute                                     | Type       | Description                                                                                                             |\n| --------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |\n| <Badge type=\"success\">Required</Badge> source | _string_   | Source node ID                                                                                                          |\n| <Badge type=\"success\">Required</Badge> target | _string_   | Target node ID                                                                                                          |\n| id                                            | _string_   | Unique identifier for the edge. If not specified, `id` is automatically generated with the format `${source}-${target}` |\n| type                                          | _string_   | Edge type.It can be the type of built-in Edge, or the custom Edge                                                       |\n| data                                          | _Object_   | Custom data for the edge, accessible in style mappings via callback functions                                           |\n| style                                         | _Object_   | Edge style, including stroke color, line width, arrowhead, etc.                                                         |\n| states                                        | _string[]_ | Initial states for the edge                                                                                             |\n\n**Example:**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Combo Data\n\nCombos allow you to create a logical unit for multiple nodes, used for layering, grouping, or other structural purposes. A combo can contain child nodes or other combos, forming a nested structure.\n\n| Attribute                                 | Type               | Description                                                                    |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the combo                                                |\n| type                                      | _string_           | Combo type.It can be the type of built-in Combo, or the custom Combo           |\n| data                                      | _Object_           | Custom data for the combo, accessible in style mappings via callback functions |\n| style                                     | _Object_           | Combo style                                                                    |\n| states                                    | _string[]_         | Initial states for the combo                                                   |\n| combo                                     | _string_ \\| _null_ | Parent combo ID. If there is no parent combo, it is null                       |\n\n**Example:**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## Data Organization and Best Practices\n\nTo ensure correct rendering and interaction of the graph, it is recommended to organize the data according to G6's standard data structure. Each element (node, edge, combo) should contain a `data` field to store business data and custom properties.\n\n- **Avoid using identifiers that conflict with internal G6 field names**, such as `id`, `type`, `style`, etc., to prevent naming conflicts.\n- Store business data (such as user information, social network relationships, etc.) in the `data` field. This ensures flexibility and scalability of the data.\n\n**Example:**\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"node1\",\n      \"data\": { \"name\": \"Alice\", \"role\": \"Admin\" }\n    },\n    {\n      \"id\": \"node2\",\n      \"data\": { \"name\": \"Bob\", \"role\": \"User\" }\n    }\n  ],\n  \"edges\": [\n    {\n      \"source\": \"node1\",\n      \"target\": \"node2\",\n      \"data\": { \"relationship\": \"friend\" }\n    }\n  ]\n}\n```\n\n## API\n\nG6 provides a series of APIs to access and manipulate data, including:\n\n- [getData](/en/api/data#graphgetdata)\n- [setData](/en/api/data#graphsetdata)\n- [getNodeData](/en/api/data#graphgetnodedata)\n- [getEdgeData](/en/api/data#graphgetedgedata)\n- [getComboData](/en/api/data#graphgetcombodata)\n- [addData](/en/api/data#graphadddata)\n- [addNodeData](/en/api/data#graphaddnodedata)\n- [addEdgeData](/en/api/data#graphaddedgedata)\n- [addComboData](/en/api/data#graphaddcombodata)\n- [updateData](/en/api/data#graphupdatedata)\n- [updateNodeData](/en/api/data#graphupdatenodedata)\n- [updateEdgeData](/en/api/data#graphupdateedgedata)\n- [updateComboData](/en/api/data#graphupdatecombodata)\n- [removeData](/en/api/data#graphremovedata)\n- [removeNodeData](/en/api/data#graphremovenodedata)\n- [removeEdgeData](/en/api/data#graphremoveedgedata)\n- [removeComboData](/en/api/data#graphremovecombodata)\n\nThrough different APIs, you can conveniently access and manipulate graph data, performing operations such as adding, deleting, modifying, and querying the graph.\n\n## Use Remote Data\n\nG6 does not provide functionality for data retrieval and parsing. For local JSON data, you can directly import and use it as follows:\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\nFor remote data, you can use `fetch` or other networking libraries to retrieve the data:\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // Use data\n  });\n```\n","packages/site/docs/manual/data.zh.md":"---\ntitle: 数据 Data\norder: 4\n---\n\n## 概述\n\nG6 是一款数据驱动的图可视化引擎，数据是 G6 中最重要的概念之一。\n\nG6 使用标准的 JSON 格式描述图数据结构。以下是一个基础的图数据示例：\n\n```javascript {4-7}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n});\n```\n\n## 数据结构\n\n图数据包含三部分：`nodes`（节点数据）、`edges`（边数据）、`combos`（组合数据）。每一部分对应图中的不同元素，它们的类型和数据决定了图如何展示。\n\n### 图数据（GraphData）\n\n| 属性   | 描述     | 类型                              | 默认值 | 必选 |\n| ------ | -------- | --------------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#节点数据nodedata)[]   | -      |      |\n| edges  | 边数据   | [EdgeData](#边数据edgedata)[]     | -      |      |\n| combos | 组合数据 | [ComboData](#组合数据combodata)[] | -      |      |\n\n### 节点数据（NodeData）\n\n节点是图中的基本构成单元，它代表图中的实体。每个节点都有一个唯一的 `id`，用于标识节点，同时节点也可以有数据、样式和状态。\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### 边数据（EdgeData）\n\n边是连接节点的元素，表示节点之间的关系。每条边都与两个节点（起始节点和目标节点）关联，并且边本身可以有数据、样式和状态。边的数据常用于表示节点之间的逻辑或关系，如社交网络中的用户关系、流程图中的步骤流转等。\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n**示例：**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 组合数据（ComboData）\n\n通过组合，可以为多个节点创建一个逻辑单元，用于图形的分层、分组或其他结构化需求。组合可以包含子节点或其他组合，从而形成嵌套层次。\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## 数据操作\n\nG6 提供了丰富的 API 来操作图数据，下面展示一些常见的数据操作示例。\n\n### 数据初始化\n\n在创建图实例时，可以直接传入数据：\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n```\n\n或者通过 `setData` 方法设置数据：\n\n```javascript\ngraph.setData({\n  nodes: [\n    { id: 'node3', data: { label: '节点3' } },\n    { id: 'node4', data: { label: '节点4' } },\n  ],\n  edges: [{ source: 'node3', target: 'node4', data: { label: '新关系' } }],\n});\n```\n\n### 数据增删改查\n\n#### 添加节点和边\n\n```javascript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node5',\n    data: {\n      label: '新节点',\n      category: 'person',\n    },\n    style: {\n      fill: '#6395F9',\n      stroke: '#5B8FF9',\n    },\n  },\n]);\n\n// 批量添加多个节点\ngraph.addNodeData([\n  { id: 'node6', data: { label: '批量节点1' } },\n  { id: 'node7', data: { label: '批量节点2' } },\n]);\n\n// 添加连接新节点的边\ngraph.addEdgeData([\n  {\n    source: 'node1',\n    target: 'node5',\n    data: {\n      label: '连接到新节点',\n      weight: 2,\n    },\n    style: {\n      stroke: '#F6BD16',\n      lineWidth: 3,\n    },\n  },\n]);\n```\n\n#### 更新数据\n\n```javascript\n// 更新单个节点\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    data: {\n      label: '已更新的节点1',\n      status: 'updated',\n    },\n    style: {\n      fill: '#F6BD16',\n      stroke: '#EBEBEB',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 更新多个节点\ngraph.updateNodeData([\n  {\n    id: 'node2',\n    style: { size: 40, fill: '#5AD8A6' },\n  },\n  {\n    id: 'node3',\n    data: { importance: 'high' },\n  },\n]);\n\n// 更新边\ngraph.updateEdgeData([\n  {\n    source: 'node1',\n    target: 'node2',\n    style: {\n      stroke: '#5B8FF9',\n      lineWidth: 2,\n      lineDash: [5, 5],\n    },\n  },\n]);\n```\n\n#### 删除数据\n\n```javascript\n// 删除单个节点（以及与该节点相连的所有边）\ngraph.removeNodeData(['node7']);\n\n// 删除多个节点\ngraph.removeNodeData(['node5', 'node6']);\n\n// 删除边\ngraph.removeEdgeData(['node1-node2']);\n```\n\n#### 查询数据\n\n```javascript\n// 获取所有节点数据\nconst nodes = graph.getNodeData();\n\n// 获取所有边数据\nconst edges = graph.getEdgeData();\n\n// 获取特定节点数据\nconst node1 = graph.getNodeData('node1');\n\n// 获取特定边数据\nconst edge1 = graph.getEdgeData('node1-node2');\n```\n\n### 复杂数据结构操作\n\n#### 嵌套组合（Combo）\n\n下面是创建和操作嵌套组合的示例：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', data: { label: '节点1' }, combo: 'combo1' },\n    { id: 'node2', data: { label: '节点2' }, combo: 'combo1' },\n    { id: 'node3', data: { label: '节点3' }, combo: 'combo2' },\n    { id: 'node4', data: { label: '节点4' }, combo: 'combo2' },\n    { id: 'node5', data: { label: '节点5' }, combo: 'combo3' },\n  ],\n  edges: [\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n  combos: [\n    { id: 'combo1', data: { label: '组1' } },\n    { id: 'combo2', data: { label: '组2' } },\n    { id: 'combo3', data: { label: '组3' }, combo: 'combo1' }, // 嵌套组合\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'force',\n  },\n});\n\n// 添加新的组合\ngraph.addComboData([\n  {\n    id: 'combo4',\n    data: { label: '新组' },\n    combo: 'combo2', // 添加到现有组合中\n  },\n]);\n\n// 将节点移动到不同的组合\ngraph.updateNodeData([\n  {\n    id: 'node5',\n    combo: 'combo4', // 将节点5移动到新组合\n  },\n]);\n\n// 展开/折叠组合\ngraph.updateComboData([\n  {\n    id: 'combo1',\n    style: { collapsed: true }, // 折叠组合1\n  },\n]);\n\ngraph.render();\n```\n\n#### 树形结构数据\n\n对于树形结构，G6 支持使用 `children` 属性表示层次关系：\n\n```javascript\n// 树形结构数据\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst treeData = {\n  id: 'root',\n  children: [\n    {\n      id: 'child1',\n      children: [{ id: 'grandchild1' }],\n    },\n    {\n      id: 'child2',\n      children: [{ id: 'grandchild2' }],\n    },\n  ],\n};\n\nconst data = treeToGraphData(treeData);\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'dendrogram', // 或 'compactBox', 'mindmap' 等树布局\n    direction: 'TB', // 从上到下布局\n    nodeSep: 50, // 节点间距\n    rankSep: 100, // 层级间距\n  },\n});\n\ngraph.render();\n```\n\n通过 `treeToGraphData` 方法，可以将树形结构数据转换为 G6 的标准数据结构，实际传入到 `data` 中的数据结构如下：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"root\", \"depth\": 0, \"children\": [\"child1\", \"child2\"] },\n    { \"id\": \"child1\", \"depth\": 1, \"children\": [\"grandchild1\"] },\n    { \"id\": \"grandchild1\", \"depth\": 2 },\n    { \"id\": \"child2\", \"depth\": 1, \"children\": [\"grandchild2\"] },\n    { \"id\": \"grandchild2\", \"depth\": 2 }\n  ],\n  \"edges\": [\n    { \"source\": \"root\", \"target\": \"child1\" },\n    { \"source\": \"root\", \"target\": \"child2\" },\n    { \"source\": \"child1\", \"target\": \"grandchild1\" },\n    { \"source\": \"child2\", \"target\": \"grandchild2\" }\n  ]\n}\n```\n\n## 数据组织与最佳实践\n\n为了确保图的正确渲染和交互，建议按照 G6 标准数据结构组织数据。每个元素（节点、边、组合）应包含一个 `data` 字段，用于存放业务数据和自定义属性。\n\n- **避免使用与 G6 内部字段名称相同的标识符**，如 `id`、`type`、`style` 等，防止发生命名冲突。\n- 将业务数据（如用户信息、社交网络关系等）存储在 `data` 字段中，这样可以确保数据的灵活性和可扩展性。\n- **使用样式映射**来根据业务数据动态设置视觉属性，而不是直接修改样式对象。\n\n### 数据与样式分离\n\n良好的做法是将数据和样式分离，通过映射函数将数据属性转换为视觉属性：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 使用数据驱动样式\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', data: { value: 10, category: 'A' } },\n      { id: 'node2', data: { value: 5, category: 'B' } },\n    ],\n  },\n  node: {\n    style: {\n      // 根据数据中的 value 字段动态设置节点大小\n      size: (node) => 20 + node.data.value * 2,\n      // 根据数据中的 category 字段设置不同颜色\n      fill: (node) => {\n        const categoryColors = { A: '#F6BD16', B: '#5B8FF9' };\n        return categoryColors[node.data.category] || '#CCC';\n      },\n    },\n  },\n});\n```\n\n## API\n\nG6 提供了一系列的 API 来访问和操作数据，包括：\n\n- [getData](/api/data#graphgetdata)\n- [setData](/api/data#graphsetdata)\n- [getNodeData](/api/data#graphgetnodedata)\n- [getEdgeData](/api/data#graphgetedgedata)\n- [getComboData](/api/data#graphgetcombodata)\n- [addData](/api/data#graphadddata)\n- [addNodeData](/api/data#graphaddnodedata)\n- [addEdgeData](/api/data#graphaddedgedata)\n- [addComboData](/api/data#graphaddcombodata)\n- [updateData](/api/data#graphupdatedata)\n- [updateNodeData](/api/data#graphupdatenodedata)\n- [updateEdgeData](/api/data#graphupdateedgedata)\n- [updateComboData](/api/data#graphupdatecombodata)\n- [removeData](/api/data#graphremovedata)\n- [removeNodeData](/api/data#graphremovenodedata)\n- [removeEdgeData](/api/data#graphremoveedgedata)\n- [removeComboData](/api/data#graphremovecombodata)\n\n通过不同的 API，你可以方便地访问和操作图数据，实现图的增删改查等操作。\n\n## 使用远程数据\n\nG6 并不提供数据的获取和解析功能，对于本地 JSON 数据，你可以直接引入使用：\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\n对于远程数据，你可以使用 `fetch` 或者其他网络请求库来获取数据：\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // 使用 data\n    const graph = new Graph({\n      container: 'container',\n      data,\n    });\n    // 触发布局和渲染\n    graph.render();\n  })\n  .catch((error) => {\n    console.error('加载数据失败:', error);\n  });\n```\n","packages/site/docs/manual/element/combo/BaseCombo.en.md":"---\ntitle: Combo Common Options\norder: 1\n---\n\nThis document introduces the built-in combo common property configurations.\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {}, // Combo style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                               | Type                    | Default  | Required |\n| --------- | --------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name | [Type](#type)           | `circle` |          |\n| style     | Combo style configuration, including color, size, etc.    | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                  | [State](#state)         | -        |          |\n| palette   | Define combo palette for mapping colors based on data     | [Palette](#palette)     | -        |          |\n| animation | Define combo animation effects                            | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the combo type, built-in combo type name or custom combo name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select combo types based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Combo](/en/manual/element/combo/circle)\n- `rect`: [Rect Combo](/en/manual/element/combo/rect)\n\n## Style\n\nDefines combo style, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All style properties below support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Combo: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the combo data object (`ComboData`), containing all combo data information.\n\nA complete combo consists of the following parts:\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the primary shape of the combo, such as circle, rectangle, etc.\n- `label`: Text label, usually used to display the combo's name or description\n- `halo`: Graphic displaying halo effect around the main graphic\n- `badge`: Badge displayed at the top-right corner of the combo by default\n\nThe following style configurations will be explained by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the combo, defining the basic shape and appearance of the combo. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdd transparency and shadow effects to combos:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreate combos with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                              | Type                          | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current combo is collapsed                                                                                                   | boolean                       | false     |          |\n| cursor                          | Combo mouse hover style, [options](#cursor)                                                                                              | string                        | default   |          |\n| fill                            | Combo fill color                                                                                                                         | string                        | `#99ADD1` |          |\n| fillOpacity                     | Combo fill opacity                                                                                                                       | number \\| string              | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick | number                        | 0         |          |\n| lineCap                         | Combo stroke end cap style                                                                                                               | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                  | number[]                      | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                 | number                        | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                  | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                       | number                        | 1         |          |\n| opacity                         | Combo opacity                                                                                                                            | number \\| string              | 1         |          |\n| pointerEvents                   | How combo responds to pointer events, [options](#pointerevents)                                                                          | string                        | `auto`    |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                        | number                        | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                       | string                        | -         |          |\n| shadowOffsetX                   | Combo shadow offset in x direction                                                                                                       | number \\| string              | -         |          |\n| shadowOffsetY                   | Combo shadow offset in y direction                                                                                                       | number \\| string              | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                        | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Combo size, quick setting for combo width and height, [options](#size)                                                                   | number \\| number[]            | -         |          |\n| stroke                          | Combo stroke color                                                                                                                       | string                        | `#99ADD1` |          |\n| strokeOpacity                   | Combo stroke opacity                                                                                                                     | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given combo                                                        | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                           | string                        | -         |          |\n| visibility                      | Whether combo is visible                                                                                                                 | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                       | number                        | 0         |          |\n| y                               | Combo y coordinate                                                                                                                       | number                        | 0         |          |\n| z                               | Combo z coordinate                                                                                                                       | number                        | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                    | number                        | 0         |          |\n\n#### Size\n\nCombo size, quick setting for combo width and height, supports three configuration methods:\n\n- number: Indicates that combo width and height are the same as the specified value\n- [number, number]: Indicates that combo width and height are represented by array elements in order for combo width and height\n- [number, number, number]: Indicates that combo width, height, and depth are represented by array elements in order\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be the target of responding events\n- **`visiblepainted`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the `fill` value\n- **`visiblestroke`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n- **`visible`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by `fill` and `stroke` values\n- **`painted`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`fill`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the `fill` value\n  - Not affected by `visibility` value\n- **`stroke`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Will respond to events as long as entering the graphic fill and stroke areas, not affected by `fill`, `stroke`, `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Does not respond to events at all\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // Combo does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Style When Expanded\n\nMain graphic style when the combo is expanded\n\n| Attribute                       | Description                                                                                                                                       | Type                                                                            | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------- | -------- |\n| collapsed                       | Whether the combo is currently collapsed                                                                                                          | boolean                                                                         | false     |          |\n| cursor                          | Combo mouse hover style, [configuration item](#cursor)                                                                                            | string                                                                          | default   |          |\n| fill                            | Combo fill color                                                                                                                                  | string                                                                          | `#99ADD1` |          |\n| fillOpacity                     | Combo fill color opacity                                                                                                                          | number  string                                                                 | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0         |          |\n| lineCap                         | Combo stroke end style                                                                                                                            | `round`  `square`  `butt`                                                     | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                           | number[]                                                                        | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                          | number                                                                          | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                           | `round`  `bevel`  `miter`                                                     | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                                | number                                                                          | 1         |          |\n| opacity                         | Combo opacity                                                                                                                                     | number  string                                                                 | 1         |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                                 | number                                                                          | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                                | string                                                                          | -         |          |\n| shadowOffsetX                   | Combo shadow offset in the x-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowOffsetY                   | Combo shadow offset in the y-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                                 | `inner`  `outer`                                                               | `outer`   |          |\n| stroke                          | Combo stroke color                                                                                                                                | string                                                                          | `#99add1` |          |\n| strokeOpacity                   | Combo stroke color opacity                                                                                                                        | number  string                                                                 | 1         |          |\n| visibility                      | Whether the combo is visible                                                                                                                      | `visible`  `hidden`                                                            | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                                | number                                                                          | 0         |          |\n| y                               | Combo y coordinate                                                                                                                                | number                                                                          | 0         |          |\n| z                               | Combo z coordinate                                                                                                                                | number                                                                          | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                             | number                                                                          | 0         |          |\n| `{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items         | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -         |          |\n\n#### Cursor\n\nOptional 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`\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      fill: '#1783FF', // Fill color\n      stroke: '#000', // Stroke color\n      lineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: { fill: '#1783FF', stroke: '#000', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Style When Collapsed\n\nEffective when `collapsed` is `true`\n\n| Attribute                                | Description                                                                                                                                                                  | Type                                                                            | Default                                  | Required |\n| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------- | -------- |\n| collapsedCursor                          | Mouse hover style when the combo is collapsed, [configuration item](#cursor)                                                                                                 | string                                                                          | Same as the cursor when expanded         |          |\n| collapsedFill                            | Fill color when the combo is collapsed                                                                                                                                       | string                                                                          | Same as the fill when expanded           |          |\n| collapsedFillOpacity                     | Fill color opacity when the combo is collapsed                                                                                                                               | number  string                                                                 | 1                                        |          |\n| collapsedIncreasedLineWidthForHitTesting | When the combo is collapsed, if lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0                                        |          |\n| collapsedLineCap                         | Stroke end style when the combo is collapsed                                                                                                                                 | `round`  `square`  `butt`                                                     | Same as the lineCap when expanded        |          |\n| collapsedLineDash                        | Stroke dash style when the combo is collapsed                                                                                                                                | number[]                                                                        | Same as the lineDash when expanded       |          |\n| collapsedLineDashOffset                  | Stroke dash offset when the combo is collapsed                                                                                                                               | number                                                                          | Same as the lineDashOffset when expanded |          |\n| collapsedLineJoin                        | Stroke join style when the combo is collapsed                                                                                                                                | `round`  `bevel`  `miter`                                                     | Same as the lineJoin when expanded       |          |\n| collapsedLineWidth                       | Stroke width when the combo is collapsed                                                                                                                                     | number                                                                          | Same as the lineWidth when expanded      |          |\n| collapsedMarker                          | Whether to display the marker when the combo is collapsed, [configuration item](#collapsedMarkerStyle)                                                                       | boolean                                                                         | true                                     |          |\n| collapsedOpacity                         | Opacity when the combo is collapsed                                                                                                                                          | number  string                                                                 | Same as the opacity when expanded        |          |\n| collapsedShadowBlur                      | Shadow blur when the combo is collapsed                                                                                                                                      | number                                                                          | Same as the shadowBlur when expanded     |          |\n| collapsedShadowColor                     | Shadow color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the shadowColor when expanded    |          |\n| collapsedShadowOffsetX                   | Shadow offset in the x-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetX when expanded  |          |\n| collapsedShadowOffsetY                   | Shadow offset in the y-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetY when expanded  |          |\n| collapsedShadowType                      | Shadow type when the combo is collapsed                                                                                                                                      | `inner`  `outer`                                                               | Same as the shadowType when expanded     |          |\n| collapsedSize                            | Size when the combo is collapsed                                                                                                                                             | number &#124; [number, number] &#124; [number, number, number]                  | 32                                       |          |\n| collapsedStroke                          | Stroke color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the stroke when expanded         |          |\n| collapsedStrokeOpacity                   | Stroke color opacity when the combo is collapsed                                                                                                                             | number  string                                                                 | Same as the strokeOpacity when expanded  |          |\n| collapsedVisibility                      | Whether the combo is visible when collapsed                                                                                                                                  | `visible`  `hidden`                                                            | Same as the visibility when expanded     |          |\n| `collapsed{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items                                    | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -                                        |          |\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedFill: '#1783FF', // Fill color\n      collapsedStroke: '#000', // Stroke color\n      collapsedLineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: { collapsedFill: '#1783FF', collapsedStroke: '#000', collapsedLineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Collapsed Marker Style\n\nEffective when `collapsedMarker` is `true`\n\n| Attribute                     | Description                                                                                                                                                                                                                                                                                                                                                         | Type                                                                                                                               | Default       | Required |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| collapsedMarkerType           | Marker type displayed when the combo is collapsed <br> - `'child-count'`: Number of child elements (including Node and Combo) <br>- `'descendant-count'`: Number of descendant elements (including Node and Combo) <br>- `'node-count'`: Number of descendant elements (only including Node) <br> - `(children: NodeLikeData[]) => string`: Custom processing logic | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string)                             | `child-count` |          |\n| collapsedMarkerFill           | Icon text color                                                                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | #fff          |          |\n| collapsedMarkerFillOpacity    | Icon text color opacity                                                                                                                                                                                                                                                                                                                                             | number                                                                                                                             | 1             |          |\n| collapsedMarkerFontSize       | Icon font size                                                                                                                                                                                                                                                                                                                                                      | number                                                                                                                             | 12            |          |\n| collapsedMarkerFontWeight     | Icon font weight                                                                                                                                                                                                                                                                                                                                                    | number \\| string                                                                                                                   | `normal`      |          |\n| collapsedMarkerRadius         | Icon corner radius                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                             | 0             |          |\n| collapsedMarkerSrc            | Image source. Its priority is higher than `collapsedMarkerText`                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | -             |          |\n| collapsedMarkerText           | Icon text                                                                                                                                                                                                                                                                                                                                                           | string                                                                                                                             | -             |          |\n| collapsedMarkerTextAlign      | Icon text horizontal alignment                                                                                                                                                                                                                                                                                                                                      | `center`  `end`  `left`  `right`  `start`                                                                                      | `center`      |          |\n| collapsedMarkerTextBaseline   | Icon text alignment baseline                                                                                                                                                                                                                                                                                                                                        | `alphabetic`  `bottom`  `hanging`  `ideographic`  `middle`  `top`                                                             | `middle`      |          |\n| collapsedMarkerWidth          | Icon width                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                             | -             |          |\n| collapsedMarkerHeight         | Icon height                                                                                                                                                                                                                                                                                                                                                         | number                                                                                                                             | -             |          |\n| collapsedMarkerZIndex         | Icon rendering layer                                                                                                                                                                                                                                                                                                                                                | number                                                                                                                             | 1             |          |\n| `collapsedMarker{StyleProps}` | More icon style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text), [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) configuration items. For example, collapsedMarkerFontSize represents the font size of the text icon                                                                                           | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) &#124; [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) | -             |          |\n\n**Example:**\n\n```js {5-6}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF', // Fill color\n      collapsedMarkerFontSize: 30, // Icon font size\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 30,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Label Style\n\nLabels are used to display text information for combos, supporting rich text style configuration and flexible position layout.\n\n#### Basic Label Configuration\n\nAdd basic text label to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Sales Department', // Label text content\n      labelFill: '#1A1A1A', // Label text color\n      labelFontSize: 14, // Label font size\n      labelPlacement: 'bottom', // Label position: bottom\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nConfigure labels that support multi-line display:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'This is a combo label text content that supports multi-line display',\n      labelWordWrap: true, // Enable text wrapping\n      labelMaxWidth: 100, // Maximum width 100px\n      labelMaxLines: 3, // Maximum 3 lines\n      labelTextAlign: 'center', // Center text alignment\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Style Label\n\nCreate labels with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // Red text\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // Bold\n      labelFontStyle: 'italic', // Italic\n      labelTextDecorationLine: 'underline', // Underline\n      labelLetterSpacing: 2, // Letter spacing\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label style configurations:\n\n| Property                 | Description                                                                                                                                                                | Type                                                                        | Default   | Required |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show combo label                                                                                                                                                | boolean                                                                     | true      |          |\n| labelCursor              | Cursor style when hovering over combo label, [options](#cursor)                                                                                                            | string                                                                      | `default` |          |\n| labelFill                | Combo label text color                                                                                                                                                     | string                                                                      | #000      |          |\n| labelFillOpacity         | Combo label text color opacity                                                                                                                                             | number                                                                      | 1         |          |\n| labelFontFamily          | Combo label font family                                                                                                                                                    | string                                                                      | -         |          |\n| labelFontSize            | Combo label font size                                                                                                                                                      | number                                                                      | 12        |          |\n| labelFontStyle           | Combo label font style                                                                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Combo label font variant                                                                                                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Combo label font weight                                                                                                                                                    | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |          |\n| labelLeading             | Line spacing                                                                                                                                                               | number                                                                      | 0         |          |\n| labelLetterSpacing       | Combo label letter spacing                                                                                                                                                 | number \\| string                                                            | -         |          |\n| labelLineHeight          | Combo label line height                                                                                                                                                    | number \\| string                                                            | -         |          |\n| labelMaxLines            | Combo label maximum lines                                                                                                                                                  | number                                                                      | 1         |          |\n| labelMaxWidth            | Combo label maximum width, [options](#labelmaxwidth)                                                                                                                       | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Combo label X offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelOffsetY             | Combo label Y offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelPadding             | Combo label padding                                                                                                                                                        | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Combo label position relative to combo main graphic, [options](#labelplacement)                                                                                            | string                                                                      | `bottom`  |          |\n| labelText                | Combo label text content                                                                                                                                                   | string                                                                      | -         |          |\n| labelTextAlign           | Combo label text horizontal alignment                                                                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Combo label text baseline                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Combo label text decoration color                                                                                                                                          | string                                                                      | -         |          |\n| labelTextDecorationLine  | Combo label text decoration line                                                                                                                                           | string                                                                      | -         |          |\n| labelTextDecorationStyle | Combo label text decoration style                                                                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Combo label text overflow handling                                                                                                                                         | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Combo label text path                                                                                                                                                      | Path                                                                        | -         |          |\n| labelWordWrap            | Whether combo label enables auto line wrapping. When labelWordWrap is enabled, parts exceeding labelMaxWidth automatically wrap                                            | boolean                                                                     | false     |          |\n| labelZIndex              | Combo label rendering layer                                                                                                                                                | number                                                                      | 0         |          |\n| `label{StyleProps}`      | More label style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) property values. For example, labelOpacity represents label opacity | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |          |\n\n#### LabelPlacement\n\nLabel position relative to combo main graphic, available values:\n\n- `center`: Label at combo center\n- `top`, `bottom`, `left`, `right`: Label at top, bottom, left, right of combo\n- `top-left`, `top-right`, `bottom-left`, `bottom-right`: Label at four corners of combo\n- `left-top`, `left-bottom`, `right-top`, `right-bottom`: Label at edge endpoints of combo\n\n#### LabelMaxWidth\n\nWhen auto line wrapping `labelWordWrap` is enabled, text wraps when exceeding this width:\n\n- string: Defines maximum width as percentage relative to combo element width. For example, `50%` means label width doesn't exceed half of combo width\n- number: Defines maximum width in pixels. For example, 100 means label maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background provides background decoration for label text, improving label readability and visual effects.\n\n#### Basic Background Style\n\nAdd simple background to label:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Important Combo',\n      labelFill: '#fff', // White text\n      labelBackground: true, // Enable background\n      labelBackgroundFill: '#1783FF', // Blue background\n      labelBackgroundPadding: [4, 8], // Padding: vertical 4px, horizontal 8px\n      labelBackgroundRadius: 4, // Border radius\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Gradient Background Effect\n\nCreate label background with gradient effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP Combo',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // Gradient background\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // Large border radius\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Stroke-only Background Style\n\nCreate label background with stroke only:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Border Label',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // Transparent background\n      labelBackgroundStroke: '#1783FF', // Blue stroke\n      labelBackgroundLineWidth: 2, // Stroke width\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label background style configurations:\n\n| Property                      | Description                                                                                                                                                                                                | Type                                                         | Default      |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | Whether to show combo label background                                                                                                                                                                     | boolean                                                      | false        |\n| labelBackgroundCursor         | Combo label background cursor style, [options](#cursor)                                                                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | Combo label background fill color                                                                                                                                                                          | string                                                       | #000         |\n| labelBackgroundFillOpacity    | Combo label background opacity                                                                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | Combo label background height                                                                                                                                                                              | string \\| number                                             | -            |\n| labelBackgroundLineDash       | Combo label background dash configuration                                                                                                                                                                  | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | Combo label background dash offset                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | Combo label background stroke line width                                                                                                                                                                   | number                                                       | -            |\n| labelBackgroundPadding        | Combo label background padding                                                                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | Combo label background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values auto-filled                                    | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | Combo label background shadow blur                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundShadowColor    | Combo label background shadow color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | Combo label background shadow X offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | Combo label background shadow Y offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundStroke         | Combo label background stroke color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | Combo label background stroke opacity                                                                                                                                                                      | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | Whether combo label background is visible                                                                                                                                                                  | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | Combo label background rendering layer                                                                                                                                                                     | number                                                       | 1            |\n| `labelBackground{StyleProps}` | More label background style configurations, refer to [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) property values. For example, labelBackgroundOpacity represents label background opacity | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### Badge Style\n\nBadges are small markers displayed on combos, usually used to show status, quantity, or other auxiliary information. Multiple badges can be displayed simultaneously with customizable positions.\n\n#### Single Badge\n\nAdd a simple badge to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Display at top by default\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdd multiple badges at different positions to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // Whether to show badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nFully customize badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete badge style configurations:\n\n| Property     | Description                    | Type                                  | Default                           |\n| ------------ | ------------------------------ | ------------------------------------- | --------------------------------- |\n| badge        | Whether to show combo badge    | boolean                               | true                              |\n| badgePalette | Combo badge background palette | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Combo badge settings           | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                            | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether to show combo badge background                                                                                                                                                                                                                                                                 | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Combo badge background cursor style, [options](#cursor)                                                                                                                                                                                                                                                | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Combo badge background fill color. If not specified, consider badgePalette for sequential allocation                                                                                                                                                                                                   | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Combo badge background fill opacity                                                                                                                                                                                                                                                                    | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Combo badge background filter                                                                                                                                                                                                                                                                          | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Combo badge background height                                                                                                                                                                                                                                                                          | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Combo badge background dash configuration                                                                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Combo badge background dash offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Combo badge background stroke line width                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Combo badge background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values will be filled <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, space-separated | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Combo badge background shadow blur                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Combo badge background shadow color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Combo badge background shadow X offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Combo badge background shadow Y offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Combo badge background stroke color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Combo badge background stroke opacity                                                                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether combo badge background is visible                                                                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | Combo badge text color                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                 | -            |\n| fontFamily               | Combo badge font family                                                                                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| fontSize                 | Combo badge font size                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | Combo badge font style                                                                                                                                                                                                                                                                                 | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Combo badge font variant                                                                                                                                                                                                                                                                               | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Combo badge font weight                                                                                                                                                                                                                                                                                | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Combo badge line height                                                                                                                                                                                                                                                                                | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Combo badge line width                                                                                                                                                                                                                                                                                 | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Combo badge text maximum lines                                                                                                                                                                                                                                                                         | number                                                                                                                                                                 | 1            |\n| offsetX                  | Combo badge X offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| offsetY                  | Combo badge Y offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| padding                  | Combo badge padding                                                                                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Combo badge position relative to combo main graphic. If not specified, defaults to clockwise placement starting from top-right                                                                                                                                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Combo badge text content                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textAlign                | Combo badge text horizontal alignment                                                                                                                                                                                                                                                                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Combo badge text baseline                                                                                                                                                                                                                                                                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Combo badge text decoration color                                                                                                                                                                                                                                                                      | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Combo badge text decoration line                                                                                                                                                                                                                                                                       | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Combo badge text decoration style                                                                                                                                                                                                                                                                      | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Combo badge text overflow handling                                                                                                                                                                                                                                                                     | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether combo badge is visible                                                                                                                                                                                                                                                                         | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether combo badge text auto-wraps                                                                                                                                                                                                                                                                    | boolean                                                                                                                                                                | -            |\n| zIndex                   | Combo badge rendering layer                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | 3            |\n\n### Halo Style\n\nHalo effect is used to highlight combos, usually used in mouse hover, selected, or active states, adding glow effect around combos.\n\n#### Basic Halo Effect\n\nAdd simple halo effect to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // Enable halo\n      haloStroke: '#1783FF', // Blue halo\n      haloLineWidth: 8, // Halo width\n      haloStrokeOpacity: 0.3, // Halo opacity\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Halo Effect\n\nCreate colorful gradient halo effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // Red halo\n      haloLineWidth: 12, // Thicker halo\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // Blur filter effect\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dynamic Halo Effect\n\nUse halo effect in state transitions:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // No halo in default state\n      halo: false,\n    },\n    state: {\n      // Show orange halo in hover state\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // Show green halo in selected state\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete halo style configurations:\n\n| Property           | Description                                                                                                                                                                       | Type                                                                  | Default                         | Required |\n| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------- | -------- |\n| halo               | Whether to show combo halo                                                                                                                                                        | boolean                                                               | false                           |          |\n| haloCursor         | Combo halo cursor style, [options](#cursor)                                                                                                                                       | string                                                                | `default`                       |          |\n| haloDraggable      | Whether combo halo allows dragging                                                                                                                                                | boolean                                                               | true                            |          |\n| haloDroppable      | Whether combo halo allows receiving dragged elements                                                                                                                              | boolean                                                               | false                           |          |\n| haloFill           | Halo fill color                                                                                                                                                                   | string                                                                | Same as main graphic fill color |          |\n| haloFillRule       | Combo halo fill rule                                                                                                                                                              | `nonzero` \\| `evenodd`                                                | -                               |          |\n| haloFilter         | Combo halo filter effect, such as 'blur(2px)' for blur effect                                                                                                                     | string                                                                | -                               |          |\n| haloLineWidth      | Combo halo stroke width, controls halo thickness                                                                                                                                  | number                                                                | 12                              |          |\n| haloPointerEvents  | Whether combo halo effect responds to pointer events, [options](#pointerevents)                                                                                                   | string                                                                | `none`                          |          |\n| haloStroke         | Combo halo stroke color, **this property is used to set the color of halo around combo, helping to highlight the combo**                                                          | string                                                                | `#99add1`                       |          |\n| haloStrokeOpacity  | Combo halo stroke opacity, recommended to use 0.2-0.6 values for natural halo effect                                                                                              | number                                                                | 0.25                            |          |\n| haloVisibility     | Combo halo visibility                                                                                                                                                             | `visible` \\| `hidden`                                                 | `visible`                       |          |\n| haloZIndex         | Combo halo rendering layer, usually set to negative value to ensure halo is below combo main graphic                                                                              | number                                                                | -1                              |          |\n| `halo{StyleProps}` | More halo style configurations, refer to [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) options. For example, haloFillOpacity represents halo fill opacity | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                               |          |\n\n**Halo Usage Recommendations:**\n\n1. **Performance Consideration**: Halo effects increase rendering burden, recommend enabling only when necessary\n2. **Color Matching**: Halo color should coordinate with combo main color tone, avoid being too abrupt\n3. **Opacity Setting**: Reasonable opacity (0.2-0.6) can create natural halo effect\n4. **State Application**: Halo is usually used for hover, selected, active and other interactive states\n\n### Icon Style\n\nIcons are used to display text or image content in combos, usually located at the center of the combo, can be used to represent combo type or function.\n\n#### Text Icon\n\nUse text as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // Display letter A\n      iconFill: '#1783FF', // Blue text\n      iconFontSize: 24, // Large font\n      iconFontWeight: 'bold', // Bold\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Image Icon\n\nUse image as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Text Icon\n\nCreate text icon with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'Dept',\n      iconFill: '#FF4D4F', // Red text\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // Italic\n      iconTextDecorationLine: 'underline', // Underline\n      iconLetterSpacing: 1, // Letter spacing\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete icon style configurations:\n\n| Property                | Description                                                                                                               | Type                                                                        | Default                     |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to show combo icon                                                                                                | boolean                                                                     | true                        |\n| iconCursor              | Combo icon cursor style, [options](#cursor)                                                                               | string                                                                      | `default`                   |\n| iconFill                | Combo icon text color                                                                                                     | string                                                                      | -                           |\n| iconFillOpacity         | Combo icon text color opacity                                                                                             | number                                                                      | 1                           |\n| iconFontFamily          | Combo icon font family                                                                                                    | string                                                                      | -                           |\n| iconFontSize            | Combo icon font size                                                                                                      | number                                                                      | 16                          |\n| iconFontStyle           | Combo icon font style                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Combo icon font variant                                                                                                   | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Combo icon font weight                                                                                                    | number \\| string                                                            | `normal`                    |\n| iconHeight              | Combo icon height, used to control image size when using image icon                                                       | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Combo icon text letter spacing                                                                                            | number \\| string                                                            | -                           |\n| iconLineHeight          | Combo icon text line height                                                                                               | number \\| string                                                            | -                           |\n| iconMaxLines            | Combo icon text maximum lines                                                                                             | number                                                                      | 1                           |\n| iconOffsetX             | Combo icon X offset                                                                                                       | number                                                                      | 0                           |\n| iconOffsetY             | Combo icon Y offset                                                                                                       | number                                                                      | 0                           |\n| iconOpacity             | Combo icon opacity                                                                                                        | number                                                                      | 1                           |\n| iconRadius              | Combo icon border radius (only effective for rectangular icons)                                                           | number                                                                      | 0                           |\n| iconSrc                 | Combo image source. Has higher priority than iconText, supports local and network images                                  | string                                                                      | -                           |\n| iconText                | Combo icon text content, supports text, Unicode characters, etc.                                                          | string                                                                      | -                           |\n| iconTextAlign           | Combo icon text horizontal alignment                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`                    |\n| iconTextBaseline        | Combo icon text baseline                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`                    |\n| iconTextDecorationColor | Combo icon text decoration color                                                                                          | string                                                                      | -                           |\n| iconTextDecorationLine  | Combo icon text decoration line, such as underline, strikethrough, etc.                                                   | string                                                                      | -                           |\n| iconTextDecorationStyle | Combo icon text decoration style                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Combo icon text overflow handling                                                                                         | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconVisibility          | Whether combo icon is visible                                                                                             | `visible` \\| `hidden`                                                       | `visible`                   |\n| iconWidth               | Combo icon width, used to control image size when using image icon                                                        | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether combo icon text auto-wraps                                                                                        | boolean                                                                     | false                       |\n| iconZIndex              | Combo icon rendering layer                                                                                                | number                                                                      | 1                           |\n| `icon{StyleProps}`      | More icon style configurations, refer to specific icon type options. For example, iconStroke represents icon stroke color | -                                                                           | -                           |\n\n**Icon Usage Recommendations:**\n\n1. **Priority**: `iconSrc` (image) has higher priority than `iconText` (text), if both are set, image will be displayed first\n2. **Size Control**: Recommend setting icon size reasonably according to combo size, avoid icons being too large or small affecting visual effect\n3. **Performance Optimization**: Text icons have better performance, image icons require additional network requests and rendering overhead\n4. **Style Consistency**: Icon styles in the same graph should be consistent to improve overall visual effect\n5. **Accessibility**: Ensure icon color has sufficient contrast with background for easy user identification\n\n## State\n\nIn some interactive behaviors, such as clicking to select a combo or hovering to activate an edge, it is merely marking certain states on the element. To reflect these states in the visual space seen by the end user, we need to set different graphic element styles for different states to respond to changes in the element's state.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the default styles of the element.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\nFor example, when the combo is in the `focus` state, you can add a stroke with a width of 3 and a color of orange.\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n**⚠️ Dynamic Configuration**: State configuration also supports dynamic configuration, which can be used to set styles dynamically based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    state: {\n      // Static configuration\n      selected: {\n        stroke: '#1783FF',\n        lineWidth: 2,\n      },\n\n      // Dynamic configuration - arrow function form\n      hover: (datum) => ({\n        fill: datum.data.isVIP ? '#FFD700' : '#1783FF',\n        fillOpacity: 0.3,\n      }),\n\n      // Dynamic configuration - regular function form (access to graph instance)\n      active: function (datum) {\n        console.log(this); // graph instance\n        return {\n          stroke: datum.data.level > 3 ? '#FF4D4F' : '#52C41A',\n          lineWidth: 3,\n        };\n      },\n    },\n  },\n});\n```\n\n**⚠️ State Priority**: When a combo has multiple states simultaneously, the style merge follows the following priority (high to low):\n\n1. Later defined states override earlier defined states\n2. More specific selectors have higher priority\n3. Dynamic configuration has higher priority than static configuration\n\nFor example, if a combo has both `selected` and `hover` states, and `hover` is defined after `selected`, then `hover` state styles will override `selected` state styles.\n\n## Animation\n\nDefines the animation effects for combos, supporting the following two configuration methods:\n\n1. Disable all combo animations\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when combos enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when combo enters the canvas\n- `update`: Animation when combo updates\n- `exit`: Animation when combo leaves the canvas\n- `show`: Animation when combo shows from hidden state\n- `hide`: Animation when combo hides\n- `collapse`: Animation when combo collapses\n- `expand`: Animation when combo expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure combos, such as:\n\n#### Enter Animation\n\nConfigure animation when combo enters the canvas:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    animation: {\n      enter: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          from: 0, // Start from 0\n          to: 1, // End at 1\n          duration: 1000, // Animation duration\n          easing: 'ease-out', // Easing function\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Update Animation\n\nConfigure animation when combo updates:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      update: [\n        {\n          fields: ['x', 'y'], // Only animate x and y properties during update\n          duration: 1000, // Animation duration\n          easing: 'linear', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Exit Animation\n\nConfigure animation when combo leaves the canvas:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      exit: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          to: 0, // End at 0\n          duration: 500, // Animation duration\n          easing: 'ease-in', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Show/Hide Animation\n\nConfigure animation when combo shows/hides:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      show: [\n        {\n          fields: ['opacity'],\n          from: 0,\n          to: 1,\n          duration: 300,\n        },\n      ],\n      hide: [\n        {\n          fields: ['opacity'],\n          to: 0,\n          duration: 300,\n        },\n      ],\n    },\n  },\n});\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass `false` to disable specific stage animations:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // Disable combo enter animation\n    }\n  }\n}\n```\n\n**Animation Configuration Options:**\n\n| Property  | Description                             | Type                                                        | Default  |\n| --------- | --------------------------------------- | ----------------------------------------------------------- | -------- |\n| fields    | Properties to animate                   | string[]                                                    | -        |\n| from      | Starting value                          | number \\| string                                            | -        |\n| to        | Ending value                            | number \\| string                                            | -        |\n| duration  | Animation duration (milliseconds)       | number                                                      | 1000     |\n| easing    | Easing function                         | string                                                      | 'ease'   |\n| delay     | Animation delay (milliseconds)          | number                                                      | 0        |\n| repeat    | Number of repetitions (-1 for infinite) | number                                                      | 0        |\n| direction | Animation direction                     | 'normal' \\| 'reverse' \\| 'alternate' \\| 'alternate-reverse' | 'normal' |\n\n## Palette\n\nDefines combo color palette, i.e., predefined combo color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For palette definition, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                          | Type                              | Default |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |\n| type     | Specifies current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                  | `group` &#124; `value`            | `group` |\n| field    | Specifies grouping field in element data. If not specified, defaults to id as grouping field                         | string &#124; ((datum) => string) | `id`    |\n| color    | Palette colors. If palette is registered, you can directly specify its registration name, also accepts a color array | string &#124; string[]            | -       |\n| invert   | Whether to invert the palette                                                                                        | boolean                           | false   |\n\nFor example, assign combo colors to a group of data by `category` field, so that combos of the same category have the same color:\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau is palette name, defaults to assign colors by ID\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/combo/BaseCombo.zh.md":"---\ntitle: 组合通用配置项\norder: 1\n---\n\n本文介绍内置组合通用属性配置。\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {}, // 组合样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](#type)           | `circle` |      |\n| style     | 组合样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定组合类型，内置组合类型名称或自定义组合的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据组合数据动态选择组合类型：\n\n```js\nconst graph = new Graph({\n  combo: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形组合](/manual/element/combo/circle)\n- `rect`：[矩形组合](/manual/element/combo/rect)\n\n## Style\n\n定义组合的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据组合数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `组合: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为组合数据对象 (`ComboData`)，包含组合的所有数据信息。\n\n一个完整的组合由以下几部分构成：\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：组合的主图形，表示组合的主要形状，例如圆形、矩形等；\n- `label` ：文本标签，通常用于展示组合的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `badge` ：默认位于组合右上角的徽标；\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是组合的核心部分，定义了组合的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置组合的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为组合添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的组合：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前组合是否折叠                                                                          | boolean                       | false     |      |\n| cursor                          | 组合鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 组合填充色                                                                                | string                        | `#99ADD1` |      |\n| fillOpacity                     | 组合填充色透明度                                                                          | number \\| string              | 0.04      |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 组合描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 组合描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 组合描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 组合描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 组合描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 组合透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 组合如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 组合阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 组合阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 组合阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 组合阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 组合阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 组合大小，快捷设置组合宽高，[配置项](#size)                                               | number \\| number[]            | -         |      |\n| stroke                          | 组合描边色                                                                                | string                        | `#99ADD1` |      |\n| strokeOpacity                   | 组合描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定组合                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 组合是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 组合 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 组合 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 组合 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 组合渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n组合大小，快捷设置组合宽高，支持三种配置方式：\n\n- number：表示组合宽高相同为指定值\n- [number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度\n- [number, number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // 组合不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 收起时样式\n\n当组合处于收起状态时（`collapsed` 为 `true`），可以为其配置特殊的样式。收起时的样式属性以 `collapsed` 为前缀。\n\n#### 基础收起样式\n\n为收起状态的组合设置不同的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedFill: '#1783FF',\n      collapsedStroke: '#000',\n      collapsedLineWidth: 2,\n      collapsedSize: 40,\n      collapsedMarkerFill: '#fff',\n      collapsedMarkerFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时样式的完整配置：\n\n| 属性                                     | 描述                                                                                                  | 类型                          | 默认值                             | 必选 |\n| ---------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------------------------- | ---- |\n| collapsedCursor                          | 组合收起时的鼠标移入样式，[配置项](#cursor)                                                           | string                        | 默认与展开时的 cursor 一致         |      |\n| collapsedFill                            | 组合收起时的填充色                                                                                    | string                        | 默认与展开时的 fill 一致           |      |\n| collapsedFillOpacity                     | 组合收起时的填充色透明度                                                                              | number \\| string              | 1                                  |      |\n| collapsedIncreasedLineWidthForHitTesting | 组合收起时，当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0                                  |      |\n| collapsedLineCap                         | 组合收起时的描边端点样式                                                                              | `round` \\| `square` \\| `butt` | 默认与展开时的 lineCap 一致        |      |\n| collapsedLineDash                        | 组合收起时的描边虚线样式                                                                              | number[]                      | 默认与展开时的 lineDash 一致       |      |\n| collapsedLineDashOffset                  | 组合收起时的描边虚线偏移量                                                                            | number                        | 默认与展开时的 lineDashOffset 一致 |      |\n| collapsedLineJoin                        | 组合收起时的描边连接处样式                                                                            | `round` \\| `bevel` \\| `miter` | 默认与展开时的 lineJoin 一致       |      |\n| collapsedLineWidth                       | 组合收起时的描边宽度                                                                                  | number                        | 默认与展开时的 lineWidth 一致      |      |\n| collapsedMarker                          | 组合收起时是否显示标记，[配置项](#收起时标记样式)                                                     | boolean                       | true                               |      |\n| collapsedOpacity                         | 组合收起时的透明度                                                                                    | number \\| string              | 默认与展开时的 opacity 一致        |      |\n| collapsedShadowBlur                      | 组合收起时的阴影模糊度                                                                                | number                        | 默认与展开时的 shadowBlur 一致     |      |\n| collapsedShadowColor                     | 组合收起时的阴影颜色                                                                                  | string                        | 默认与展开时的 shadowColor 一致    |      |\n| collapsedShadowOffsetX                   | 组合收起时的阴影在 x 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetX 一致  |      |\n| collapsedShadowOffsetY                   | 组合收起时的阴影在 y 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetY 一致  |      |\n| collapsedShadowType                      | 组合收起时的阴影类型                                                                                  | `inner` \\| `outer`            | 默认与展开时的 shadowType 一致     |      |\n| collapsedSize                            | 组合收起时的大小                                                                                      | number \\| [number, number]    | 32                                 |      |\n| collapsedStroke                          | 组合收起时的描边色                                                                                    | string                        | 默认与展开时的 stroke 一致         |      |\n| collapsedStrokeOpacity                   | 组合收起时的描边色透明度                                                                              | number \\| string              | 默认与展开时的 strokeOpacity 一致  |      |\n| collapsedVisibility                      | 组合收起时是否可见                                                                                    | `visible` \\| `hidden`         | 默认与展开时的 visibility 一致     |      |\n\n### 收起时标记样式\n\n当 `collapsedMarker` 为 `true` 时显示的标记，用于显示收起组合内包含的元素数量。\n\n#### 自定义标记内容\n\n可以自定义收起标记显示的内容：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n      { id: 'node3', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerType: 'child-count',\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 14,\n      collapsedMarkerFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时标记样式的完整配置：\n\n| 属性                        | 描述                                                                                                                                                                                                                                                          | 类型                                                                                                   | 默认值        | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | ---- |\n| collapsedMarkerType         | 组合收起时显示的标记类型 <br> - `'child-count'`: 子元素数量（包括 Node 和 Combo）<br>- `'descendant-count'`: 后代元素数量（包括 Node 和 Combo）<br>- `'node-count'`: 后代元素数量（只包括 Node）<br> - `(children: NodeLikeData[]) => string`: 自定义处理逻辑 | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string) | `child-count` |      |\n| collapsedMarkerFill         | 标记文字颜色                                                                                                                                                                                                                                                  | string                                                                                                 | #fff          |      |\n| collapsedMarkerFillOpacity  | 标记文字颜色透明度                                                                                                                                                                                                                                            | number                                                                                                 | 1             |      |\n| collapsedMarkerFontSize     | 标记字体大小                                                                                                                                                                                                                                                  | number                                                                                                 | 12            |      |\n| collapsedMarkerFontWeight   | 标记字体粗细                                                                                                                                                                                                                                                  | number \\| string                                                                                       | `normal`      |      |\n| collapsedMarkerRadius       | 标记圆角半径                                                                                                                                                                                                                                                  | number                                                                                                 | 0             |      |\n| collapsedMarkerSrc          | 图片来源。其优先级高于 `collapsedMarkerText`                                                                                                                                                                                                                  | string                                                                                                 | -             |      |\n| collapsedMarkerText         | 标记文字                                                                                                                                                                                                                                                      | string                                                                                                 | -             |      |\n| collapsedMarkerTextAlign    | 标记文字水平对齐方式                                                                                                                                                                                                                                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                                                      | `center`      |      |\n| collapsedMarkerTextBaseline | 标记文字对齐基线                                                                                                                                                                                                                                              | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top`                            | `middle`      |      |\n| collapsedMarkerWidth        | 标记宽度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerHeight       | 标记高度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerZIndex       | 标记层级                                                                                                                                                                                                                                                      | number                                                                                                 | 1             |      |\n\n### 徽标样式\n\n徽标是组合上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为组合添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为组合添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 组合是否显示徽标   | boolean                               | true                              |\n| badgePalette | 组合徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 组合徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 组合徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 组合徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 组合徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 组合徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 组合徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 组合徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 组合徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 组合徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 组合徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 组合徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 组合徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 组合徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 组合徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 组合徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 组合徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 组合徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 组合徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | 组合徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 组合徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 组合徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 组合徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 组合徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 组合徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 组合徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 组合徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 组合徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 组合徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 组合徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 组合徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 组合徽标相对于组合主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 组合徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 组合徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 组合徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 组合徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 组合徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 组合徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 组合徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 组合徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 组合徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 组合徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 标签样式\n\n标签用于显示组合的文本信息，支持丰富的文本样式配置和灵活的位置布局。\n\n#### 基础标签配置\n\n为组合添加基本的文本标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '销售部门', // 标签文字内容\n      labelFill: '#1A1A1A', // 标签文字颜色\n      labelFontSize: 14, // 标签字体大小\n      labelPlacement: 'bottom', // 标签位置：底部\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n配置支持多行显示的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '这是一个支持多行显示的组合标签文本内容',\n      labelWordWrap: true, // 开启文本换行\n      labelMaxWidth: 100, // 最大宽度 100px\n      labelMaxLines: 3, // 最多显示 3 行\n      labelTextAlign: 'center', // 文本居中对齐\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义样式标签\n\n创建具有特殊样式的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // 红色文字\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // 粗体\n      labelFontStyle: 'italic', // 斜体\n      labelTextDecorationLine: 'underline', // 下划线\n      labelLetterSpacing: 2, // 字间距\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                                                                         | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示组合标签                                                                                                             | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入组合标签时显示的样式，[配置项](#cursor)                                                                              | string                                                                      | `default` |      |\n| labelFill                | 组合标签文字颜色                                                                                                             | string                                                                      | #000      |      |\n| labelFillOpacity         | 组合标签文字颜色的透明度                                                                                                     | number                                                                      | 1         |      |\n| labelFontFamily          | 组合标签字体族                                                                                                               | string                                                                      | -         |      |\n| labelFontSize            | 组合标签字体大小                                                                                                             | number                                                                      | 12        |      |\n| labelFontStyle           | 组合标签字体样式                                                                                                             | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 组合标签字体变种                                                                                                             | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 组合标签字体粗细                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |      |\n| labelLeading             | 行间距                                                                                                                       | number                                                                      | 0         |      |\n| labelLetterSpacing       | 组合标签字间距                                                                                                               | number \\| string                                                            | -         |      |\n| labelLineHeight          | 组合标签行高                                                                                                                 | number \\| string                                                            | -         |      |\n| labelMaxLines            | 组合标签最大行数                                                                                                             | number                                                                      | 1         |      |\n| labelMaxWidth            | 组合标签最大宽度，[配置项](#labelmaxwidth)                                                                                   | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 组合标签在 x 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelOffsetY             | 组合标签在 y 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelPadding             | 组合标签内边距                                                                                                               | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 组合标签相对于组合主图形的位置，[配置项](#labelplacement)                                                                    | string                                                                      | `bottom`  |      |\n| labelText                | 组合标签文字内容                                                                                                             | string                                                                      | -         |      |\n| labelTextAlign           | 组合标签文本水平对齐方式                                                                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 组合标签文本基线                                                                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 组合标签文本装饰线颜色                                                                                                       | string                                                                      | -         |      |\n| labelTextDecorationLine  | 组合标签文本装饰线                                                                                                           | string                                                                      | -         |      |\n| labelTextDecorationStyle | 组合标签文本装饰线样式                                                                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 组合标签文本溢出处理方式                                                                                                     | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 组合标签文本路径                                                                                                             | Path                                                                        | -         |      |\n| labelWordWrap            | 组合标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行                                           | boolean                                                                     | false     |      |\n| labelZIndex              | 组合标签渲染层级                                                                                                             | number                                                                      | 0         |      |\n| `label{StyleProps}`      | 更多标签样式配置，参考 [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) 属性值。比如 labelOpacity 代表标签透明度 | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |      |\n\n#### LabelPlacement\n\n标签相对于组合主图形的位置，可选值有：\n\n- `center`：标签位于组合中心\n- `top`、`bottom`、`left`、`right`：标签位于组合的上、下、左、右方\n- `top-left`、`top-right`、`bottom-left`、`bottom-right`：标签位于组合的四个角\n- `left-top`、`left-bottom`、`right-top`、`right-bottom`：标签位于组合边的端点\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于组合元素宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过组合宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景为标签文字提供背景装饰，可以提升标签的可读性和视觉效果。\n\n#### 基础背景样式\n\n为标签添加简单的背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '重要组合',\n      labelFill: '#fff', // 白色文字\n      labelBackground: true, // 启用背景\n      labelBackgroundFill: '#1783FF', // 蓝色背景\n      labelBackgroundPadding: [4, 8], // 内边距：垂直4px，水平8px\n      labelBackgroundRadius: 4, // 圆角半径\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 渐变背景效果\n\n创建带渐变效果的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP组合',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // 渐变背景\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // 大圆角\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 描边背景样式\n\n创建只有描边的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '边框标签',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // 透明背景\n      labelBackgroundStroke: '#1783FF', // 蓝色描边\n      labelBackgroundLineWidth: 2, // 描边宽度\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签背景样式配置：\n\n| 属性                          | 描述                                                                                                                                           | 类型                                                         | 默认值       |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | 组合标签背景是否显示                                                                                                                           | boolean                                                      | false        |\n| labelBackgroundCursor         | 组合标签背景鼠标移入样式，[配置项](#cursor)                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | 组合标签背景填充色                                                                                                                             | string                                                       | #000         |\n| labelBackgroundFillOpacity    | 组合标签背景透明度                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | 组合标签背景高度                                                                                                                               | string \\| number                                             | -            |\n| labelBackgroundLineDash       | 组合标签背景虚线配置                                                                                                                           | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | 组合标签背景虚线偏移量                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | 组合标签背景描边线宽                                                                                                                           | number                                                       | -            |\n| labelBackgroundPadding        | 组合标签背景内间距                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | 组合标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充                                 | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | 组合标签背景阴影模糊程度                                                                                                                       | number                                                       | -            |\n| labelBackgroundShadowColor    | 组合标签背景阴影颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | 组合标签背景阴影 X 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | 组合标签背景阴影 Y 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundStroke         | 组合标签背景描边颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | 组合标签背景描边透明度                                                                                                                         | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | 组合标签背景是否可见                                                                                                                           | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | 组合标签背景渲染层级                                                                                                                           | number                                                       | 1            |\n| `labelBackground{StyleProps}` | 更多标签背景样式配置，参考 [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) 属性值。例如 labelBackgroundOpacity 代表标签背景透明度 | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### 光晕样式\n\n光晕效果用于突出显示组合，通常在鼠标悬停、选中或激活状态下使用，为组合周围添加发光效果。\n\n#### 基础光晕效果\n\n为组合添加简单的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // 启用光晕\n      haloStroke: '#1783FF', // 蓝色光晕\n      haloLineWidth: 8, // 光晕宽度\n      haloStrokeOpacity: 0.3, // 光晕透明度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色光晕效果\n\n创建彩色渐变的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // 红色光晕\n      haloLineWidth: 12, // 较粗的光晕\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // 模糊滤镜效果\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 动态光晕效果\n\n在状态切换时使用光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // 默认状态下不显示光晕\n      halo: false,\n    },\n    state: {\n      // 悬停状态显示橙色光晕\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // 选中状态显示绿色光晕\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性               | 描述                                                                                                                                           | 类型                                                                  | 默认值                       | 必选 |\n| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------- | ---- |\n| halo               | 是否显示组合光晕                                                                                                                               | boolean                                                               | false                        |      |\n| haloCursor         | 组合光晕鼠标移入样式，[配置项](#cursor)                                                                                                        | string                                                                | `default`                    |      |\n| haloDraggable      | 组合光晕是否允许拖拽                                                                                                                           | boolean                                                               | true                         |      |\n| haloDroppable      | 组合光晕是否允许接收被拖拽的元素                                                                                                               | boolean                                                               | false                        |      |\n| haloFill           | 光晕填充色                                                                                                                                     | string                                                                | 与主图形的填充色 `fill` 一致 |      |\n| haloFillRule       | 组合光晕填充规则                                                                                                                               | `nonzero` \\| `evenodd`                                                | -                            |      |\n| haloFilter         | 组合光晕滤镜效果，如 'blur(2px)' 可创建模糊效果                                                                                                | string                                                                | -                            |      |\n| haloLineWidth      | 组合光晕描边宽度，控制光晕的粗细程度                                                                                                           | number                                                                | 12                           |      |\n| haloPointerEvents  | 组合光晕效果是否响应指针事件，[配置项](#pointerevents)                                                                                         | string                                                                | `none`                       |      |\n| haloStroke         | 组合光晕描边色，**此属性用于设置组合周围光晕的颜色，帮助突出显示组合**                                                                         | string                                                                | `#99add1`                    |      |\n| haloStrokeOpacity  | 组合光晕描边色透明度，建议使用 0.2-0.6 的值以获得自然的光晕效果                                                                                | number                                                                | 0.25                         |      |\n| haloVisibility     | 组合光晕可见性                                                                                                                                 | `visible` \\| `hidden`                                                 | `visible`                    |      |\n| haloZIndex         | 组合光晕渲染层级，通常设置为负值以确保光晕在组合主图形下方                                                                                     | number                                                                | -1                           |      |\n| `halo{StyleProps}` | 更多光晕样式配置，参考 [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) 配置项。例如 haloFillOpacity 代表光晕填充色透明度 | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                            |      |\n\n**光晕使用建议：**\n\n1. **性能考虑**：光晕效果会增加渲染负担，建议在必要时才启用\n2. **颜色搭配**：光晕颜色应与组合主色调协调，避免过于突兀\n3. **透明度设置**：合理的透明度（0.2-0.6）可以创造自然的光晕效果\n4. **状态应用**：光晕通常用于 hover、selected、active 等交互状态\n\n### 图标样式\n\n图标用于在组合中显示文字或图片内容，通常位于组合的中心位置，可以用来表示组合的类型或功能。\n\n#### 文字图标\n\n使用文字作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // 显示字母 A\n      iconFill: '#1783FF', // 蓝色文字\n      iconFontSize: 24, // 大字体\n      iconFontWeight: 'bold', // 粗体\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 图片图标\n\n使用图片作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色文字图标\n\n创建带有特殊样式的文字图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: '部门',\n      iconFill: '#FF4D4F', // 红色文字\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // 斜体\n      iconTextDecorationLine: 'underline', // 下划线\n      iconLetterSpacing: 1, // 字间距\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                                                         | 类型                                                                        | 默认值           |\n| ----------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示组合图标                                                             | boolean                                                                     | true             |\n| iconCursor              | 组合图标鼠标移入样式，[配置项](#cursor)                                      | string                                                                      | `default`        |\n| iconFill                | 组合图标文字颜色                                                             | string                                                                      | -                |\n| iconFillOpacity         | 组合图标文字颜色透明度                                                       | number                                                                      | 1                |\n| iconFontFamily          | 组合图标字体族                                                               | string                                                                      | -                |\n| iconFontSize            | 组合图标字体大小                                                             | number                                                                      | 16               |\n| iconFontStyle           | 组合图标字体样式                                                             | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 组合图标字体变种                                                             | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 组合图标字体粗细                                                             | number \\| string                                                            | `normal`         |\n| iconHeight              | 组合图标高度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 组合图标文本字间距                                                           | number \\| string                                                            | -                |\n| iconLineHeight          | 组合图标文本行高                                                             | number \\| string                                                            | -                |\n| iconMaxLines            | 组合图标文本最大行数                                                         | number                                                                      | 1                |\n| iconOffsetX             | 组合图标在 x 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOffsetY             | 组合图标在 y 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOpacity             | 组合图标透明度                                                               | number                                                                      | 1                |\n| iconRadius              | 组合图标圆角半径（仅对矩形图标有效）                                         | number                                                                      | 0                |\n| iconSrc                 | 组合图片来源。其优先级高于 iconText，支持本地图片和网络图片                  | string                                                                      | -                |\n| iconText                | 组合图标文字内容，支持文字、Unicode 字符等                                   | string                                                                      | -                |\n| iconTextAlign           | 组合图标文本水平对齐方式                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`         |\n| iconTextBaseline        | 组合图标文本基线                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`         |\n| iconTextDecorationColor | 组合图标文本装饰线颜色                                                       | string                                                                      | -                |\n| iconTextDecorationLine  | 组合图标文本装饰线，如下划线、删除线等                                       | string                                                                      | -                |\n| iconTextDecorationStyle | 组合图标文本装饰线样式                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 组合图标文本溢出处理方式                                                     | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconVisibility          | 组合图标是否可见                                                             | `visible` \\| `hidden`                                                       | `visible`        |\n| iconWidth               | 组合图标宽度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 组合图标文本是否自动换行                                                     | boolean                                                                     | false            |\n| iconZIndex              | 组合图标渲染层级                                                             | number                                                                      | 1                |\n| `icon{StyleProps}`      | 更多图标样式配置，参考图标的具体类型配置项。例如 iconStroke 代表图标描边颜色 | -                                                                           | -                |\n\n**图标使用建议：**\n\n1. **优先级**：`iconSrc`（图片）的优先级高于 `iconText`（文字），如果同时设置，会优先显示图片\n2. **尺寸控制**：建议根据组合大小合理设置图标尺寸，避免图标过大或过小影响视觉效果\n3. **性能优化**：使用文字图标性能更好，图片图标需要额外的网络请求和渲染开销\n4. **样式一致性**：在同一个图中的组合图标样式应保持一致，提升整体视觉效果\n5. **可访问性**：确保图标颜色与背景有足够的对比度，便于用户识别\n\n## State\n\n在一些交互行为中，比如点击选中一个组合或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\n例如，当组合处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义组合的动画效果，支持下列两种配置方式：\n\n1. 关闭组合全部动画\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指组合在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 组合进入画布时的动画\n- `update`: 组合更新时的动画\n- `exit`: 组合离开画布时的动画\n- `show`: 组合从隐藏状态显示时的动画\n- `hide`: 组合隐藏时的动画\n- `collapse`: 组合收起时的动画\n- `expand`: 组合展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置组合，如：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // 关闭组合入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义组合的色板，即预定义组合颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                              | 默认值  |\n| ------ | ------------------------------------------------------------------- | --------------------------------- | ------- |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` &#124; `value`            | `group` |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string &#124; ((datum) => string) | `id`    |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string &#124; string[]            | -       |\n| invert | 是否反转色板                                                        | boolean                           | false   |\n\n如将一组数据按 `category` 字段分配组合颜色，使得同类别的组合颜色相同：\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/combo/CircleCombo.en.md":"---\ntitle: Circle Combo\norder: 2\n---\n\n## Overview\n\nThe circular combo wraps child nodes or child combos with a circular boundary, suitable for representing equal or non-hierarchical group relationships.\n\nApplicable scenarios:\n\n- Suitable for representing node groups without a clear hierarchical relationship. The circular combo can reflect the equality of members, such as user groups in social networks or decentralized team structures (highlighting collaboration).\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example shows the distribution of interest group members:\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","packages/site/docs/manual/element/combo/CircleCombo.zh.md":"---\ntitle: 圆形组合 Circle\norder: 2\n---\n\n## 概述\n\n圆形组合以圆形边界包裹子节点或子组合，适合表示平等或非层级化的群组关系。\n\n适用场景：\n\n- 适合表示无明确层级关系的节点群组，圆形组合能体现成员的平等性，如社交网络中的用户群体、分散式团队结构（突出协作性）。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为兴趣小组人员分布：\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","packages/site/docs/manual/element/combo/RectCombo.en.md":"---\ntitle: Rect Combo\norder: 3\n---\n\n## Overview\n\nThe rectangular combo organizes content with right-angle boundaries, supporting strict hierarchical structures.\n\nApplicable scenarios:\n\n- **System Architecture Diagrams**: Such as service layering within system architecture, and subdivisions within each layer.\n- **Geographical Area Division**: Such as cities containing multiple areas, where the rectangular combo can intuitively display administrative boundaries or functional divisions.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example is a simple microservice architecture service layer:\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","packages/site/docs/manual/element/combo/RectCombo.zh.md":"---\ntitle: 矩形组合 Rect\norder: 3\n---\n\n## 概述\n\n矩形组合以直角边界组织内容，支持严格的层级结构。\n\n适用场景：\n\n- **系统架构图**：如系统架构里面的服务分层，以及每层服务里面的细分等。\n- **地理区域划分**：如城市包含多个区域，矩形组合能直观展示行政边界或功能分区。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为简单的微服务架构服务层：\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","packages/site/docs/manual/element/combo/custom-combo.en.md":"---\ntitle: Custom Combo\norder: 4\n---\n\nG6 provides two types of [built-in combos](/en/manual/element/combo/base-combo): circular combos and rectangular combos. However, in complex business scenarios, you may need to create custom combos with specific styles, interactive effects, or behavior logic.\n\n## Before You Start: Understanding the Basic Composition of Combos\n\nIn G6, a complete combo typically consists of the following parts:\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the main shape of the combo, such as a circle, rectangle, etc.\n- `label`: Text label, usually used to display the name or description of the combo.\n- `halo`: A graphic that displays a halo effect around the main graphic.\n\n### Special Characteristics of Combos\n\nCombos differ from ordinary nodes and have the following characteristics:\n\n1. **Containment**: Combos can contain nodes and other combos, forming a hierarchical structure.\n2. **Two States**: Expanded and Collapsed states.\n3. **Adaptive Size**: Automatically adjusts size based on internal elements.\n4. **Drag Behavior**: Supports overall dragging and dragging elements in/out.\n\n## Ways to Customize Combos <Badge type=\"warning\">Choose the Right Way</Badge>\n\nThere are two ways to create custom combos:\n\n### 1. Inherit Existing Combo Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most common way, and you can choose to inherit one of the following types:\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - The most basic combo class, providing core functionality for combos.\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - Circular combo.\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - Rectangular combo.\n\n**Why choose this way?**\n\n- 📌 **Less Code**: Reuse existing combo properties and methods, focusing only on new features.\n- 📌 **Fast Development**: Suitable for most project needs, quickly achieving business goals.\n- 📌 **Easy Maintenance**: Clear code structure and clear inheritance relationships.\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing combo types (recommended), you can jump directly to [Create Your First Custom Combo in Three Steps](#create-your-first-custom-combo-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Develop from Scratch Based on the G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing combo types do not meet your needs, you can create combos from scratch based on the underlying graphics system of G.\n\n**Why choose this way?**\n\n- 📌 **Maximum Freedom**: Full control over every detail of the combo, achieving any complex effect.\n- 📌 **Special Needs**: Highly customized scenarios that existing combo types cannot meet.\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios.\n\n:::warning{title=Note}\nDeveloping custom combos from scratch requires handling all details yourself, including graphic drawing, event response, state changes, expand/collapse logic, etc., which is quite challenging. You can directly refer to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) for implementation.\n:::\n\n## Create Your First Custom Combo in Three Steps\n\nLet's start by inheriting `BaseCombo` to implement a custom hexagon combo:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// Define the path for the collapsed state button\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// Define the path for the expanded state button\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the expand/collapse button, using paths for finer control\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Override the render method to add more custom graphics\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // Use lifecycle hooks to add event listeners\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// Register the custom combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// Create a graph instance and use the custom combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Step 1: Write the Custom Combo Class\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// Define button path generation functions\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic, directly using path data\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic, using path type to directly pass in style objects\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the collapse/expand button, using SVG paths for finer control\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Use lifecycle hook methods to bind events\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### Step 2: Register the Custom Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### Step 3: Apply the Custom Combo\n\n```js\nconst graph = new Graph({\n  // ...other configurations\n  combo: {\n    type: 'hexagon-combo', // Use the name registered\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // Since we implemented the collapse/expand feature ourselves, only drag behavior is needed here\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 Congratulations! You have created your first custom combo.\n\n## Going Further: Understanding the Principles of Combo Drawing\n\n### Differences Between Combos and Nodes\n\nAlthough Combos inherit from `BaseNode`, there are some key differences:\n\n1. **Adaptive Size**: Combos automatically calculate the appropriate size based on internal elements.\n2. **Expand/Collapse States**: Combos have two display states and need to handle state transitions.\n3. **Hierarchical Structure**: Combos can be nested, forming hierarchical relationships.\n4. **Internal Element Management**: Combos need to manage the nodes and sub-combos they contain.\n\n### Atomic Graphics\n\nG6's Combos are drawn using atomic graphic units provided by the [G Graphics System](https://g.antv.antgroup.com/). For an introduction to atomic graphics, please refer to the [Element - Shape (Optional)](/en/manual/element/shape/overview) documentation.\n\nAll these graphics can be dynamically created or updated using `upsert()` and automatically manage graphic states and lifecycles.\n\n### Element Base Class\n\nBefore customizing Combos, you need to understand some important properties and methods in the G6 element base class:\n\n#### Properties\n\n| Property   | Type                          | Description                                               |\n| ---------- | ----------------------------- | --------------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under the current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under the current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom Combos, you will frequently use the `upsert` method. It is short for \"update or insert\" and is responsible for adding or updating graphics in the element:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| key       | string                                  | Key of the graphic, corresponding to the key in `shapeMap`. Built-in keys include `'key'`, `'label'`, `'halo'`, `'icon'`, `'port'`, `'badge'`<br/> Keys should not use special symbols, and will be converted to camel case to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                  |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                 |\n\nFor example, insert a fixed-position purple circle:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics with `container.appendChild()`? Because:\n\n1. **Better Performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and recreating them, greatly improving rendering performance.\n2. **Simpler Code**: No need to manually check if elements exist.\n3. **Easy Management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, and you can easily access them with `this.getShape(key)`.\n\n#### `render(attributes, container)`: Main Entry for Rendering Combos\n\nEvery custom combo class must implement the `render(attributes, container)` method, which defines how the combo is \"drawn\". You can use various atomic graphics here to create the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation or have interactions between sub-graphics. In this case, the `getShape` method can help you access any graphics previously created with `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, make sure A is created first.\n\n### Element Conventions\n\n- **Use Convention Properties**\n\nThe convention properties in combos include:\n\n- Use `this.getKeySize(attributes)` to get the size of the combo, considering the collapsed state and sub-elements.\n- Use `this.getContentBBox(attributes)` to get the bounding box of the content area.\n- Use `this.getComboPosition(attributes)` to get the current position of the combo, based on state and sub-elements.\n\n- **Use `getXxxStyle` and `drawXxxShape` Pairing for Graphic Drawing**\n\n`getXxxStyle` is used to get the graphic style, and `drawXxxShape` is used to draw the graphic. Graphics created this way support automatic animation execution.\n\n> `Xxx` is the camel case form of the key passed to the [upsert](#methods) method.\n\n- **Access Graph Context via `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, and you can override these methods in custom combos to execute specific logic at key moments:\n\n| Hook Function | Trigger Timing                                                     | Typical Use Cases                                                                |\n| ------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| `onCreate`    | After the combo is created and the entrance animation is completed | Bind interactive events, initialize combo state, add external listeners          |\n| `onUpdate`    | After the combo is updated and the update animation is completed   | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | After the combo is destroyed and the exit animation is completed   | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"drawing logic\"**.\n\nYou can define styles for each state in the combo configuration:\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\nThis state will be passed into the `render()` method's `attributes` and automatically applied to the graphics as a result of the internal system merging.\n\nYou can also customize rendering logic based on the state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","packages/site/docs/manual/element/combo/custom-combo.zh.md":"---\ntitle: 自定义 Combo\norder: 4\n---\n\nG6 提供了两种 [内置组合](/manual/element/combo/base-combo) 类型：圆形组合和矩形 Combo 。但在复杂的业务场景中，你可能需要创建具有特定样式、交互效果或行为逻辑的自定义 Combo 。\n\n## 开始之前：了解 Combo 的基本构成\n\n在 G6 中，一个完整的 Combo 通常由以下几个部分组成：\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ： Combo 的主图形，表示 Combo 的主要形状，如圆形、矩形等；\n- `label` ：文本标签，通常用于展示 Combo 的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n\n### Combo 的特殊性\n\nCombo 不同于普通节点，它具有以下特性：\n\n1. **包含性**： Combo 可以包含节点和其他 Combo ，形成层级结构\n2. **两种状态**：展开(Expanded)和收起(Collapsed)状态\n3. **自适应大小**：根据内部元素动态调整大小\n4. **拖拽行为**：支持整体拖拽及内部元素拖入/拖出\n\n## 自定义 Combo 的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义 Combo 的方式有两种途径：\n\n### 1. 继承现有 Combo 类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - 最基础的 Combo 类，提供 Combo 的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - 圆形 Combo\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - 矩形 Combo\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有 Combo 的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有组合类型（推荐），可以直接跳到 [三步创建你的第一个自定义 Combo](#三步创建你的第一个自定义-combo) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有 Combo 类型都不满足需求，你可以基于 G 的底层图形系统从零创建 Combo。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制 Combo 的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有 Combo 类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义 Combo 需要自行处理所有细节，包括图形绘制、事件响应、状态变化、展开/收起逻辑等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义 Combo\n\n让我们从继承 `BaseCombo` 开始，实现一个自定义六边形 Combo ：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// 定义收起状态的按钮路径\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// 定义展开状态的按钮路径\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建SVG路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制展开/收起按钮，使用路径实现更精细的控制\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 重写render方法，添加更多自定义图形\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // 使用生命周期钩子添加事件监听\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// 注册自定义 Combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// 创建图实例并使用自定义 Combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义 Combo 类\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// 定义按钮路径生成函数\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建 SVG 路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式，直接使用路径数据\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形，使用 path 类型直接传入样式对象\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制收起/展开按钮，使用 SVG 路径实现更精细的控制\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 使用生命周期钩子方法绑定事件\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### 第二步：注册自定义 Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### 第三步：应用自定义 Combo\n\n```js\nconst graph = new Graph({\n  // ...其他配置\n  combo: {\n    type: 'hexagon-combo', // 使用注册时的名称\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // 由于我们自己实现了折叠展开功能，这里只需要拖拽行为\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 恭喜！你已经创建了第一个自定义 Combo 。\n\n## 更进一步：理解 Combo 绘制的原理\n\n### Combo 与节点的区别\n\n虽然 Combo 继承自 `BaseNode`，但有一些关键区别：\n\n1. **自适应大小**： Combo 会根据内部元素自动计算合适的大小\n2. **展开/收起状态**： Combo 有两种显示状态，并需要处理状态切换\n3. **层级结构**： Combo 可以嵌套，形成层级关系\n4. **内部元素管理**： Combo 需要管理其包含的节点和子 Combo\n\n### 原子图形\n\nG6 的 Combo 是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。原子图形的介绍请参考 [元素 - 图形（可选）](/manual/element/shape/overview) 文档。\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义 Combo 之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义 Combo 时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见 [元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                                |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                          |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染组合的主入口\n\n每个自定义 Combo 类都必须实现 `render(attributes, container)` 方法，它定义了该组合如何被\"绘制\"出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n组合中约定的元素属性包括：\n\n- 通过 `this.getKeySize(attributes)` 获取组合的尺寸，考虑折叠状态和子元素\n- 通过 `this.getContentBBox(attributes)` 获取内容区域的边界盒\n- 通过 `this.getComboPosition(attributes)` 获取组合的当前位置，基于状态和子元素\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义 Combo 中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                   | 典型用途                                     |\n| ----------- | -------------------------- | -------------------------------------------- |\n| `onCreate`  | 当组合创建后完成入场动画时 | 绑定交互事件、初始化组合状态、添加外部监听器 |\n| `onUpdate`  | 当组合更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果     |\n| `onDestroy` | 当组合完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知       |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **\"状态响应\"** 与 **\"绘制逻辑\"** 分离。\n\n你可以在组合配置中定义每种状态下的样式：\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","packages/site/docs/manual/element/combo/overview.en.md":"---\ntitle: Combo Overview\norder: 0\n---\n\n## What is a Combo\n\nA Combo, short for Combination, is a special type of graph element in G6 that can contain nodes and sub-combos, similar to the concept of \"groups\" or \"containers.\" It is typically used to represent set relationships, such as a department containing multiple employees or a city containing multiple regions.\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=Note}\nIt is not recommended to use Combos in **tree graphs**. The layout mechanism of tree graphs is incompatible with that of Combos, which can lead to node misalignment or style confusion.\n:::\n\nG6 has built-in Combos including `circle` (circular combo) and `rect` (rectangular combo), as shown in the images below:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## Data Structure\n\nWhen defining a Combo, you need to add a `combos` field to the graph's data object. Each Combo is an object with the following structure:\n\n| Attribute | Description                                                                                            | Type           | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------ | -------------- | ------- | -------- |\n| id        | Unique identifier of the combo                                                                         | string         | -       | ✓        |\n| type      | Combo type, name of built-in combo type or custom combo name, such as `circle` or `rect`               | string         | -       |          |\n| data      | Combo data, used to store custom data of the combo, accessible via callback functions in style mapping | object         | -       |          |\n| style     | Combo style                                                                                            | object         | -       |          |\n| states    | Initial states of the combo                                                                            | string[]       | -       |          |\n| combo     | Parent combo ID. If there is no parent combo, it is null                                               | string \\| null | -       |          |\n\nAn example of a data item in the `combos` array:\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\nTo assign a node to a Combo, you can add a `combo` field to the node data:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 belongs to comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // define comboA\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure Combos, listed in order of priority from highest to lowest:\n\n- Use `graph.setCombo()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setCombo()`\n\nYou can dynamically set the style mapping logic of Combos using `graph.setCombo()` after the graph instance is created.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nYou can configure Combo style mapping globally during graph instantiation. This configuration will apply to all Combos.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Specify combo type and combo style type in the combo configuration\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different Combos, you can write the configuration into the Combo data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\n// Specify combo type and combo style type in the data\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## Example\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo Interaction\n\nSimply rendering a Combo does not provide much practical value; it is only when a series of interactive operations are supported that the value of Combos can be maximized.\n\nIn G6, we have built-in interactions such as `drag-element` and `collapse-expand`.\n\n#### drag-element\n\nSupports dragging nodes and Combos. During the dragging of a Combo, the positions of nodes and edges within the Combo will dynamically change. After dragging is complete, the relative positions of the Combo and nodes remain unchanged. You can also change the affiliation of the Combo during dragging by setting `dropEffect: 'link'`.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\nSupports double-clicking a Combo to collapse and expand it. After collapsing a Combo, all nodes within the Combo are hidden. If there are connections between external nodes and nodes within the Combo, all connections will connect to the Combo.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## Custom Combos\n\nWhen built-in Combos cannot meet your needs, G6 provides powerful customization capabilities:\n\n- Extend built-in Combos\n- Create new Combo types\n\nUnlike Combos, custom Combos need to be registered before use. For detailed tutorials, please refer to the [Custom Combo](/en/manual/element/combo/custom-combo) documentation.\n","packages/site/docs/manual/element/combo/overview.zh.md":"---\ntitle: 组合总览\norder: 0\n---\n\n## 什么是组合\n\n组合(Combo) 全称为 Combination，是 G6 中的一种特殊的图元素，它可以包含节点和子组合，类似“群组”或“容器”的概念。它通常用于表示集合关系，例如一个部门包含多个员工，一个城市包含多个区域等。\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=注意}\n不推荐在**树图**中使用 Combo。因为树图的布局与 Combo 的布局机制不兼容，容易导致节点错位或样式混乱。\n:::\n\nG6 的内置 Combo 包括 `circle`（圆形组合）和 `rect` (矩形组合) 两种类型，分别如下图所示：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## 数据结构\n\n定义 Combo 时，需要在图的数据对象中添加 `combos` 字段，每个 Combo 是一个对象，结构如下：\n\n| 属性   | 描述                                                                    | 类型           | 默认值 | 必选 |\n| ------ | ----------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                        | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称，比如 `circle` 或者 `rect` | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取    | object         | -      |      |\n| style  | 组合样式                                                                | object         | -      |      |\n| states | 组合初始状态                                                            | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                              | string \\| null | -      |      |\n\n`combos` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n要将节点归属到某个 Combo，可以在节点数据中添加 `combo` 字段：\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 属于 comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // 定义 comboA\n}\n```\n\n## 配置方法\n\n配置 Combo 的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setCombo()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setCombo()`\n\n可在图实例创建后，使用 `graph.setCombo()` 动态设置 Combo 的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `combo` 配置 Combo 样式映射，这里的配置是全局的配置，将会在所有 Combo 上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 在组合配置中指定组合类型以及组合样式类型\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同 Combo 进行不同的配置，可以将配置写入到 Combo 数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\n// 在数据中指定组合类型以及组合样式类型\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## 示例\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo 交互\n\n只是简单地将 Combo 渲染出来，并没有多大的实用价值，只有支持一系列的交互操作后，才能最大程度地体现 Combo 的价值。\n\n在 G6 中，我们内置了 `drag-element`、`collapse-expand` 三个交互。\n\n#### drag-element\n\n支持拖动节点和 Combo。拖动 Combo 过程中，会动态改变 Combo 中节点和边的位置，在拖拽完成以后，保持 Combo 和节点的相对位置不变。还可以通过设置 `dropEffect: 'link'` 在拖拽时改变 Combo 的从属关系。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\n支持双击 Combo 收起和展开 Combo ，收起 Combo 以后，隐藏 Combo 中的所有节点，外部节点和 Combo 中节点有连线的情况下，所有连接会连接到 Combo 上面。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## 自定义组合\n\n当内置组合无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置组合进行扩展\n- 创建全新的组合类型\n\n与组合不同，自定义组合需要先注册后使用。详细教程请参考 [自定义组合](/manual/element/combo/custom-combo) 文档。\n","packages/site/docs/manual/element/edge/BaseEdge.en.md":"---\ntitle: Edge Common Configuration\norder: 1\n---\n\nThis document introduces the built-in edge common property configurations.\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // Edge type\n    style: {}, // Edge style\n    state: {}, // State styles\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name         | [Type](#type)           | `line`  |          |\n| style     | Edge style configuration, including color, thickness, etc.     | [Style](#style)         | -       |          |\n| state     | Style configuration for different states                       | [State](#state)         | -       |          |\n| palette   | Define edge palette for mapping colors based on different data | [Palette](#palette)     | -       |          |\n| animation | Define edge animation effects                                  | [Animation](#animation) | -       |          |\n\n## Type\n\nSpecify the edge type, built-in edge type name or custom edge name. Default is `line` (straight line edge). **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select edge types based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    // Static configuration\n    type: 'line',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `line`: [Straight line edge](/en/manual/element/edge/line)\n- `polyline`: [Polyline edge](/en/manual/element/edge/polyline)\n- `cubic`: [Cubic Bezier curve edge](/en/manual/element/edge/cubic)\n- `cubic-horizontal`: [Horizontal cubic Bezier curve edge](/en/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`: [Vertical cubic Bezier curve edge](/en/manual/element/edge/cubic-vertical)\n- `quadratic`: [Quadratic Bezier curve edge](/en/manual/element/edge/quadratic)\n\n## Style\n\nDefine edge styles, including color, thickness, etc.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // Static configuration\n      stroke: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineDash: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Edge: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the edge data object (`EdgeData`), containing all data information of the edge.\n\nA complete edge consists of the following parts:\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the main path of the edge, such as straight lines, curves, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `badge`: Badge on the edge\n- `halo`: The halo effect graphic displayed around the main graphic\n- `startArrow`: Arrow at the starting end of the edge\n- `endArrow`: Arrow at the ending end of the edge\n\nThe following style configurations will be explained by atomic graphics in order:\n\n### Main Graphic Styles\n\nThe main graphic is the core part of the edge, defining the basic path and appearance of the edge. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // Blue edge\n      lineWidth: 2, // Edge width\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Line Style\n\nCreate edges with dashed line style:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // Dashed line style\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Shadow Effect\n\nAdd shadow effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                        | Type                  | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------- | -------- |\n| cursor                          | Mouse cursor style when hovering over edge, [options](#cursor)                                                                     | string                | `default` |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. We can increase this area to make \"thin lines\" easier to pick up | number                | 0         |          |\n| lineDash                        | Edge dash line style                                                                                                               | number[]              | -         |          |\n| lineDashOffset                  | Edge dash line offset                                                                                                              | number                | 0         |          |\n| lineWidth                       | Edge width                                                                                                                         | number                | 1         |          |\n| opacity                         | Edge opacity                                                                                                                       | number \\| string      | 1         |          |\n| pointerEvents                   | How edge responds to pointer events, [options](#pointerevents)                                                                     | string                | `auto`    |          |\n| shadowBlur                      | Edge shadow blur                                                                                                                   | number                | -         |          |\n| shadowColor                     | Edge shadow color                                                                                                                  | string                | -         |          |\n| shadowOffsetX                   | Edge shadow offset in x direction                                                                                                  | number \\| string      | -         |          |\n| shadowOffsetY                   | Edge shadow offset in y direction                                                                                                  | number \\| string      | -         |          |\n| shadowType                      | Edge shadow type                                                                                                                   | `inner` \\| `outer`    | `outer`   |          |\n| sourcePort                      | Connection port at the source end of the edge                                                                                      | string                | -         |          |\n| stroke                          | Edge color                                                                                                                         | string                | `#000`    |          |\n| strokeOpacity                   | Edge color opacity                                                                                                                 | number \\| string      | 1         |          |\n| targetPort                      | Connection port at the target end of the edge                                                                                      | string                | -         |          |\n| transform                       | Transform property allows you to rotate, scale, skew, or translate the given edge                                                  | string                | -         |          |\n| transformOrigin                 | The center of rotation and scaling, also known as the transform center                                                             | string                | -         |          |\n| visibility                      | Whether the edge is visible                                                                                                        | `visible` \\| `hidden` | `visible` |          |\n| zIndex                          | Edge rendering layer                                                                                                               | number                | 1         |          |\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, both `stroke` and `visibility` can independently or in combination affect hit testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Never becomes a target for responding to events\n- **`visiblepainted`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n- **`visiblestroke`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`visible`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`painted`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`stroke`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Responds to events as long as entering the graphic stroke area, not affected by `stroke` or `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely non-responsive to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // Edge does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Styles\n\nLabels are used to display text information for edges, supporting various style configurations and layout options. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Edge Label',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'This is a very long edge label that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdd background to labels for better readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Important Connection',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Auto-rotating Label\n\nLabels can automatically rotate to align with edge direction:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Auto Rotate',\n      labelAutoRotate: true, // Auto rotate\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete label style configuration:\n\n| Property                 | Description                                                                                                     | Type                                                                        | Default   | Required |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show edge label                                                                                      | boolean                                                                     | true      |          |\n| labelAutoRotate          | Whether edge label automatically rotates to align with edge direction                                           | boolean                                                                     | true      |          |\n| labelCursor              | Mouse cursor style when hovering over edge label, [options](#cursor)                                            | string                                                                      | `default` |          |\n| labelFill                | Edge label text color                                                                                           | string                                                                      | -         |          |\n| labelFontFamily          | Edge label font family                                                                                          | string                                                                      | -         |          |\n| labelFontSize            | Edge label font size                                                                                            | number                                                                      | 12        |          |\n| labelFontStyle           | Edge label font style                                                                                           | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Edge label font variant                                                                                         | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Edge label font weight                                                                                          | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                    | number                                                                      | 0         |          |\n| labelLetterSpacing       | Edge label letter spacing                                                                                       | number \\| string                                                            | -         |          |\n| labelLineHeight          | Edge label line height                                                                                          | number \\| string                                                            | -         |          |\n| labelMaxLines            | Edge label maximum lines                                                                                        | number                                                                      | 1         |          |\n| labelMaxWidth            | Edge label maximum width, [options](#labelmaxwidth)                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Edge label offset in x direction                                                                                | number                                                                      | 0         |          |\n| labelOffsetY             | Edge label offset in y direction                                                                                | number                                                                      | 0         |          |\n| labelPadding             | Edge label padding                                                                                              | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Edge label position relative to edge, [options](#labelplacement)                                                | string \\| number                                                            | `center`  |          |\n| labelText                | Edge label text content                                                                                         | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Edge label text horizontal alignment                                                                            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Edge label text baseline                                                                                        | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Edge label text decoration line color                                                                           | string                                                                      | -         |          |\n| labelTextDecorationLine  | Edge label text decoration line                                                                                 | string                                                                      | -         |          |\n| labelTextDecorationStyle | Edge label text decoration line style                                                                           | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Edge label text overflow handling                                                                               | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Edge label text path                                                                                            | Path                                                                        | -         |          |\n| labelWordWrap            | Whether to enable automatic line wrapping for edge labels. When enabled, text exceeding labelMaxWidth will wrap | boolean                                                                     | false     |          |\n| labelZIndex              | Edge label rendering layer                                                                                      | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nEdge label position relative to the edge, can be set to:\n\n- `start`: Label positioned at the starting point of the edge\n- `center`: Label positioned at the center of the edge (default)\n- `end`: Label positioned at the ending point of the edge\n- `number`: Value range 0-1, representing the specific position ratio of the label on the edge, 0 for start position, 1 for end position\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text exceeding this width will wrap:\n\n- string: Represents the maximum width defined as a percentage relative to the edge length. For example, `50%` means the label width does not exceed half the edge length\n- number: Represents the maximum width defined in pixels. For example, 100 means the label's maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Styles\n\nLabel background is used to display the background of edge labels:\n\n| Property                      | Description                                                                                                                                                       | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to show edge label background                                                                                                                             | boolean                                  | false     |\n| labelBackgroundCursor         | Edge label background mouse cursor style, [options](#cursor)                                                                                                      | string                                   | `default` |\n| labelBackgroundFill           | Edge label background fill color                                                                                                                                  | string                                   | -         |\n| labelBackgroundFillOpacity    | Edge label background opacity                                                                                                                                     | number                                   | 1         |\n| labelBackgroundHeight         | Edge label background height                                                                                                                                      | string \\| number                         | -         |\n| labelBackgroundLineDash       | Edge label background dash line configuration                                                                                                                     | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Edge label background dash line offset                                                                                                                            | number                                   | -         |\n| labelBackgroundLineWidth      | Edge label background stroke line width                                                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | Edge label background border radius <br> - number: Uniform radius for all corners <br> - number[]: Individual radius for each corner, auto-filled if insufficient | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Edge label background shadow blur                                                                                                                                 | number                                   | -         |\n| labelBackgroundShadowColor    | Edge label background shadow color                                                                                                                                | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Edge label background shadow X offset                                                                                                                             | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Edge label background shadow Y offset                                                                                                                             | number                                   | -         |\n| labelBackgroundStroke         | Edge label background stroke color                                                                                                                                | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Edge label background stroke opacity                                                                                                                              | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Edge label background visibility                                                                                                                                  | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Edge label background rendering layer                                                                                                                             | number                                   | 1         |\n\n### Halo Styles\n\nHalo is an effect displayed around the edge main graphic, usually used for highlighting or indicating special states of the edge.\n\n#### Basic Halo Effect\n\nAdd basic halo effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete halo style configuration:\n\n| Property          | Description                                                                          | Type                   | Default                                   | Required |\n| ----------------- | ------------------------------------------------------------------------------------ | ---------------------- | ----------------------------------------- | -------- |\n| halo              | Whether to show edge halo                                                            | boolean                | false                                     |          |\n| haloCursor        | Edge halo mouse cursor style, [options](#cursor)                                     | string                 | `default`                                 |          |\n| haloDraggable     | Whether edge halo allows dragging                                                    | boolean                | true                                      |          |\n| haloDroppable     | Whether edge halo allows receiving dragged elements                                  | boolean                | true                                      |          |\n| haloFillRule      | Edge halo fill rule                                                                  | `nonzero` \\| `evenodd` | -                                         |          |\n| haloFilter        | Edge halo filter                                                                     | string                 | -                                         |          |\n| haloLineWidth     | Edge halo stroke width                                                               | number                 | 3                                         |          |\n| haloPointerEvents | Whether edge halo responds to pointer events, [options](#pointerevents)              | string                 | `none`                                    |          |\n| haloStroke        | Edge halo stroke color, **this property sets the color of the halo around the edge** | string                 | Consistent with main graphic stroke color |          |\n| haloStrokeOpacity | Edge halo stroke opacity                                                             | number                 | 0.25                                      |          |\n| haloVisibility    | Edge halo visibility                                                                 | `visible` \\| `hidden`  | `visible`                                 |          |\n| haloZIndex        | Edge halo rendering layer                                                            | number                 | -1                                        |          |\n\n### Arrow Styles\n\nEdges support adding arrows at the start and end points to indicate the directionality of the edge.\n\n#### Basic Arrow\n\nAdd basic arrow to the end of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // End arrow\n      endArrowType: 'vee', // Arrow type\n      endArrowSize: 10, // Arrow size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Bidirectional Arrows\n\nAdd arrows to both ends of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // Start arrow\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // End arrow\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Arrow Style\n\nCustomize arrow color and type:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // Diamond arrow\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // Red arrow fill\n      endArrowStroke: '#722ED1', // Arrow stroke color\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Start Arrow Style Configuration\n\n| Property                | Description                                             | Type                                                                                 | Default                            | Required |\n| ----------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| startArrow              | Whether to show edge start arrow                        | boolean                                                                              | false                              |          |\n| startArrowCursor        | Edge start arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| startArrowFill          | Edge start arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| startArrowFillOpacity   | Edge start arrow fill opacity                           | number                                                                               | 1                                  |          |\n| startArrowOffset        | Edge start arrow offset                                 | number                                                                               | 0                                  |          |\n| startArrowSize          | Edge start arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| startArrowStroke        | Edge start arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| startArrowStrokeOpacity | Edge start arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| startArrowType          | Edge start arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n#### End Arrow Style Configuration\n\n| Property              | Description                                           | Type                                                                                 | Default                            | Required |\n| --------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| endArrow              | Whether to show edge end arrow                        | boolean                                                                              | false                              |          |\n| endArrowCursor        | Edge end arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| endArrowFill          | Edge end arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| endArrowFillOpacity   | Edge end arrow fill opacity                           | number                                                                               | 1                                  |          |\n| endArrowOffset        | Edge end arrow offset                                 | number                                                                               | 0                                  |          |\n| endArrowSize          | Edge end arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| endArrowStroke        | Edge end arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| endArrowStrokeOpacity | Edge end arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| endArrowType          | Edge end arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n### Loop Edge Styles\n\nLoop edges are special edges where the start and end nodes are the same node.\n\n#### Basic Loop Edge\n\nCreate a basic loop edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // Loop position\n      loopDist: 30, // Loop size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Loop Edges\n\nCreate multiple loop edges at different positions for the same node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete loop edge style configuration:\n\n| Property      | Description                                                         | Type                                                                                                                                                                   | Default                  | Required |\n| ------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- |\n| loop          | Whether to enable loop edges                                        | boolean                                                                                                                                                                | true                     |          |\n| loopClockwise | Whether to draw the loop clockwise                                  | boolean                                                                                                                                                                | true                     |          |\n| loopDist      | Distance from node edge to loop top, used to specify loop curvature | number                                                                                                                                                                 | Default to max node size |          |\n| loopPlacement | Loop edge position                                                  | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                    |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select an edge or hovering to activate an edge, it's simply marking certain states on that element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of that graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. Additionally, it supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\nFor example, when an edge is in the `focus` state, you can add a halo with a width of 6 and orange color.\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefine edge animation effects. Supports the following two configuration methods:\n\n1. Disable all edge animations\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to the animation effects when edges enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when edge enters the canvas\n- `update`: Animation when edge updates\n- `exit`: Animation when edge leaves the canvas\n- `show`: Animation when edge shows from hidden state\n- `hide`: Animation when edge hides\n- `collapse`: Animation when edge collapses\n- `expand`: Animation when edge expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#动画范式) to use animation syntax to configure edges, such as:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // Only animate stroke property during update\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"path-in\", // Use path animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable specific stage animations:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // Disable edge entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefine the edge palette, which is a predefined edge color pool that is allocated according to rules and maps colors to the `stroke` property.\n\n> For palette definitions, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to using id as grouping field                  | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                     | `group` \\| `value`            | `group` |\n\nFor example, to assign edge colors to a group of data by the `direction` field, making edges of the same category have the same color:\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau is the palette name, colors assigned by ID by default\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/BaseEdge.zh.md":"---\ntitle: 边通用配置项\norder: 1\n---\n\n本文介绍内置边通用属性配置。\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // 边类型\n    style: {}, // 边样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                   | 类型                    | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](#type)           | `line` |      |\n| style     | 边样式配置，包括颜色、粗细等           | [Style](#style)         | -      |      |\n| state     | 不同状态下的样式配置                   | [State](#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](#animation) | -      |      |\n\n## Type\n\n指定边类型，内置边类型名称或自定义边的名称。默认为 `line`（直线边）。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据边数据动态选择边类型：\n\n```js\nconst graph = new Graph({\n  edge: {\n    // 静态配置\n    type: 'line',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `line`：[直线边](/manual/element/edge/line)\n- `polyline`：[折线边](/manual/element/edge/polyline)\n- `cubic`：[三次贝塞尔曲线边](/manual/element/edge/cubic)\n- `cubic-horizontal`：[水平三次贝塞尔曲线边](/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`：[垂直三次贝塞尔曲线边](/manual/element/edge/cubic-vertical)\n- `quadratic`：[二次贝塞尔曲线边](/manual/element/edge/quadratic)\n\n## Style\n\n定义边的样式，包括颜色、粗细等。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据边数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // 静态配置\n      stroke: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineDash: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `边: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\n其中 `datum` 参数为边数据对象 (`EdgeData`)，包含边的所有数据信息。\n\n一个完整的边由以下几部分构成：\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要路径，例如直线、曲线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `badge` ：边上的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `startArrow` ：边起始端的箭头；\n- `endArrow` ：边结束端的箭头。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是边的核心部分，定义了边的基本路径和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置边的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // 蓝色边\n      lineWidth: 2, // 边宽度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线样式\n\n创建带虚线样式的边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // 虚线样式\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 阴影效果\n\n为边添加阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                  | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | --------------------- | --------- | ---- |\n| cursor                          | 边鼠标移入样式，[配置项](#cursor)                                                         | string                | `default` |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                | 0         |      |\n| lineDash                        | 边虚线样式                                                                                | number[]              | -         |      |\n| lineDashOffset                  | 边虚线偏移量                                                                              | number                | 0         |      |\n| lineWidth                       | 边宽度                                                                                    | number                | 1         |      |\n| opacity                         | 边透明度                                                                                  | number \\| string      | 1         |      |\n| pointerEvents                   | 边如何响应指针事件，[配置项](#pointerevents)                                              | string                | `auto`    |      |\n| shadowBlur                      | 边阴影模糊度                                                                              | number                | -         |      |\n| shadowColor                     | 边阴影颜色                                                                                | string                | -         |      |\n| shadowOffsetX                   | 边阴影在 x 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowOffsetY                   | 边阴影在 y 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowType                      | 边阴影类型                                                                                | `inner` \\| `outer`    | `outer`   |      |\n| sourcePort                      | 边起始连接的连接桩                                                                        | string                | -         |      |\n| stroke                          | 边颜色                                                                                    | string                | `#000`    |      |\n| strokeOpacity                   | 边颜色透明度                                                                              | number \\| string      | 1         |      |\n| targetPort                      | 边终点连接的连接桩                                                                        | string                | -         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定边                                          | string                | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                | -         |      |\n| visibility                      | 边是否可见                                                                                | `visible` \\| `hidden` | `visible` |      |\n| zIndex                          | 边渲染层级                                                                                | number                | 1         |      |\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的描边区域就会响应事件，不会受 `stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // 边不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示边的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '边标签',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '这是一个很长的边标签需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '重要连接',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自动旋转标签\n\n标签可以自动旋转以保持与边方向一致：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '自动旋转',\n      labelAutoRotate: true, // 自动旋转\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                             | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 边标签是否显示                                                                   | boolean                                                                     | true      |      |\n| labelAutoRotate          | 边标签是否自动旋转，保持与边的方向一致                                           | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入边标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 边标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 边标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 边标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 边标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 边标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 边标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                           | number                                                                      | 0         |      |\n| labelLetterSpacing       | 边标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 边标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 边标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 边标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 边标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 边标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 边标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 边标签相对于边的位置，[配置项](#labelplacement)                                  | string \\| number                                                            | `center`  |      |\n| labelText                | 边标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 边标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 边标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 边标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 边标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 边标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 边标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 边标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 边标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 边标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n边标签相对于边的位置，可以设置为：\n\n- `start`：标签位于边的起始位置\n- `center`：标签位于边的中心位置（默认）\n- `end`：标签位于边的结束位置\n- `number`：取值范围为 0-1，表示标签在边上的具体位置比例，0 为起始位置，1 为结束位置\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于边长度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过边长度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示边标签的背景：\n\n| 属性                          | 描述                                                                                                         | 类型                                     | 默认值    |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | --------- |\n| labelBackground               | 边标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 边标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 边标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 边标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 边标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 边标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 边标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 边标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 边标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 边标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 边标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 边标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 边标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 边标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 边标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 边标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 边标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕边主图形显示的效果，通常用于高亮显示或表示边的特殊状态。\n\n#### 基础光晕效果\n\n为边添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                 | 类型                   | 默认值                         | 必选 |\n| ----------------- | ---------------------------------------------------- | ---------------------- | ------------------------------ | ---- |\n| halo              | 边光晕是否显示                                       | boolean                | false                          |      |\n| haloCursor        | 边光晕鼠标移入样式，[配置项](#cursor)                | string                 | `default`                      |      |\n| haloDraggable     | 边光晕是否允许拖拽                                   | boolean                | true                           |      |\n| haloDroppable     | 边光晕是否允许接收被拖拽的元素                       | boolean                | true                           |      |\n| haloFillRule      | 边光晕填充规则                                       | `nonzero` \\| `evenodd` | -                              |      |\n| haloFilter        | 边光晕滤镜                                           | string                 | -                              |      |\n| haloLineWidth     | 边光晕描边宽度                                       | number                 | 3                              |      |\n| haloPointerEvents | 边光晕效果是否响应指针事件，[配置项](#pointerevents) | string                 | `none`                         |      |\n| haloStroke        | 边光晕描边色，**此属性用于设置边周围光晕的颜色**     | string                 | 与主图形的描边色 `stroke` 一致 |      |\n| haloStrokeOpacity | 边光晕描边色透明度                                   | number                 | 0.25                           |      |\n| haloVisibility    | 边光晕可见性                                         | `visible` \\| `hidden`  | `visible`                      |      |\n| haloZIndex        | 边光晕渲染层级                                       | number                 | -1                             |      |\n\n### 箭头样式\n\n边支持在起始端和结束端添加箭头，用于表示边的方向性。\n\n#### 基础箭头\n\n为边的结束端添加基本箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'vee', // 箭头类型\n      endArrowSize: 10, // 箭头大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 双向箭头\n\n为边的两端都添加箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // 起始端箭头\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义箭头样式\n\n自定义箭头的颜色和类型：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // 菱形箭头\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // 红色箭头填充\n      endArrowStroke: '#722ED1', // 箭头描边颜色\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 起始箭头样式配置\n\n| 属性                    | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| ----------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| startArrow              | 边起始箭头是否显示                        | boolean                                                                              | false              |      |\n| startArrowCursor        | 边起始箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| startArrowFill          | 边起始箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowFillOpacity   | 边起始箭头填充透明度                      | number                                                                               | 1                  |      |\n| startArrowOffset        | 边起始箭头的偏移量                        | number                                                                               | 0                  |      |\n| startArrowSize          | 边起始箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| startArrowStroke        | 边起始箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowStrokeOpacity | 边起始箭头描边透明度                      | number                                                                               | 1                  |      |\n| startArrowType          | 边起始箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n#### 结束箭头样式配置\n\n| 属性                  | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| --------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| endArrow              | 边结束箭头是否显示                        | boolean                                                                              | false              |      |\n| endArrowCursor        | 边结束箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| endArrowFill          | 边结束箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowFillOpacity   | 边结束箭头填充透明度                      | number                                                                               | 1                  |      |\n| endArrowOffset        | 边结束箭头的偏移量                        | number                                                                               | 0                  |      |\n| endArrowSize          | 边结束箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| endArrowStroke        | 边结束箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowStrokeOpacity | 边结束箭头描边透明度                      | number                                                                               | 1                  |      |\n| endArrowType          | 边结束箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n### 自环边样式\n\n自环边是指起始节点和结束节点为同一个节点的特殊边。\n\n#### 基础自环边\n\n创建基本的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // 自环位置\n      loopDist: 30, // 自环大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个自环边\n\n为同一节点创建多个不同位置的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的自环边样式配置：\n\n| 属性          | 描述                                           | 类型                                                                                                                                                                   | 默认值                 | 必选 |\n| ------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| loop          | 是否启用自环边                                 | boolean                                                                                                                                                                | true                   |      |\n| loopClockwise | 指定是否顺时针绘制环                           | boolean                                                                                                                                                                | true                   |      |\n| loopDist      | 从节点边缘到自环顶部的距离，用于指定自环的曲率 | number                                                                                                                                                                 | 默认为节点尺寸的最大值 |      |\n| loopPlacement | 自环边的位置                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                  |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个边或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\n例如，当边处于 `focus` 状态时，可以为其添加一个宽度为 6 且颜色为橙色的光晕。\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义边的动画效果，支持下列两种配置方式：\n\n1. 关闭边全部动画\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指边在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 边进入画布时的动画\n- `update`: 边更新时的动画\n- `exit`: 边离开画布时的动画\n- `show`: 边从隐藏状态显示时的动画\n- `hide`: 边隐藏时的动画\n- `collapse`: 边收起时的动画\n- `expand`: 边展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置边，如：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // 更新时只对 stroke 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ]\n    }\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"path-in\", // 使用路径动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // 关闭边入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义边的色板，即预定义边颜色池，并根据规则进行分配，将颜色映射到 `stroke` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `direction` 字段分配边颜色，使得同类别的边颜色相同：\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Cubic.en.md":"---\ntitle: Cubic Bezier Curve Edge\norder: 2\n---\n\n## Overview\n\nA cubic Bezier curve is a versatile smooth curve with control points that can be freely distributed, suitable for connecting nodes in any direction.\n\nUse cases:\n\n- Suitable for graphs with any layout, such as network graphs and relationship graphs.\n\n- Use when smooth node connections are needed without specific directional requirements.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type                               | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [[Point](#point), [Point](#point)] | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number &#124; number[]             | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number &#124; number[]             | 20      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Cubic.zh.md":"---\ntitle: 三次贝塞尔曲线边 Cubic\norder: 2\n---\n\n## 概述\n\n三次贝塞尔曲线是一种通用的平滑曲线，其控制点可以自由分布，适合连接任意方向的节点。\n\n使用场景：\n\n- 适用于任意布局的图，如网络图、关系图。\n\n- 当需要平滑连接节点且无特定方向要求时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型                               | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [[Point](#point), [Point](#point)] | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number &#124; number[]             | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number &#124; number[]             | 20     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicHorizontal.en.md":"---\ntitle: CubicHorizontal Bezier Curve Edge\norder: 3\n---\n\n## Overview\n\nThe horizontal cubic Bezier curve is a smooth curve with control points primarily distributed along the horizontal direction, suitable for connecting nodes horizontally.\n\nUse cases:\n\n- Suitable for horizontally laid-out graphs, such as flowcharts and hierarchical diagrams.\n\n- Use when emphasizing horizontal connections is needed.\n\n> Note: When calculating control points, the distance on the x-axis is primarily considered, ignoring changes on the y-axis.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Horizontal Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicHorizontal.zh.md":"---\ntitle: 水平三次贝塞尔曲线边 CubicHorizontal\norder: 3\n---\n\n## 概述\n\n水平三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿水平方向分布，适合在水平方向上连接节点。\n\n使用场景：\n\n- 适用于水平布局的图，如流程图、层次结构图。\n\n- 当需要强调水平方向的连接关系时使用。\n\n> 特别注意，计算控制点时主要考虑 x 轴上的距离，忽略 y 轴的变化\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置水平三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicVertical.en.md":"---\ntitle: CubicVertical Bezier Curve Edge\norder: 4\n---\n\n## Overview\n\nThe vertical cubic Bezier curve is a smooth curve with control points primarily distributed along the vertical direction, suitable for connecting nodes vertically.\n\nUse cases:\n\n- Suitable for vertically laid-out graphs, such as organizational charts and tree diagrams.\n\n- Use when emphasizing vertical connections is needed.\n\n**Note: When calculating control points, the distance on the y-axis is primarily considered, ignoring changes on the x-axis.**\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Vertical Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/CubicVertical.zh.md":"---\ntitle: 垂直三次贝塞尔曲线边 CubicVertical\norder: 4\n---\n\n## 概述\n\n垂直三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿垂直方向分布，适合在垂直方向上连接节点。\n\n使用场景：\n\n- 适用于垂直布局的图，如组织结构图、树状图。\n\n- 当需要强调垂直方向的连接关系时使用。\n\n**特别注意，计算控制点时主要考虑 y 轴上的距离，忽略 x 轴的变化**\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置垂直三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Line.en.md":"---\ntitle: Line Edge\norder: 5\n---\n\n## Overview\n\nA line is the simplest type of edge, directly connecting two nodes without any curvature.\n\nUse cases:\n\n- Suitable for simple graphs, such as topology diagrams and flowcharts.\n\n- Use when quick drawing is needed without complex visual effects.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n## Example\n\n### Built-in Line Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Line.zh.md":"---\ntitle: 直线边 Line\norder: 5\n---\n\n## 概述\n\n直线是最简单的边类型，直接连接两个节点，没有任何弯曲。\n\n使用场景：\n\n- 适用于简单的图，如拓扑图、流程图。\n\n- 当需要快速绘制且无需复杂视觉效果时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n## 示例\n\n### 内置直线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Polyline.en.md":"---\ntitle: Polyline Edge\norder: 6\n---\n\n## Overview\n\nA polyline is an edge composed of multiple straight line segments, suitable for connecting nodes by bypassing obstacles in complex layouts.\n\nUse cases:\n\n- Suitable for graphs with complex layouts, such as circuit diagrams and pipeline diagrams.\n\n- Use when you need to bypass other nodes or obstacles.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                | Type                                                                                    | Default | Required |\n| ------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the turning points of the polyline. | [Point](#point)[]                                                                       | []      |          |\n| radius        | Corner radius of the turning points.                                       | number                                                                                  | 0       |          |\n| router        | Whether to enable routing.                                                 | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false   |          |\n\n### OrthRouter\n\n| Attribute | Description                                                                                              | Type                | Default |\n| --------- | -------------------------------------------------------------------------------------------------------- | ------------------- | ------- |\n| type      | Orthogonal routing, adding extra control points on the path to keep each segment horizontal or vertical. | `'orth'`            | -       |\n| padding   | Minimum distance between the node connection point and the corner.                                       | [Padding](#padding) | `0`     |\n\n### ShortestPathRouter\n\n| Attribute                 | Description                                                                                                                                                                                                                                                                          | Type                                                                   | Default |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------- |\n| type                      | Shortest path routing, an intelligent version of orthogonal routing `'orth'`. This routing consists of horizontal or vertical orthogonal segments. It uses the A\\* algorithm to calculate the shortest path and supports automatic avoidance of other nodes (obstacles) on the path. | `'shortest-path'`                                                      | -       |\n| offset                    | Minimum distance between the node anchor point and the corner.                                                                                                                                                                                                                       | [Padding](#padding)                                                    | 0       |\n| gridSize                  | Grid cell size.                                                                                                                                                                                                                                                                      | number                                                                 | 0       |\n| maxAllowedDirectionChange | Maximum allowed rotation angle (radians).                                                                                                                                                                                                                                            | number                                                                 | 0       |\n| startDirections           | Possible starting directions of the node.                                                                                                                                                                                                                                            | [Direction](#direction)[]                                              | 0       |\n| endDirections             | Possible ending directions of the node.                                                                                                                                                                                                                                              | [Direction](#direction)[]                                              | 0       |\n| directionMap              | Specifies the movable directions.                                                                                                                                                                                                                                                    | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0       |\n| penalties                 | Represents additional costs for certain paths during path searching. The key is the radian value, and the value is the cost.                                                                                                                                                         | { [key: string]: number }                                              | 0       |\n| distFunc                  | Specifies the function to calculate the distance between two points.                                                                                                                                                                                                                 | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0       |\n| maximumLoops              | Maximum number of iterations.                                                                                                                                                                                                                                                        | number                                                                 | 0       |\n| enableObstacleAvoidance   | Whether to enable obstacle avoidance.                                                                                                                                                                                                                                                | boolean                                                                | false   |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## Example\n\n### Built-in Polyline Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Polyline.zh.md":"---\ntitle: 折线边 Polyline\norder: 6\n---\n\n## 概述\n\n折线是由多条直线段组成的边，适合在复杂布局中绕过障碍物连接节点。\n\n使用场景：\n\n- 适用于复杂布局的图，如电路图、管道图。\n\n- 当需要绕过其他节点或障碍物时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                             | 类型                                                                                    | 默认值 | 必选 |\n| ------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义折线的转折点 | [Point](#point)[]                                                                       | []     |      |\n| radius        | 转折点圆角半径                   | number                                                                                  | 0      |      |\n| router        | 是否启用路由                     | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false  |      |\n\n### OrthRouter\n\n| 属性    | 描述                                                                   | 类型                | 默认值 |\n| ------- | ---------------------------------------------------------------------- | ------------------- | ------ |\n| type    | 正交路由，通过在路径上添加额外的控制点，使得边的每一段都保持水平或垂直 | `'orth'`            | -      |\n| padding | 节点连接点与转角的最小距离                                             | [Padding](#padding) | `0`    |\n\n### ShortestPathRouter\n\n| 属性                      | 描述                                                                                                                                              | 类型                                                                   | 默认值 |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------ |\n| type                      | 最短路径路由，是正交路由 `'orth'` 的智能版本。该路由由水平或垂直的正交线段组成。采用 A\\* 算法计算最短路径，并支持自动避开路径上的其他节点（障碍） | `'shortest-path'`                                                      | -      |\n| offset                    | 节点锚点与转角的最小距离                                                                                                                          | [Padding](#padding)                                                    | 0      |\n| gridSize                  | grid 格子大小                                                                                                                                     | number                                                                 | 0      |\n| maxAllowedDirectionChange | 支持的最大旋转角度（弧度）                                                                                                                        | number                                                                 | 0      |\n| startDirections           | 节点的可能起始方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| endDirections             | 节点的可能结束方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| directionMap              | 指定可移动的方向                                                                                                                                  | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0      |\n| penalties                 | 表示在路径搜索过程中某些路径的额外代价。key 为弧度值，value 为代价                                                                                | { [key: string]: number }                                              | 0      |\n| distFunc                  | 指定计算两点之间距离的函数                                                                                                                        | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0      |\n| maximumLoops              | 最大迭代次数                                                                                                                                      | number                                                                 | 0      |\n| enableObstacleAvoidance   | 是否开启避障                                                                                                                                      | boolean                                                                | false  |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## 示例\n\n### 内置折线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Quadratic.en.md":"---\ntitle: Quadratic Bezier Curve Edge\norder: 6\n---\n\n## Overview\n\nA quadratic Bezier curve is a smooth curve whose shape is determined by a start point, an end point, and a control point.\n\nUse cases:\n\n- Suitable for moderately complex graphs, such as relationship graphs and network graphs.\n\n- Use when smooth node connections are needed with limited computational resources.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type            | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [Point](#point) | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number          | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number          | 30      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Quadratic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/Quadratic.zh.md":"---\ntitle: 二次贝塞尔曲线边 Quadratic\norder: 6\n---\n\n## 概述\n\n二次贝塞尔曲线是一种平滑的曲线，其形状由起点、终点和一个控制点决定。\n\n使用场景：\n\n- 适用于中等复杂度的图，如关系图、网络图。\n\n- 当需要平滑连接节点且计算资源有限时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型            | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | --------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [Point](#point) | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number          | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number          | 30     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置二次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/custom-edge.en.md":"---\ntitle: Custom Edge\norder: 7\n---\n\nG6 provides multiple [built-in edge](/en/manual/element/edge/base-edge) types, including [line](/en/manual/element/edge/line), [polyline](/en/manual/element/edge/polyline), [quadratic (quadratic Bézier curve edge)](/en/manual/element/edge/quadratic), [cubic (cubic Bézier curve edge)](/en/manual/element/edge/cubic), [cubic-horizontal](/en/manual/element/edge/cubic-horizontal), [cubic-vertical](/en/manual/element/edge/cubic-vertical), and more. These built-in edges can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter requirements that these basic edges cannot satisfy. In such cases, you need to create custom edges. Don't worry, it's simpler than you think!\n\n## Before Starting: Understanding the Basic Components of an Edge\n\nIn G6, a complete edge typically consists of the following parts:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the primary shape of the edge, such as straight lines, polylines, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `arrow`: Arrow, used to indicate the direction of the edge\n- `halo`: Graphic displaying halo effects around the main graphic\n\n## Ways to Create Custom Edges <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are two main ways to create custom edges:\n\n### 1. Inherit from Existing Edge Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach. You can choose to inherit from one of the following types:\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - The most basic edge class, providing core edge functionality\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - Straight line edge\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - Polyline edge\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - Quadratic Bézier curve edge\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - Cubic Bézier curve edge\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - Vertical cubic Bézier curve edge\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - Horizontal cubic Bézier curve edge\n\n**Why choose this approach?**\n\n- 📌 **Less code**: Reuse existing edge properties and methods, only focus on new functionality\n- 📌 **Fast development**: Suitable for most project requirements, quickly achieve business goals\n- 📌 **Easy maintenance**: Clear code structure, clear inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing edge types (recommended), you can jump directly to [Create Your First Custom Edge in Three Steps](#create-your-first-custom-edge-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing edge types don't meet your requirements, you can create edges from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum freedom**: Complete control over every detail of the edge, achieving any complex effects\n- 📌 **Special requirements**: Highly customized scenarios that existing edge types cannot satisfy\n- 📌 **Performance optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom edges built from scratch need to handle all details by themselves, including graphic rendering, event response, state changes, etc., which is more challenging to develop. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) for implementation.\n:::\n\n## Create Your First Custom Edge in Three Steps\n\nLet's start with the most basic `BaseEdge` to implement a custom straight line edge:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Edge Class\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // Define edge style, can add or override default styles\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // Call parent class method to get basic style, then add custom styles\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // Implement abstract method: define edge path\n  // This is an abstract method of BaseEdge, all subclasses must implement it\n  protected getKeyPath(attributes) {\n    // Get source node and target node\n    const { sourceNode, targetNode } = this;\n\n    // Get node position coordinates\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // Return SVG path array, defining a straight line from start to end\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=Key Method Analysis}\n\n- `getKeyStyle`: Defines the basic style of the edge, such as line width, color, etc.\n- `getKeyPath`: An abstract method in `BaseEdge` that **must be implemented**, it defines the path shape of the edge\n  :::\n\n### Step 2: Register Custom Edge\n\nUse the `register` method to register the edge type so that G6 can recognize your custom edge:\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.EDGE` indicates this is an edge type\n- Type name: `my-line-edge` is the name we give to this custom edge, which will be used in configuration later\n- Class definition: `MyLineEdge` is the edge class we just created\n\n### Step 3: Apply Custom Edge\n\nIn the graph configuration, use our custom edge by setting `edge.type`:\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom edge.\n\n## Going Further: Understanding the Principles of Edge Rendering\n\n### Atomic Graphics\n\nG6 nodes are drawn using atomic graphic units provided by the [G graphics system](https://g.antv.antgroup.com/). Here are common graphic elements and their uses:\n\n| Graphic Element | Type       | Description                                                                                                                                                                                                                                                                 |\n| --------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Circle          | `circle`   | Suitable for representing states, avatars, circular buttons, etc. Refer to SVG's [\\<circle\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/circle) element                                                                                            |\n| Ellipse         | `ellipse`  | Similar to circle, but supports scenarios with different horizontal and vertical axes. Refer to SVG's [\\<ellipse\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/ellipse) element                                                                     |\n| Image           | `image`    | Used to display icons, user avatars, LOGOs, etc. Refer to SVG's [\\<image\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image) element                                                                                                                         |\n| Line            | `line`     | Used for decoration, auxiliary connections, etc. Refer to SVG's [\\<line\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) element                                                                                                                           |\n| Path            | `path`     | Supports complex graphics such as arrows, arcs, curves, Bézier paths, etc. The path contains a set of commands and parameters with different semantics, [specific usage](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths)                                   |\n| Polygon         | `polygon`  | Supports custom graphics such as pentagrams, arrows. Refer to SVG's [\\<polygon\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon) element                                                                                                                 |\n| Polyline        | `polyline` | Multi-point polyline, suitable for complex connection structures. Refer to SVG's [\\<polyline\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline) element                                                                                                  |\n| Rectangle       | `rect`     | Most commonly used graphic, suitable as containers, cards, buttons, and other basic structures. Refer to SVG's [\\<rect\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect) element                                                                            |\n| Text            | `text`     | Displays names, descriptions, labels, and other content. Provides simple single-line/multi-line text layout capabilities, single-line supports horizontal alignment, character spacing; multi-line supports explicit line breaks and automatic wrapping, vertical alignment |\n\n> For more atomic graphics and detailed properties, please refer to [Element - Shape (Optional)](/en/manual/element/shape/overview)\n\nAll these graphics can be dynamically created or updated through `upsert()`, automatically managing graphic state and lifecycle.\n\n### Element Base Class\n\nBefore starting to customize elements, you need to understand some important properties and methods in G6 element base classes:\n\n#### Properties\n\n| Property   | Type                          | Description                                           |\n| ---------- | ----------------------------- | ----------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom elements, you will frequently use the `upsert` method. It's short for \"update or insert\", responsible for adding or updating graphics in elements:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                       |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | The key of the graphic, i.e., the corresponding key in `shapeMap`. Built-in keys include `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> The key should not use special symbols, it will be converted to camelCase to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                     |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                     |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                    |\n\nFor example, inserting a purple circle at a fixed position:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics through `container.appendChild()`? Because:\n\n1. **Better performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and rebuilding, greatly improving rendering performance\n2. **Simpler code**: No need to manually check if elements exist\n3. **Easy management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, you can easily get them through `this.getShape(key)`\n\n#### `render(attributes, container)`: Main Entry Point for Rendering Edges\n\nEvery custom edge class must implement the `render(attributes, container)` method, which defines how the edge is \"drawn\". You can use various atomic graphics here to compose the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation, or make sub-graphics interact with each other. In this case, the `getShape` method can help you get any graphic previously created through `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, you must ensure A is created first\n\n### Element Conventions\n\n- **Use Conventional Properties**\n\nCurrently conventional element properties include:\n\n- Get element size through `this.getSize()`\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` (simple mode - doesn't consider node shape, directly returns node center or nearest port center position)\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` (optimized mode - default is true, considers node shape, returns connection points on node boundary)\n\n- **Use Paired `getXxxStyle` and `drawXxxShape` Methods for Graphic Drawing**\n\n`getXxxStyle` is used to get graphic styles, `drawXxxShape` is used to draw graphics. Graphics created this way support automatic animation execution.\n\n> Where `Xxx` is the camelCase form of the key passed when calling the [upsert](#methods) method.\n\n- **Access Graph Context through `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, which you can override in custom edges to execute specific logic at key moments:\n\n| Hook Function | Trigger Time                                            | Typical Usage                                                                    |\n| ------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------- |\n| `onCreate`    | When edge creation is completed with entrance animation | Bind interaction events, initialize edge state, add external listeners           |\n| `onUpdate`    | When edge update is completed with update animation     | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | When edge completes exit animation and is destroyed     | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"rendering logic\"**.\n\nYou can define styles for each state in edge configuration:\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\nThis state will be passed to the `render()` method's `attributes`, and the merged result by the internal system will be automatically applied to the graphics.\n\nYou can also customize rendering logic based on state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## From Simple to Complex\n\n### Custom Path Polyline Edge\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Additional Labels\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/custom-edge.zh.md":"---\ntitle: 自定义边\norder: 7\n---\n\nG6 提供了多种[内置边](/manual/element/edge/base-edge)类型，包含 [line（直线边）](/manual/element/edge/line)、[polyline（折线边）](/manual/element/edge/polyline)、[quadratic（二次贝塞尔曲线边）](/manual/element/edge/quadratic)、[cubic（三次贝塞尔曲线边）](/manual/element/edge/cubic)、[cubic-horizontal（水平三次贝塞尔曲线边）](/manual/element/edge/cubic-horizontal)、[cubic-vertical（垂直三次贝塞尔曲线边）](/manual/element/edge/cubic-vertical) 等。这些内置边能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础边无法满足的需求。这时，你需要创建自定义边。别担心，这比你想象的要简单！\n\n## 开始之前：了解边的基本构成\n\n在 G6 中，一条完整的边通常由以下几个部分组成：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要形状，例如直线、折线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `arrow` ：箭头，用于表示边的方向；\n- `halo` ：主图形周围展示的光晕效果的图形。\n\n## 自定义边的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义边的方式主要有两种途径：\n\n### 1. 继承现有边类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - 最基础的边类，提供边的核心功能\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - 直线边\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - 折线边\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - 二次贝塞尔曲线边\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - 三次贝塞尔曲线边\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - 垂直三次贝塞尔曲线边\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - 水平三次贝塞尔曲线边\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有边的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有边类型（推荐），可以直接跳到 [三步创建你的第一个自定义边](#三步创建你的第一个自定义边) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有边类型都不满足需求，你可以基于 G 的底层图形系统从零创建边。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制边的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有边类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义边需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义边\n\n让我们从最基础的 `BaseEdge` 开始，实现一个自定义直线边：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义边类\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // 定义边的样式，可以添加或覆盖默认样式\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // 调用父类方法获取基础样式，然后添加自定义样式\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // 实现抽象方法：定义边的路径\n  // 这是 BaseEdge 的抽象方法，所有子类必须实现\n  protected getKeyPath(attributes) {\n    // 获取源节点和目标节点\n    const { sourceNode, targetNode } = this;\n\n    // 获取节点的位置坐标\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // 返回SVG路径数组，定义从起点到终点的直线\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=关键方法解析}\n\n- `getKeyStyle`: 定义边的基本样式，如线宽、颜色等\n- `getKeyPath`: 是 `BaseEdge` 中的抽象方法，**必须实现**，它定义了边的路径形状\n  :::\n\n### 第二步：注册自定义边\n\n使用 `register` 方法注册边类型，这样 G6 才能识别你的自定义边：\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.EDGE` 表示这是一个边类型\n- 类型名称：`my-line-edge` 是我们给这个自定义边起的名字，后续会在配置中使用\n- 类定义：`MyLineEdge` 是我们刚刚创建的边类\n\n### 第三步：应用自定义边\n\n在图的配置中，通过设置 `edge.type` 来使用我们的自定义边：\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义边。\n\n## 更进一步：理解边绘制的原理\n\n### 原子图形\n\nG6 的节点是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。以下是常见图形元素及其用途：\n\n| 图形元素 | 类型       | 描述                                                                                                                                                                        |\n| -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 圆形     | `circle`   | 适合表示状态、头像、圆形按钮等。可以参考 SVG 的 [\\<circle\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/circle) 元素                                |\n| 椭圆     | `ellipse`  | 与 circle 类似，但支持横纵轴不同的场景。可以参考 SVG 的 [\\<ellipse\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/ellipse) 元素                      |\n| 图片     | `image`    | 用于展示图标、用户头像、LOGO 等。可以参考 SVG 的 [\\<image\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/image) 元素                                           |\n| 直线     | `line`     | 用于装饰、辅助连接等。可以参考 SVG 的 [\\<line\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/line) 元素                                                        |\n| 路径     | `path`     | 支持复杂图形，如箭头、圆弧、曲线、贝塞尔路径等。路径中包含一组命令与参数，这些命令有不同的语义，[具体用法](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths) |\n| 多边形   | `polygon`  | 支持自定义图形，如五角星、箭头。可以参考 SVG 的 [\\<polygon\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polygon) 元素                                        |\n| 折线     | `polyline` | 多点折线，适合复杂的连线结构。可以参考 SVG 的 [\\<polyline\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polyline) 元素                                        |\n| 矩形     | `rect`     | 最常用图形，适合作为容器、卡片、按钮等基础结构。可以参考 SVG 的 [\\<rect\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/rect) 元素                              |\n| 文本     | `text`     | 显示名称、描述、标签等内容。提供简单的单行/多行文本排版能力，单行支持水平对齐、字符间距；多行支持显式换行符以及自动换行，垂直对齐                                           |\n\n> 更多原子图形和详细的属性请参考 [元素 - 图形（可选）](/manual/element/shape/overview)\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义元素之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义元素时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                   |\n| --------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见[元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                 |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                               |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                         |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染边的主入口\n\n每个自定义边类都必须实现 `render(attributes, container)` 方法，它定义了该边如何被“绘制”出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n目前约定的元素属性包括：\n\n- 通过 `this.getSize()` 获取元素的尺寸\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` 获取边的起点和终点（简单模式 - 不考虑节点形状，直接返回节点中心点或最近连接桩中心˝位置）\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` 获取边的起点和终点（优化模式 - 默认为 true，考虑节点形状，返回节点边界上的连接点）\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义边中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                 | 典型用途                                   |\n| ----------- | ------------------------ | ------------------------------------------ |\n| `onCreate`  | 当边创建后完成入场动画时 | 绑定交互事件、初始化边状态、添加外部监听器 |\n| `onUpdate`  | 当边更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果   |\n| `onDestroy` | 当边完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知     |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **“状态响应”** 与 **“绘制逻辑”** 分离。\n\n你可以在边配置中定义每种状态下的样式：\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## 从简单到复杂\n\n### 自定义路径的折线边\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 额外标签\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/edge/overview.en.md":"---\ntitle: Edge Overview\norder: 0\n---\n\n## What is an Edge\n\nAn edge is one of the basic elements in a graph, used to connect two nodes or combos, representing the relationship between them. In G6, edges are directional, pointing from `source` to `target`, but you can configure them to hide the arrow to represent undirected connections.\n\nYou can create edges between any two nodes, combos, or between a node and a combo, and you can express different types of relationships by creating multiple edges.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 provides the following built-in edges:\n\n- `line` Straight line edge\n- `polyline` Polyline edge\n- `quadratic` Quadratic Bezier curve edge\n- `cubic` Cubic Bezier curve edge\n- `cubicVertical` Vertical cubic Bezier curve edge\n- `cubicHorizontal` Horizontal cubic Bezier curve edge\n\n### Data Structure\n\nWhen defining an edge, you need to add an `edges` field to the graph's data object. Each edge is an object with the following structure:\n\n| Attribute | Description                                                                                                   | Type     | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source    | ID of the starting node of the edge                                                                           | string   | -       | ✓        |\n| target    | ID of the target node of the edge                                                                             | string   | -       | ✓        |\n| id        | Unique identifier of the edge                                                                                 | string   | -       |          |\n| type      | Type of edge, name of built-in edge type or custom edge, such as `line` or `polyline`                         | string   | -       |          |\n| data      | Edge data, used to store custom data of the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style     | Edge style, including visual attributes like line color, width, arrow, etc.                                   | object   | -       |          |\n| states    | Initial states of the edge                                                                                    | string[] | -       |          |\n\nAn example of a data item in the `edges` array:\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Configuration Methods\n\nThere are three ways to configure edges, listed in order of priority from high to low:\n\n- Use `graph.setEdge()` for dynamic configuration\n- Global configuration when instantiating the graph\n- Dynamic attributes in data\n\nThese configuration methods can be used simultaneously. When there are the same configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setEdge()`\n\nYou can dynamically set the style mapping logic of edges using `graph.setEdge()` after the graph instance is created.\n\nThis method needs to be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration When Instantiating the Graph\n\nYou can configure edge style mapping globally when instantiating the graph, and this configuration will take effect on all edges.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different edges, you can write the configuration into the edge data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## Custom Edges\n\nWhen built-in edges cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend built-in edges\n- Create entirely new edge types\n\nUnlike combos, custom edges need to be registered before use. For detailed tutorials, please refer to the [Custom Edge](/manual/element/edge/custom-edge) documentation.\n","packages/site/docs/manual/element/edge/overview.zh.md":"---\ntitle: 边总览\norder: 0\n---\n\n## 什么是边\n\n边（Edge）是图中的基本元素之一，用于连接两个节点或组合，表示它们之间的关系。在 G6 中，边具有方向性，从 `source` 指向 `target`，也可以通过配置隐藏箭头以表示无方向连接。\n\n你可以在任意两个节点、组合，或节点与组合之间创建边，还可以通过创建多条边来表达不同的关系类型。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 提供了以下内置边：\n\n- `line` 直线边\n- `polyline` 折线边\n- `quadratic` 二次贝塞尔曲线边\n- `cubic` 三次贝塞尔曲线边\n- `cubicVertical` 垂直三次贝塞尔曲线边\n- `cubicHorizontal` 水平三次贝塞尔曲线边\n\n### 数据结构\n\n定义边时，需要在图的数据对象中添加 `edges` 字段。每条边是一个对象，结构如下：\n\n| 属性   | 描述                                                                  | 类型     | 默认值 | 必选 |\n| ------ | --------------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                         | string   | -      | ✓    |\n| target | 边目标节点 ID                                                         | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                        | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称，比如 `line` 或者 `polyline` | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取      | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                            | object   | -      |      |\n| states | 边初始状态                                                            | string[] | -      |      |\n\n`edges` 数组中一个数据项的示例：\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 配置方法\n\n配置边的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setEdge()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setEdge()`\n\n可在图实例创建后，使用 `graph.setEdge()` 动态设置边的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `edge` 配置边样式映射，这里的配置是全局的配置，将会在所有边上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同边进行不同的配置，可以将配置写入到边数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## 自定义边\n\n当内置边无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置边进行扩展\n- 创建全新的边类型\n\n与组合不同，自定义边需要先注册后使用。详细教程请参考 [自定义边](/manual/element/edge/custom-edge) 文档。\n","packages/site/docs/manual/element/node/BaseNode.en.md":"---\ntitle: Common Node Configuration\norder: 1\n---\n\nThis document introduces the common configuration properties for built-in nodes.\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {}, // Node style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default  | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name         | [Type](#type)           | `circle` |          |\n| style     | Node style configuration, including color, size, etc.          | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                       | [State](#state)         | -        |          |\n| palette   | Define node palette for mapping colors based on different data | [Palette](#palette)     | -        |          |\n| animation | Define animation effects for nodes                             | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the node type, built-in node type name or custom node name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: The `type` property also supports dynamic configuration, allowing you to dynamically select node types based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Node](/en/manual/element/node/circle)\n- `diamond`: [Diamond Node](/en/manual/element/node/diamond)\n- `donut`: [Donut Node](/en/manual/element/node/donut)\n- `ellipse`: [Ellipse Node](/en/manual/element/node/ellipse)\n- `hexagon`: [Hexagon Node](/en/manual/element/node/hexagon)\n- `html`: [HTML Node](/en/manual/element/node/html)\n- `image`: [Image Node](/en/manual/element/node/image)\n- `rect`: [Rectangle Node](/en/manual/element/node/rect)\n- `star`: [Star Node](/en/manual/element/node/star)\n- `triangle`: [Triangle Node](/en/manual/element/node/triangle)\n\n## Style\n\nDefines the style of nodes, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Node: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the node data object (`NodeData`), containing all data information of the node.\n\nA complete node consists of the following parts:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the node, representing the primary shape of the node, such as rectangle, circle, etc.\n- `label`: Text label, usually used to display the name or description of the node\n- `icon`: Icon graphic, usually used to display node icons, can be images or text icons\n- `badge`: Badge, by default located at the top-right corner of the node\n- `halo`: Graphic showing halo effect around the main graphic\n- `port`: Connection points on the node, used to connect edges\n\nThe following style configurations are explained in order by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the node, defining the basic shape and appearance of the node. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSetting the basic appearance of nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdding transparency and shadow effects to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreating nodes with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete main graphic style configuration is as follows:\n\n| Property                        | Description                                                                                                                                      | Type                          | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current node/combo is collapsed                                                                                                      | boolean                       | false     |          |\n| cursor                          | Node mouse hover style, [options](#cursor)                                                                                                       | string                        | default   |          |\n| fill                            | Node fill color                                                                                                                                  | string                        | `#1783FF` |          |\n| fillOpacity                     | Node fill color transparency                                                                                                                     | number \\| string              | 1         |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick up | number                        | 0         |          |\n| lineCap                         | Node stroke end style                                                                                                                            | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Node stroke dash style                                                                                                                           | number[]                      | -         |          |\n| lineDashOffset                  | Node stroke dash offset                                                                                                                          | number                        | -         |          |\n| lineJoin                        | Node stroke join style                                                                                                                           | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Node stroke width                                                                                                                                | number                        | 1         |          |\n| opacity                         | Node transparency                                                                                                                                | number \\| string              | 1         |          |\n| pointerEvents                   | How the node responds to pointer events, [options](#pointerevents)                                                                               | string                        | `auto`    |          |\n| shadowBlur                      | Node shadow blur                                                                                                                                 | number                        | -         |          |\n| shadowColor                     | Node shadow color                                                                                                                                | string                        | -         |          |\n| shadowOffsetX                   | Node shadow offset in x-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowOffsetY                   | Node shadow offset in y-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowType                      | Node shadow type                                                                                                                                 | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Node size, quick setting for node width and height, [options](#size)                                                                             | number \\| number[]            | 32        |          |\n| stroke                          | Node stroke color                                                                                                                                | string                        | `#000`    |          |\n| strokeOpacity                   | Node stroke color transparency                                                                                                                   | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given node                                                                 | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                                   | string                        | -         |          |\n| visibility                      | Whether the node is visible                                                                                                                      | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Node x coordinate                                                                                                                                | number                        | 0         |          |\n| y                               | Node y coordinate                                                                                                                                | number                        | 0         |          |\n| z                               | Node z coordinate                                                                                                                                | number                        | 0         |          |\n| zIndex                          | Node rendering level                                                                                                                             | number                        | 0         |          |\n\n#### Size\n\nNode size, quick setting for node width and height, supports three configuration methods:\n\n- number: Indicates that the node width and height are the same as the specified value\n- [number, number]: Indicates that the node width and height are represented by array elements indicating the node's width and height respectively\n- [number, number, number]: Indicates that the node width, height, and depth are represented by array elements\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. You can refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be a target for responding to events\n- **`visiblepainted`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n- **`visiblestroke`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n- **`visible`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by the values of `fill` and `stroke`\n- **`painted`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by the value of `visibility`\n- **`fill`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n  - Not affected by the value of `visibility`\n- **`stroke`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n  - Not affected by the value of `visibility`\n- **`all`**: Will respond to events as long as entering the fill and stroke areas of the graphic, not affected by the values of `fill`, `stroke`, and `visibility`\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely unresponsive to events\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // Node does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Style\n\nLabels are used to display text information of nodes, supporting various style configurations and layout methods. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Node Name',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'This is a very long node name that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdding background to labels to improve readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Important Node',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete label style configuration is as follows:\n\n| Property                 | Description                                                                                                                        | Type                                                                        | Default   | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to display node label                                                                                                      | boolean                                                                     | true      |          |\n| labelCursor              | Style displayed when mouse hovers over node label, [options](#cursor)                                                              | string                                                                      | `default` |          |\n| labelFill                | Node label text color                                                                                                              | string                                                                      | -         |          |\n| labelFontFamily          | Node label font family                                                                                                             | string                                                                      | -         |          |\n| labelFontSize            | Node label font size                                                                                                               | number                                                                      | 12        |          |\n| labelFontStyle           | Node label font style                                                                                                              | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Node label font variant                                                                                                            | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Node label font weight                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                                       | number                                                                      | 0         |          |\n| labelLetterSpacing       | Node label letter spacing                                                                                                          | number \\| string                                                            | -         |          |\n| labelLineHeight          | Node label line height                                                                                                             | number \\| string                                                            | -         |          |\n| labelMaxLines            | Maximum number of lines for node label                                                                                             | number                                                                      | 1         |          |\n| labelMaxWidth            | Maximum width of node label, [options](#labelmaxwidth)                                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Node label offset in x-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelOffsetY             | Node label offset in y-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelPadding             | Node label padding                                                                                                                 | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Position of node label relative to node main graphic, [options](#labelplacement)                                                   | string                                                                      | `bottom`  |          |\n| labelText                | Node label text content                                                                                                            | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Node label text horizontal alignment                                                                                               | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Node label text baseline                                                                                                           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Node label text decoration line color                                                                                              | string                                                                      | -         |          |\n| labelTextDecorationLine  | Node label text decoration line                                                                                                    | string                                                                      | -         |          |\n| labelTextDecorationStyle | Node label text decoration line style                                                                                              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Node label text overflow handling                                                                                                  | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Node label text path                                                                                                               | Path                                                                        | -         |          |\n| labelWordWrap            | Whether node label enables automatic line wrapping. After enabling labelWordWrap, parts exceeding labelMaxWidth wrap automatically | boolean                                                                     | false     |          |\n| labelZIndex              | Node label rendering level                                                                                                         | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nAvailable values: `left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text wraps when exceeding this width:\n\n- string: Defines maximum width as a percentage relative to node width. For example, `50%` means label width does not exceed half of the node width\n- number: Defines maximum width in pixels. For example, 100 means the maximum width of the label is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background is used to display the background of node labels:\n\n| Property                      | Description                                                                                                                                                                         | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to display node label background                                                                                                                                            | boolean                                  | false     |\n| labelBackgroundCursor         | Node label background mouse hover style, [options](#cursor)                                                                                                                         | string                                   | `default` |\n| labelBackgroundFill           | Node label background fill color                                                                                                                                                    | string                                   | -         |\n| labelBackgroundFillOpacity    | Node label background transparency                                                                                                                                                  | number                                   | 1         |\n| labelBackgroundHeight         | Node label background height                                                                                                                                                        | string \\| number                         | -         |\n| labelBackgroundLineDash       | Node label background dash configuration                                                                                                                                            | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Node label background dash offset                                                                                                                                                   | number                                   | -         |\n| labelBackgroundLineWidth      | Node label background stroke line width                                                                                                                                             | number                                   | -         |\n| labelBackgroundRadius         | Node label background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Node label background shadow blur degree                                                                                                                                            | number                                   | -         |\n| labelBackgroundShadowColor    | Node label background shadow color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Node label background shadow X direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Node label background shadow Y direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundStroke         | Node label background stroke color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Node label background stroke transparency                                                                                                                                           | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Whether node label background is visible                                                                                                                                            | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Node label background rendering level                                                                                                                                               | number                                   | 1         |\n\n### Halo Style\n\nHalo is an effect displayed around the node's main graphic, usually used for highlighting or indicating special states of nodes.\n\n#### Basic Halo Effect\n\nAdding basic halo effect to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete halo style configuration is as follows:\n\n| Property          | Description                                                                                                                   | Type                   | Default                                 | Required |\n| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------------------------------------- | -------- |\n| halo              | Whether to display node halo                                                                                                  | boolean                | false                                   |          |\n| haloCursor        | Node halo mouse hover style, [options](#cursor)                                                                               | string                 | `default`                               |          |\n| haloDraggable     | Whether node halo allows dragging                                                                                             | boolean                | true                                    |          |\n| haloDroppable     | Whether node halo allows receiving dragged elements                                                                           | boolean                | true                                    |          |\n| haloFillRule      | Node halo fill rule                                                                                                           | `nonzero` \\| `evenodd` | -                                       |          |\n| haloFilter        | Node halo filter                                                                                                              | string                 | -                                       |          |\n| haloLineWidth     | Node halo stroke width                                                                                                        | number                 | 3                                       |          |\n| haloPointerEvents | Whether node halo effect responds to pointer events, [options](#pointerevents)                                                | string                 | `none`                                  |          |\n| haloStroke        | Node halo stroke color, **this property is used to set the color of the halo around the node, helping to highlight the node** | string                 | Consistent with main graphic fill color |          |\n| haloStrokeOpacity | Node halo stroke color transparency                                                                                           | number                 | 0.25                                    |          |\n| haloVisibility    | Node halo visibility                                                                                                          | `visible` \\| `hidden`  | `visible`                               |          |\n| haloZIndex        | Node halo rendering level                                                                                                     | number                 | -1                                      |          |\n\n### Icon Style\n\nNode icons support three common usage methods: text icons, image icons, and IconFont icons. The configurations for these three methods are shown below:\n\n#### 1. Text Icons\n\nUsing text directly as icons, suitable for simple identifiers:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // Icon text content\n      iconFill: '#C41D7F', // Deep pink icon\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. Image Icons\n\nUsing images as icons, supporting various image formats:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont Icons\n\nUsing IconFont font icons, you need to import the corresponding font files first:\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // Light blue background\n      stroke: '#1890FF', // Blue border\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete icon style configuration is as follows:\n\n| Property                | Description                                          | Type                                                                        | Default                     |\n| ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to display node icon                         | boolean                                                                     | true                        |\n| iconFill                | Node icon text color                                 | string                                                                      | -                           |\n| iconFontFamily          | Node icon font family                                | string                                                                      | -                           |\n| iconFontSize            | Node icon font size                                  | number                                                                      | 16                          |\n| iconFontStyle           | Node icon font style                                 | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Node icon font variant                               | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Node icon font weight                                | number \\| string                                                            | `normal`                    |\n| iconHeight              | Node icon height                                     | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Node icon text letter spacing                        | number \\| string                                                            | -                           |\n| iconLineHeight          | Node icon text line height                           | number \\| string                                                            | -                           |\n| iconMaxLines            | Maximum lines for node icon text                     | number                                                                      | 1                           |\n| iconRadius              | Node icon border radius                              | number                                                                      | 0                           |\n| iconSrc                 | Node image source. Has higher priority than iconText | string                                                                      | -                           |\n| iconText                | Node icon text                                       | string                                                                      | -                           |\n| iconTextAlign           | Node icon text horizontal alignment                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`                      |\n| iconTextBaseline        | Node icon text baseline                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`                |\n| iconTextDecorationColor | Node icon text decoration line color                 | string                                                                      | -                           |\n| iconTextDecorationLine  | Node icon text decoration line                       | string                                                                      | -                           |\n| iconTextDecorationStyle | Node icon text decoration line style                 | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Node icon text overflow handling                     | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconWidth               | Node icon width                                      | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether node icon text automatically wraps           | boolean                                                                     | -                           |\n\n### Badge Style\n\nBadges are small markers displayed on nodes, usually used to show status, quantity, or other auxiliary information. Supports displaying multiple badges simultaneously with customizable positions.\n\n#### Single Badge\n\nAdding a simple badge to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Default display at the top\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdding multiple badges at different positions to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // Whether to display badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background color palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nCompletely customizing badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete badge style configuration is as follows:\n\n| Property     | Description                      | Type                                  | Default                           |\n| ------------ | -------------------------------- | ------------------------------------- | --------------------------------- |\n| badge        | Whether the node displays badges | boolean                               | true                              |\n| badgePalette | Badge background color palette   | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Node badge settings              | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                                         | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether node badge displays background                                                                                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Node badge background mouse hover style, [options](#cursor)                                                                                                                                                                                                                                                         | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Node badge background fill color. If not specified, badgePalette is considered for allocation in order                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Node badge background fill transparency                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Node badge background filter                                                                                                                                                                                                                                                                                        | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Node badge background height                                                                                                                                                                                                                                                                                        | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Node badge background dash configuration                                                                                                                                                                                                                                                                            | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Node badge background dash offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Node badge background stroke line width                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Node badge background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, separated by spaces | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Node badge background shadow blur degree                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Node badge background shadow color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Node badge background shadow X direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Node badge background shadow Y direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Node badge background stroke color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Node badge background stroke transparency                                                                                                                                                                                                                                                                           | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether node badge background is visible                                                                                                                                                                                                                                                                            | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | Node badge background rendering level                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| fill                     | Node badge text color                                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| fontFamily               | Node badge font family                                                                                                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| fontSize                 | Node badge font size                                                                                                                                                                                                                                                                                                | number                                                                                                                                                                 | 8            |\n| fontStyle                | Node badge font style                                                                                                                                                                                                                                                                                               | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Node badge font variant                                                                                                                                                                                                                                                                                             | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Node badge font weight                                                                                                                                                                                                                                                                                              | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Node badge line height                                                                                                                                                                                                                                                                                              | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Node badge line width                                                                                                                                                                                                                                                                                               | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Maximum lines for node badge text                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 1            |\n| offsetX                  | Node badge offset in x-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| offsetY                  | Node badge offset in y-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| padding                  | Node badge padding                                                                                                                                                                                                                                                                                                  | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Position of node badge relative to node main graphic. If not specified, defaults to clockwise arrangement starting from top-right corner                                                                                                                                                                            | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Node badge text content                                                                                                                                                                                                                                                                                             | string                                                                                                                                                                 | -            |\n| textAlign                | Node badge text horizontal alignment                                                                                                                                                                                                                                                                                | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Node badge text baseline                                                                                                                                                                                                                                                                                            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Node badge text decoration line color                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Node badge text decoration line                                                                                                                                                                                                                                                                                     | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Node badge text decoration line style                                                                                                                                                                                                                                                                               | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Node badge text overflow handling                                                                                                                                                                                                                                                                                   | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether node badge is visible                                                                                                                                                                                                                                                                                       | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether node badge text automatically wraps                                                                                                                                                                                                                                                                         | boolean                                                                                                                                                                | -            |\n| zIndex                   | Node badge rendering level                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                 | 3            |\n\n### Port Style\n\nPorts are connection points on nodes, used to connect edges. Supports adding multiple ports at different positions on nodes with customizable styles.\n\n#### Basic Ports\n\nAdding four basic directional ports to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Position Ports\n\nUsing percentages or absolute coordinates to precisely position ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // Relative position: 20% from top-left\n        { key: 'custom2', placement: [0.8, 0] }, // Relative position: 80% from top-right\n        { key: 'custom3', placement: [1, 0.5] }, // Relative position: right center\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Differentiated Port Styles\n\nSetting different styles for different ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // Green input port\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // Red output port\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // Unified stroke color\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete port style configuration is as follows:\n\n| Property | Description                                                  | Type                                | Default | Required |\n| -------- | ------------------------------------------------------------ | ----------------------------------- | ------- | -------- |\n| port     | Whether the node displays ports                              | boolean                             | true    |          |\n| ports    | Node port configuration, supports configuring multiple ports | [PortStyleProps](#portstyleprops)[] | -       |          |\n\n#### PortStyleProps\n\n| Property          | Description                                                                                                                                                                                                                                                  | Type                                                                                                                                                                                                   | Default   | Required |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- |\n| key               | Key value of node port, defaults to the index of the node port                                                                                                                                                                                               | string                                                                                                                                                                                                 | -         |          |\n| placement         | Position of node port relative to node main graphic                                                                                                                                                                                                          | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓        |\n| r                 | Node port radius <br> - If set to undefined, the port is treated as a point, not displayed on canvas but exists, edges will preferentially connect to the nearest port <br> - If set to a number, the port is treated as a circle with radius specified here | number                                                                                                                                                                                                 | -         |          |\n| linkToCenter      | Whether edges connect to the center of the node port <br> - If true, edges connect to the center of the node port <br> - If false, edges connect to the edge of the node port                                                                                | boolean                                                                                                                                                                                                | false     |          |\n| cursor            | Node port mouse hover style, [options](#cursor)                                                                                                                                                                                                              | string                                                                                                                                                                                                 | `default` |          |\n| fill              | Node port fill color                                                                                                                                                                                                                                         | string                                                                                                                                                                                                 | -         |          |\n| fillOpacity       | Node port fill transparency                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | 1         |          |\n| isBillboard       | Whether node port has Billboard effect                                                                                                                                                                                                                       | boolean                                                                                                                                                                                                | -         |          |\n| isSizeAttenuation | Whether node port enables size attenuation                                                                                                                                                                                                                   | boolean                                                                                                                                                                                                | -         |          |\n| lineDash          | Node port stroke dash configuration                                                                                                                                                                                                                          | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |          |\n| lineDashOffset    | Node port stroke dash offset                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| lineWidth         | Node port stroke line width                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | -         |          |\n| shadowBlur        | Node port shadow blur degree                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| shadowColor       | Node port shadow color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| shadowOffsetX     | Node port shadow X direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| shadowOffsetY     | Node port shadow Y direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| stroke            | Node port stroke color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| strokeOpacity     | Node port stroke transparency                                                                                                                                                                                                                                | number \\| string                                                                                                                                                                                       | 1         |          |\n| visibility        | Whether node port is visible                                                                                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |          |\n| zIndex            | Node port rendering level                                                                                                                                                                                                                                    | number                                                                                                                                                                                                 | 2         |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select a node or hovering to activate an edge, only certain state identifications are made on the element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of the graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\nFor example, when a node is in the `focus` state, you can add a stroke with width 3 and orange color.\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefines animation effects for nodes, supporting the following two configuration methods:\n\n1. Disable all node animations\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when nodes enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when nodes enter the canvas\n- `update`: Animation when nodes are updated\n- `exit`: Animation when nodes leave the canvas\n- `show`: Animation when nodes are shown from hidden state\n- `hide`: Animation when nodes are hidden\n- `collapse`: Animation when nodes are collapsed\n- `expand`: Animation when nodes are expanded\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure nodes, such as:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // Only animate x and y properties during updates\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable animations for specific stages:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // Disable node entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefines the color palette for nodes, i.e., predefined node color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For the definition of palettes, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to id as the grouping field                    | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify the current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                 | `group` \\| `value`            | `group` |\n\nFor example, assigning node colors to a group of data by `category` field, so that nodes of the same category have the same color:\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau is the palette name, defaults to assigning colors based on ID\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/BaseNode.zh.md":"---\ntitle: 节点通用配置项\norder: 1\n---\n\n本文介绍内置节点通用属性配置。\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {}, // 节点样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](#type)           | `circle` |      |\n| style     | 节点样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定节点类型，内置节点类型名称或自定义节点的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据节点数据动态选择节点类型：\n\n```js\nconst graph = new Graph({\n  node: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形节点](/manual/element/node/circle)\n- `diamond`：[菱形节点](/manual/element/node/diamond)\n- `donut`：[甜甜圈节点](/manual/element/node/donut)\n- `ellipse`：[椭圆节点](/manual/element/node/ellipse)\n- `hexagon`：[六边形节点](/manual/element/node/hexagon)\n- `html`：[HTML 节点](/manual/element/node/html)\n- `image`：[图片节点](/manual/element/node/image)\n- `rect`：[矩形节点](/manual/element/node/rect)\n- `star`：[星形节点](/manual/element/node/star)\n- `triangle`：[三角形节点](/manual/element/node/triangle)\n\n## Style\n\n定义节点的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据节点数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `节点: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为节点数据对象 (`NodeData`)，包含节点的所有数据信息。\n\n一个完整的节点由以下几部分构成：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：节点的主图形，表示节点的主要形状，例如矩形、圆形等；\n- `label` ：文本标签，通常用于展示节点的名称或描述；\n- `icon` ：图标图形，通常用于展示节点的图标，可以是图片或者文本图标；\n- `badge` ：默认位于节点右上角的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `port` ：节点上的连接点，用于连接边。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是节点的核心部分，定义了节点的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置节点的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为节点添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的节点：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前节点/组合是否折叠                                                                     | boolean                       | false     |      |\n| cursor                          | 节点鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 节点填充色                                                                                | string                        | `#1783FF` |      |\n| fillOpacity                     | 节点填充色透明度                                                                          | number \\| string              | 1         |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 节点描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 节点描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 节点描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 节点描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 节点描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 节点透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 节点如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 节点阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 节点阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 节点阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 节点阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 节点阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 节点大小，快捷设置节点宽高，[配置项](#size)                                               | number \\| number[]            | 32        |      |\n| stroke                          | 节点描边色                                                                                | string                        | `#000`    |      |\n| strokeOpacity                   | 节点描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定节点                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 节点是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 节点 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 节点 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 节点 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 节点渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n节点大小，快捷设置节点宽高，支持三种配置方式：\n\n- number：表示节点宽高相同为指定值\n- [number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度\n- [number, number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // 节点不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示节点的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '节点名称',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '这是一个很长的节点名称需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '重要节点',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                               | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示节点标签                                                                   | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入节点标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 节点标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 节点标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 节点标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 节点标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 节点标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 节点标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                             | number                                                                      | 0         |      |\n| labelLetterSpacing       | 节点标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 节点标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 节点标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 节点标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 节点标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 节点标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 节点标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 节点标签相对于节点主图形的位置，[配置项](#labelplacement)                          | string                                                                      | `bottom`  |      |\n| labelText                | 节点标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 节点标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 节点标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 节点标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 节点标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 节点标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 节点标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 节点标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 节点标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 节点标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n可选值有：`left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于节点宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过节点宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示节点标签的背景：\n\n| 属性                          | 描述                                                                                                           | 类型                                     | 默认值    |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | 节点标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 节点标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 节点标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 节点标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 节点标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 节点标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 节点标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 节点标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 节点标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 节点标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 节点标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 节点标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 节点标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 节点标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 节点标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 节点标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 节点标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕节点主图形显示的效果，通常用于高亮显示或表示节点的特殊状态。\n\n#### 基础光晕效果\n\n为节点添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                                   | 类型                   | 默认值                       | 必选 |\n| ----------------- | ---------------------------------------------------------------------- | ---------------------- | ---------------------------- | ---- |\n| halo              | 节点光晕是否显示                                                       | boolean                | false                        |      |\n| haloCursor        | 节点光晕鼠标移入样式，[配置项](#cursor)                                | strig                  | `default`                    |      |\n| haloDraggable     | 节点光晕是否允许拖拽                                                   | boolean                | true                         |      |\n| haloDroppable     | 节点光晕是否允许接收被拖拽的元素                                       | boolean                | true                         |      |\n| haloFillRule      | 节点光晕填充规则                                                       | `nonzero` \\| `evenodd` | -                            |      |\n| haloFilter        | 节点光晕滤镜                                                           | string                 | -                            |      |\n| haloLineWidth     | 节点光晕描边宽度                                                       | number                 | 3                            |      |\n| haloPointerEvents | 节点光晕效果是否响应指针事件，[配置项](#pointerevents)                 | string                 | `none`                       |      |\n| haloStroke        | 节点光晕描边色，**此属性用于设置节点周围光晕的颜色，帮助突出显示节点** | string                 | 与主图形的填充色 `fill` 一致 |      |\n| haloStrokeOpacity | 节点光晕描边色透明度                                                   | number                 | 0.25                         |      |\n| haloVisibility    | 节点光晕可见性                                                         | `visible` \\| `hidden`  | `visible`                    |      |\n| haloZIndex        | 节点光晕渲染层级                                                       | number                 | -1                           |      |\n\n### 图标样式\n\n节点图标支持三种常见的使用方式：文字图标、图片图标和 IconFont 图标。下面分别展示这三种方式的配置：\n\n#### 1. 文字图标\n\n直接使用文字作为图标，适合简单的标识：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // 图标文字内容\n      iconFill: '#C41D7F', // 深粉色图标\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. 图片图标\n\n使用图片作为图标，支持各种图片格式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont 图标\n\n使用 IconFont 字体图标，需要先引入相应的字体文件：\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // 淡蓝色背景\n      stroke: '#1890FF', // 蓝色边框\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                | 类型                                                                        | 默认值           |\n| ----------------------- | ----------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示节点图标                    | boolean                                                                     | true             |\n| iconFill                | 节点图标文字颜色                    | string                                                                      | -                |\n| iconFontFamily          | 节点图标字体族                      | string                                                                      | -                |\n| iconFontSize            | 节点图标字体大小                    | number                                                                      | 16               |\n| iconFontStyle           | 节点图标字体样式                    | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 节点图标字体变种                    | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 节点图标字体粗细                    | number \\| string                                                            | `normal`         |\n| iconHeight              | 节点图标高度                        | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 节点图标文本字间距                  | number \\| string                                                            | -                |\n| iconLineHeight          | 节点图标文本行高                    | number \\| string                                                            | -                |\n| iconMaxLines            | 节点图标文本最大行数                | number                                                                      | 1                |\n| iconRadius              | 节点图标圆角半径                    | number                                                                      | 0                |\n| iconSrc                 | 节点图片来源。其优先级高于 iconText | string \\| ((datum) => string)                                                | -                |\n| iconText                | 节点图标文字                        | string \\| ((datum) => string)                                               | -                |\n| iconTextAlign           | 节点图标文本水平对齐方式            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`           |\n| iconTextBaseline        | 节点图标文本基线                    | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`     |\n| iconTextDecorationColor | 节点图标文本装饰线颜色              | string                                                                      | -                |\n| iconTextDecorationLine  | 节点图标文本装饰线                  | string                                                                      | -                |\n| iconTextDecorationStyle | 节点图标文本装饰线样式              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 节点图标文本溢出处理方式            | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconWidth               | 节点图标宽度                        | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 节点图标文本是否自动换行            | boolean                                                                     | -                |\n\n### 徽标样式\n\n徽标是节点上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为节点添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为节点添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 节点是否显示徽标   | boolean                               | true                              |\n| badgePalette | 节点徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 节点徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 节点徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 节点徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 节点徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 节点徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 节点徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 节点徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 节点徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 节点徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 节点徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 节点徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 节点徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 节点徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 节点徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 节点徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 节点徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 节点徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 节点徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | 节点徽标背景渲染层级                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| fill                     | 节点徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 节点徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 节点徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 节点徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 节点徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 节点徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 节点徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 节点徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 节点徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 节点徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 节点徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 节点徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 节点徽标相对于节点主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 节点徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 节点徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 节点徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 节点徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 节点徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 节点徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 节点徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 节点徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 节点徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 节点徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 连接桩样式\n\n连接桩是节点上的连接点，用于连接边。支持在节点的不同位置添加多个连接桩，并可自定义样式。\n\n#### 基础连接桩\n\n为节点添加四个基本方向的连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义位置连接桩\n\n使用百分比或绝对坐标精确定位连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // 相对位置：左上角20%处\n        { key: 'custom2', placement: [0.8, 0] }, // 相对位置：右上角80%处\n        { key: 'custom3', placement: [1, 0.5] }, // 相对位置：右边中央\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 差异化连接桩样式\n\n为不同的连接桩设置不同的样式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // 绿色输入桩\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // 红色输出桩\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // 统一的描边颜色\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的连接桩样式配置：\n\n| 属性  | 描述                                 | 类型                                | 默认值 | 必选 |\n| ----- | ------------------------------------ | ----------------------------------- | ------ | ---- |\n| port  | 节点是否显示连接桩                   | boolean                             | true   |      |\n| ports | 节点连接桩配置项，支持配置多个连接桩 | [PortStyleProps](#portstyleprops)[] |        |      |\n\n#### PortStyleProps\n\n| 属性              | 描述                                                                                                                                                                               | 类型                                                                                                                                                                                                   | 默认值    | 必选 |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ---- |\n| key               | 节点连接桩的键值，默认为节点连接桩的索引                                                                                                                                           | string                                                                                                                                                                                                 | -         |      |\n| placement         | 节点连接桩相对于节点主图形的位置                                                                                                                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓    |\n| r                 | 节点连接桩半径 <br> - 如果设置为 undefined，则连接桩被视为一个点，不在画布上显示但存在，边会优先连接到最近的连接桩 <br> - 如果设置为数字，则连接桩被视为一个圆，圆的半径由此处指定 | number                                                                                                                                                                                                 | -         |      |\n| linkToCenter      | 边是否连接到节点连接桩的中心 <br> - 若为 true，则边连接到节点连接桩的中心 <br> - 若为 false，则边连接到节点连接桩的边缘                                                            | boolean                                                                                                                                                                                                | false     |      |\n| cursor            | 节点连接桩鼠标移入样式，[配置项](#cursor)                                                                                                                                          | string                                                                                                                                                                                                 | `default` |      |\n| fill              | 节点连接桩填充颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| fillOpacity       | 节点连接桩填充透明度                                                                                                                                                               | number                                                                                                                                                                                                 | 1         |      |\n| isBillboard       | 节点连接桩是否为Billboard 效果                                                                                                                                                     | boolean                                                                                                                                                                                                | -         |      |\n| isSizeAttenuation | 节点连接桩是否启用大小衰减                                                                                                                                                         | boolean                                                                                                                                                                                                | -         |      |\n| lineDash          | 节点连接桩描边虚线配置                                                                                                                                                             | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |      |\n| lineDashOffset    | 节点连接桩描边虚线偏移量                                                                                                                                                           | number                                                                                                                                                                                                 | -         |      |\n| lineWidth         | 节点连接桩描边线宽                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |      |\n| shadowBlur        | 节点连接桩阴影模糊程度                                                                                                                                                             | number                                                                                                                                                                                                 | -         |      |\n| shadowColor       | 节点连接桩阴影颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| shadowOffsetX     | 节点连接桩阴影 X 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| shadowOffsetY     | 节点连接桩阴影 Y 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| stroke            | 节点连接桩描边颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| strokeOpacity     | 节点连接桩描边透明度                                                                                                                                                               | number \\| string                                                                                                                                                                                       | 1         |      |\n| visibility        | 节点连接桩是否可见                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |      |\n| zIndex            | 节点连接桩渲染层级                                                                                                                                                                 | number                                                                                                                                                                                                 | 2         |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个节点或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\n例如，当节点处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义节点的动画效果，支持下列两种配置方式：\n\n1. 关闭节点全部动画\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指节点在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 节点进入画布时的动画\n- `update`: 节点更新时的动画\n- `exit`: 节点离开画布时的动画\n- `show`: 节点从隐藏状态显示时的动画\n- `hide`: 节点隐藏时的动画\n- `collapse`: 节点收起时的动画\n- `expand`: 节点展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置节点，如：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // 关闭节点入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义节点的色板，即预定义节点颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `category` 字段分配节点颜色，使得同类别的节点颜色相同：\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Circle.en.md":"---\ntitle: Circle Node\norder: 2\n---\n\n## Overview\n\nA circle is a symmetrical geometric shape with a uniform radius.\n\nApplicable scenarios:\n\n- Used to represent the size or weight of a node (controlled by radius).\n- Suitable for representing non-directional relationships, such as user nodes in social networks.\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node))\n\n## Example\n\n### Built-in Circle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Circle.zh.md":"---\ntitle: 圆形节点 Circle\norder: 2\n---\n\n## 概述\n\n圆形是一个对称的几何形状，具有均匀的半径。\n\n适用场景：\n\n- 用于表示节点的大小或权重（通过半径控制）。\n- 适合表示无方向性的关系，如社交网络中的用户节点。\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见[BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Diamond.en.md":"---\ntitle: Diamond Node\norder: 3\n---\n\n## Overview\n\nA diamond is a geometric shape with four equal sides and diagonal symmetry.\n\nApplicable scenarios:\n\n- Used to represent decision nodes, conditional judgments, or critical paths.\n\n- Suitable for representing decision nodes or key steps in flowcharts.\n\n- Commonly used in flowcharts, decision trees, network diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Diamond Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Diamond.zh.md":"---\ntitle: 菱形节点 Diamond\norder: 3\n---\n\n## 概述\n\n菱形是一个四边相等的几何形状，具有对角线对称性。\n\n适用场景：\n\n- 用于表示决策节点、条件判断或关键路径。\n\n- 适合表示流程图中的判断节点或关键步骤。\n\n- 常用于流程图、决策树、网络图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置菱形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Donut.en.md":"---\ntitle: Donut Node\norder: 4\n---\n\n## Overview\n\nThe donut node is a ring-shaped geometric figure composed of two concentric circles.\n\nApplicable scenarios:\n\n- Used to represent proportional data, such as completion progress and ratio analysis.\n\n- Suitable for representing multi-layered data, such as nested ring charts.\n\n- Commonly used in data visualization, dashboards, progress charts, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute           | Description                         | Type                                    | Default   | Required |\n| ------------------- | ----------------------------------- | --------------------------------------- | --------- | -------- |\n| donutFill           | Fill color                          | string                                  | `#1783FF` |          |\n| donutFillOpacity    | Fill color opacity                  | number \\| string                        | 1         |          |\n| donutLineCap        | Stroke end style                    | `round` \\| `square` \\| `butt`           | `butt`    |          |\n| donutLineDash       | Stroke dash style                   | number[]                                | -         |          |\n| donutLineDashOffset | Stroke dash offset                  | number                                  | -         |          |\n| donutLineJoin       | Stroke join style                   | `round` \\| `bevel` \\| `miter`           | `miter`   |          |\n| donutLineWidth      | Stroke width                        | number                                  | 1         |          |\n| donutOpacity        | Opacity                             | number \\| string                        | 1         |          |\n| donutPalette        | Color or palette name               | string \\| string[]                      | `tableau` |          |\n| donuts              | Donut data                          | number[] \\| [DonutRound](#donutround)[] | -         |          |\n| donutShadowBlur     | Shadow blur                         | number                                  | -         |          |\n| donutShadowColor    | Shadow color                        | string                                  | -         |          |\n| donutShadowOffsetX  | Shadow offset in x-axis direction   | number \\| string                        | -         |          |\n| donutShadowOffsetY  | Shadow offset in y-axis direction   | number \\| string                        | -         |          |\n| donutShadowType     | Shadow type                         | `inner` \\| `outer`                      | `outer`   |          |\n| donutStroke         | Stroke color                        | string                                  | `#000`    |          |\n| donutStrokeOpacity  | Stroke color opacity                | number \\| string                        | 1         |          |\n| donutVisibility     | Visibility of the shape             | `visible` \\| `hidden`                   | `visible` |          |\n| innerR              | Inner ring radius, percentage or px | string \\| number                        | 50%       |          |\n\n### DonutRound\n\n| Attribute      | Description                       | Type                          | Default   | Required |\n| -------------- | --------------------------------- | ----------------------------- | --------- | -------- |\n| color          | Color                             | string                        | -         |          |\n| fill           | Fill color                        | string                        | `#1783FF` |          |\n| fillOpacity    | Fill color opacity                | number \\| string              | 1         |          |\n| lineCap        | Stroke end style                  | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash       | Stroke dash style                 | number[]                      | -         |          |\n| lineDashOffset | Stroke dash offset                | number                        | -         |          |\n| lineJoin       | Stroke join style                 | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth      | Stroke width                      | number                        | 1         |          |\n| opacity        | Opacity                           | number \\| string              | 1         |          |\n| shadowBlur     | Shadow blur                       | number                        | -         |          |\n| shadowColor    | Shadow color                      | string                        | -         |          |\n| shadowOffsetX  | Shadow offset in x-axis direction | number \\| string              | -         |          |\n| shadowOffsetY  | Shadow offset in y-axis direction | number \\| string              | -         |          |\n| shadowType     | Shadow type                       | `inner` \\| `outer`            | `outer`   |          |\n| stroke         | Stroke color                      | string                        | `#000`    |          |\n| strokeOpacity  | Stroke color opacity              | number \\| string              | 1         |          |\n| value          | Value for ratio calculation       | number                        | -         | ✓        |\n| visibility     | Visibility of the shape           | `visible` \\| `hidden`         | `visible` |          |\n\n## Example\n\n### Built-in Donut Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Donut.zh.md":"---\ntitle: 甜甜圈节点 Donut\norder: 4\n---\n\n## 概述\n\n甜甜圈节点是一个环形几何形状，由内外两个同心圆组成。\n\n适用场景：\n\n- 用于表示比例数据，如完成进度、占比分析。\n\n- 适合表示多层数据，如嵌套的环形图。\n\n- 常用于数据可视化、仪表盘、进度图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性                | 描述                           | 类型                                        | 默认值    | 必选 |\n| ------------------- | ------------------------------ | ------------------------------------------- | --------- | ---- |\n| donutFill           | 填充色                         | string                                      | `#1783FF` |      |\n| donutFillOpacity    | 填充色透明度                   | number \\| string                            | 1         |      |\n| donutLineCap        | 描边端点样式                   | `round` \\| `square` \\| `butt`               | `butt`    |      |\n| donutLineDash       | 描边虚线样式                   | number[]                                    | -         |      |\n| donutLineDashOffset | 描边虚线偏移量                 | number                                      | -         |      |\n| donutLineJoin       | 描边连接处样式                 | `round` \\| `bevel` \\| `miter`               | `miter`   |      |\n| donutLineWidth      | 描边宽度                       | number                                      | 1         |      |\n| donutOpacity        | 透明度                         | number \\| string                            | 1         |      |\n| donutPalette        | 颜色或者色板名                 | string &#124; string[]                      | `tableau` |      |\n| donuts              | 圆环数据                       | number[] &#124; [DonutRound](#donutround)[] | -         |      |\n| donutShadowBlur     | 阴影模糊度                     | number                                      | -         |      |\n| donutShadowColor    | 阴影颜色                       | string                                      | -         |      |\n| donutShadowOffsetX  | 阴影在 x 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowOffsetY  | 阴影在 y 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowType     | 阴影类型                       | `inner` \\| `outer`                          | `outer`   |      |\n| donutStroke         | 描边色                         | string                                      | `#000`    |      |\n| donutStrokeOpacity  | 描边色透明度                   | number \\| string                            | 1         |      |\n| donutVisibility     | 图形是否可见                   | `visible` \\| `hidden`                       | `visible` |      |\n| innerR              | 内环半径，使用百分比或者像素值 | string &#124; number                        | 50%       |      |\n\n### DonutRound\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| color          | 颜色                      | string                        | -         |      |\n| fill           | 填充色                    | string                        | `#1783FF` |      |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |      |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash       | 描边虚线样式              | number[]                      | -         |      |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |      |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth      | 描边宽度                  | number                        | 1         |      |\n| opacity        | 透明度                    | number \\| string              | 1         |      |\n| shadowBlur     | 阴影模糊度                | number                        | -         |      |\n| shadowColor    | 阴影颜色                  | string                        | -         |      |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |      |\n| stroke         | 描边色                    | string                        | `#000`    |      |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |      |\n| value          | 数值，用于计算比例        | number                        | -         | ✓    |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |      |\n\n## 示例\n\n### 内置甜甜圈节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Ellipse.en.md":"---\ntitle: Ellipse Node\norder: 5\n---\n\n## Overview\n\nAn ellipse is a geometric shape with asymmetrical major and minor axes.\n\nApplicable scenarios:\n\n- Used to represent dynamic nodes, asymmetric relationships, or special shapes.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Ellipse Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Ellipse.zh.md":"---\ntitle: 椭圆形节点 Ellipse\norder: 5\n---\n\n## 概述\n\n椭圆是一个长轴和短轴不对称的几何形状。\n\n适用场景：\n\n- 用于表示动态节点、非对称关系或特殊形状。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置椭圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Hexagon.en.md":"---\ntitle: Hexagon Node\norder: 6\n---\n\n## Overview\n\nA hexagon is a geometric shape with six equal sides, featuring a honeycomb structure.\n\nApplicable scenarios:\n\n- Used to represent honeycomb networks, molecular structures, or tightly packed nodes.\n\n- Suitable for representing network topology, molecular diagrams, or game maps.\n\n- Commonly used in network diagrams, topology diagrams, game design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                        | Type   | Default                                 | Required |\n| --------- | ------------------------------------------------------------------ | ------ | --------------------------------------- | -------- |\n| outerR    | Outer radius, the distance from the hexagon's center to any vertex | number | Half of the minimum of width and height |          |\n\n## Example\n\n### Built-in Hexagon Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Hexagon.zh.md":"---\ntitle: 六边形节点 Hexagon\norder: 6\n---\n\n## 概述\n\n六边形是一个六边相等的几何形状，具有蜂窝状结构。\n\n适用场景：\n\n- 用于表示蜂窝网络、分子结构或紧密排列的节点。\n\n- 适合表示网络拓扑、分子图或游戏地图。\n\n- 常用于网络图、拓扑图、游戏设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                     | 类型   | 默认值                   | 必选 |\n| ------ | ---------------------------------------- | ------ | ------------------------ | ---- |\n| outerR | 外半径，是指从六边形中心到任意顶点的距离 | number | 默认为宽高的最小值的一半 |      |\n\n## 示例\n\n### 内置六边形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Html.en.md":"---\ntitle: HTML Node\norder: 7\n---\n\n## Overview\n\nHTML node is a custom rectangular area used to display HTML content. It allows you to embed arbitrary HTML elements within graph nodes, providing great flexibility for creating complex custom nodes.\n\nUse Cases:\n\n- Used to represent complex custom nodes such as tables, charts, or rich text\n- Suitable for representing custom visual elements or interactive components\n- Commonly used in custom charts, UI design, dashboards, and other scenarios\n- When you need to embed interactive elements like forms and buttons in nodes\n\n## Framework Support\n\n> **💡 Tips**：\n>\n> - **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node) for better component-based development experience\n> - **Vue Projects**: Vue Node is not currently supported, community contributions are welcome\n> - **Native HTML**: The HTML node introduced in this document is suitable for native HTML development\n\n## Online Demo\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific properties, we will list them below. For all common style properties, see [BaseNode](/en/manual/element/node/base-node)\n\n| Property  | Description                                                                                           | Type                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------------- | --------------------------- | ------- | -------- |\n| dx        | Horizontal offset. HTML container defaults to top-left corner as origin, use dx for horizontal offset | number                      | 0       |          |\n| dy        | Vertical offset. HTML container defaults to top-left corner as origin, use dy for vertical offset     | number                      | 0       |          |\n| innerHTML | HTML content, can be string or `HTMLElement`                                                          | string &#124; `HTMLElement` | -       | ✓        |\n\n## Examples\n\n### Basic HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### HTML Node with Interactive Buttons\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >Restart</button>\n    <button \n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >Monitor</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle button clicks\nwindow.handleRestart = (nodeId) => {\n  console.log(`Restarting server: ${nodeId}`);\n  alert(`Restarting server ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`Opening monitoring panel: ${nodeId}`);\n  alert(`Opening monitoring panel for server ${nodeId}`);\n};\n\ngraph.render();\n```\n\n### Form Input HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: 'User Information', type: 'user-form' } },\n      { id: 'form-2', data: { title: 'Configuration Panel', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Name</label>\n    <input \n      type=\"text\" \n      placeholder=\"Enter name\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Email</label>\n    <input \n      type=\"email\" \n      placeholder=\"Enter email\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Role</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>Administrator</option>\n      <option>User</option>\n      <option>Guest</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Save</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Cancel</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle form operations\nwindow.handleSave = (nodeId) => {\n  console.log(`Saving form: ${nodeId}`);\n  alert(`Form ${nodeId} saved`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`Canceling form: ${nodeId}`);\n  alert(`Form ${nodeId} operation canceled`);\n};\n\ngraph.render();\n```\n\n## Usage Notes\n\n### 1. Performance Optimization\n\n- HTML nodes have higher rendering costs compared to regular graphic nodes, recommend using when node count is small\n- Complex HTML structures will affect performance, recommend keeping structure simple\n- Avoid using too many animation effects in HTML\n\n### 2. Event Handling\n\n- Event handling in HTML nodes needs to be implemented through global functions or event delegation\n- Recommend mounting event handling functions to the `window` object to ensure accessibility in HTML strings\n- Be careful to prevent event bubbling from affecting graph interaction behavior\n\n### 3. Style Isolation\n\n- HTML node styles may be affected by global page styles\n- Recommend using inline styles or ensuring sufficient style specificity\n- Consider using CSS-in-JS or style namespaces to avoid style conflicts\n\n### 4. Responsive Design\n\n- HTML node dimensions are fixed and do not automatically adapt to content\n- Need to dynamically calculate node dimensions based on content or use responsive layouts\n- Consider display effects at different zoom levels\n\n### 5. Framework Integration Recommendations\n\n- **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node), which allows direct use of React components as node content\n- **Vue Projects**: Vue Node is not currently supported, community contributions are welcome if needed\n- **Native Projects**: HTML nodes are the best choice, providing maximum flexibility\n","packages/site/docs/manual/element/node/Html.zh.md":"---\ntitle: HTML节点 Html\norder: 7\n---\n\n## 概述\n\nHTML 节点是一个自定义的矩形区域，用于显示 HTML 内容。它允许您在图形节点中嵌入任意的 HTML 元素，提供了极大的灵活性来创建复杂的自定义节点。\n\n适用场景：\n\n- 用于表示复杂的自定义节点，如表格、图表或富文本\n- 适合表示自定义的可视化元素或交互组件\n- 常用于自定义图表、UI 设计、仪表板等场景\n- 需要在节点中嵌入表单、按钮等交互元素时\n\n## 框架支持说明\n\n> **💡 提示**：\n>\n> - **React 项目**：推荐使用 [React Node](/manual/element/node/react-node) 来实现更好的组件化开发体验\n> - **Vue 项目**：目前暂不支持 Vue Node，欢迎社区共建贡献\n> - **原生 HTML**：本文档介绍的 HTML 节点适用于原生 HTML 开发\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述                                                            | 类型                        | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------- | --------------------------- | ------ | ---- |\n| dx        | 横行偏移量。HTML 容器默认以左上角为原点，通过 dx 来进行横向偏移 | number                      | 0      |      |\n| dy        | 纵向偏移量。HTML 容器默认以左上角为原点，通过 dy 来进行纵向偏移 | number                      | 0      |      |\n| innerHTML | HTML 内容，可以为字符串或者 `HTMLElement`                       | string &#124; `HTMLElement` | -      | ✓    |\n\n## 示例\n\n### 基础HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 带交互按钮的HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%;\n  height: 100%;\n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"display: flex; gap: 8px;\">\n    <button\n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >重启</button>\n    <button\n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >监控</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理按钮点击\nwindow.handleRestart = (nodeId) => {\n  console.log(`重启服务器: ${nodeId}`);\n  alert(`正在重启服务器 ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`打开监控面板: ${nodeId}`);\n  alert(`打开服务器 ${nodeId} 的监控面板`);\n};\n\ngraph.render();\n```\n\n### 表单输入HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: '用户信息', type: 'user-form' } },\n      { id: 'form-2', data: { title: '配置面板', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">姓名</label>\n    <input \n      type=\"text\" \n      placeholder=\"请输入姓名\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">邮箱</label>\n    <input \n      type=\"email\" \n      placeholder=\"请输入邮箱\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">角色</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>管理员</option>\n      <option>用户</option>\n      <option>访客</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >保存</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >取消</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理表单操作\nwindow.handleSave = (nodeId) => {\n  console.log(`保存表单: ${nodeId}`);\n  alert(`表单 ${nodeId} 已保存`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`取消表单: ${nodeId}`);\n  alert(`取消表单 ${nodeId} 操作`);\n};\n\ngraph.render();\n```\n\n## 使用注意事项\n\n### 1. 性能优化\n\n- HTML 节点相比普通图形节点有更高的渲染成本，建议在节点数量较少时使用\n- 复杂的 HTML 结构会影响性能，建议保持结构简洁\n- 避免在 HTML 中使用过多的动画效果\n\n### 2. 事件处理\n\n- HTML 节点中的事件处理需要通过全局函数或事件委托来实现\n- 建议将事件处理函数挂载到 `window` 对象上，确保在 HTML 字符串中可以访问\n- 注意防止事件冒泡影响图的交互行为\n\n### 3. 样式隔离\n\n- HTML 节点的样式可能会受到页面全局样式的影响\n- 建议使用内联样式或确保样式的特异性足够高\n- 考虑使用 CSS-in-JS 或样式命名空间来避免样式冲突\n\n### 4. 响应式设计\n\n- HTML 节点的尺寸是固定的，不会自动适应内容\n- 需要根据内容动态计算节点尺寸，或使用响应式布局\n- 考虑在不同缩放级别下的显示效果\n\n### 5. 框架集成建议\n\n- **React 项目**：推荐使用 [React Node](/manual/element/node/react-node)，可以直接使用 React 组件作为节点内容\n- **Vue 项目**：目前暂不支持 Vue Node，如有需求欢迎社区贡献\n- **原生项目**：HTML 节点是最佳选择，提供了最大的灵活性\n","packages/site/docs/manual/element/node/Image.en.md":"---\ntitle: Image Node\norder: 8\n---\n\n## Overview\n\nThe image node is a rectangular area used to display images.\n\nApplicable scenarios:\n\n- Used to represent user avatars, product images, or icons.\n\n- Suitable for representing social networks, product catalogs, or icon collections.\n\n- Commonly used in social network graphs, product images, UI design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                          | Type   | Default | Required |\n| --------- | ------------------------------------ | ------ | ------- | -------- |\n| img       | Alias for the img attribute          | string | -       |          |\n| src       | Image source, i.e., image URL string | string | -       | ✓        |\n\n## Example\n\n### Built-in Image Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Image.zh.md":"---\ntitle: 图片节点 Image\norder: 8\n---\n\n## 概述\n\n图片节点是一个矩形区域，用于显示图像。\n\n适用场景：\n\n- 用于表示用户头像、产品图片或图标。\n\n- 适合表示社交网络、产品目录或图标集合。\n\n- 常用于社交网络图、产品图、UI 设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性 | 描述                       | 类型   | 默认值 | 必选 |\n| ---- | -------------------------- | ------ | ------ | ---- |\n| img  | 该属性为 img 的别名        | string | -      |      |\n| src  | 图片来源，即图片地址字符串 | string | -      | ✓    |\n\n## 示例\n\n### 内置图片节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Rect.en.md":"---\ntitle: Rect Node\norder: 9\n---\n\n## Overview\n\nA rectangle is a geometric shape with four equal sides and defined boundaries.\n\nApplicable scenarios:\n\n- Used to represent modules, components, or containers.\n\n- Suitable for representing hierarchies, such as organizational charts, file directory trees.\n\n- Commonly used in flowcharts, architecture diagrams, UML diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Rect Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Rect.zh.md":"---\ntitle: 矩形节点 Rect\norder: 9\n---\n\n## 概述\n\n矩形是一个四边相等的几何形状，具有明确的边界。\n\n适用场景：\n\n- 用于表示模块、组件或容器。\n\n- 适合表示层次结构，如组织结构图、文件目录树。\n\n- 常用于流程图、架构图、UML 图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置矩形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Star.en.md":"---\ntitle: Star Node\norder: 10\n---\n\n## Overview\n\nA star is a polygonal geometric shape with prominent points.\n\nApplicable scenarios:\n\n- Used to represent important nodes, special markers, or decorative elements.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                           | Type   | Default                            | Required |\n| --------- | --------------------------------------------------------------------- | ------ | ---------------------------------- | -------- |\n| innerR    | Inner radius, the distance from the star's center to the inner vertex | number | Default is 3/8 of the outer radius |\n\nStructure Description:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## Example\n\n### Built-in Star Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Star.zh.md":"---\ntitle: 五角形节点 Star\norder: 10\n---\n\n## 概述\n\n星形是一个多角几何形状，具有突出的角。\n\n适用场景：\n\n- 用于表示重要节点、特殊标记或装饰性元素。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                 | 类型   | 默认值             | 必选 |\n| ------ | ------------------------------------ | ------ | ------------------ | ---- |\n| innerR | 内半径，是指从星形中心到内顶点的距离 | number | 默认为外半径的 3/8 |\n\n结构说明：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## 示例\n\n### 内置五角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Triangle.en.md":"---\ntitle: Triangle Node\norder: 11\n---\n\n## Overview\n\nA triangle is a geometric shape with three sides, having a clear directionality.\n\nApplicable scenarios:\n\n- Used to represent directional nodes, warnings, or prompts.\n\n- Suitable for indicating direction or hierarchy in flowcharts.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description               | Type                                | Default | Required |\n| --------- | ------------------------- | ----------------------------------- | ------- | -------- |\n| direction | Direction of the triangle | `up` \\| `left` \\| `right` \\| `down` | `up`    |\n\n## Example\n\n### Built-in Triangle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/Triangle.zh.md":"---\ntitle: 三角形节点 Triangle\norder: 11\n---\n\n## 概述\n\n三角形是一个三边几何形状，具有明确的方向性。\n\n适用场景：\n\n- 用于表示方向性节点、警告或提示。\n\n- 适合表示流程图中的方向指示或层级关系。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述         | 类型                                | 默认值 | 必选 |\n| --------- | ------------ | ----------------------------------- | ------ | ---- |\n| direction | 三角形的方向 | `up` \\| `left` \\| `right` \\| `down` | `up`   |\n\n## 示例\n\n### 内置三角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/custom-node.en.md":"---\ntitle: Custom Node\norder: 12\n---\n\nG6 provides a series of [built-in nodes](/en/manual/element/node/base-node), including [circle (Circle Node)](/en/manual/element/node/circle), [diamond (Diamond Node)](/en/manual/element/node/diamond), [donut (Donut Node)](/en/manual/element/node/donut), [ellipse (Ellipse Node)](/en/manual/element/node/ellipse), [hexagon (Hexagon Node)](/en/manual/element/node/hexagon), [html (HTML Node)](/en/manual/element/node/html), [image (Image Node)](/en/manual/element/node/image), [rect (Rectangle Node)](/en/manual/element/node/rect), [star (Star Node)](/en/manual/element/node/star), and [triangle (Triangle Node)](/en/manual/element/node/triangle). These built-in nodes can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter needs that these basic nodes cannot satisfy. In such cases, you need to create custom nodes. Don't worry, this is simpler than you might think!\n\n## Ways to Create Custom Nodes <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are mainly two approaches to creating custom nodes:\n\n### 1. Inherit from Existing Node Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach, where you can choose to inherit from one of the following types:\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - The most basic node class, providing core node functionality\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - Circle node\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - Rectangle node\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - Ellipse node\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - Diamond node\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - Triangle node\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - Star node\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - Image node\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - Donut node\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - Hexagon node\n\n**Why choose this approach?**\n\n- 📌 **Less Code**: Reuse properties and methods of existing nodes, only focus on new features\n- 📌 **Rapid Development**: Suitable for most project needs, quickly achieve business goals\n- 📌 **Easy Maintenance**: Clear code structure with well-defined inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing node types (recommended), you can jump directly to [Create Your First Custom Node in Three Steps](#create-your-first-custom-node-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing node types don't meet your requirements, you can create nodes from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum Freedom**: Complete control over every detail of the node, achieving any complex effects\n- 📌 **Special Requirements**: Highly customized scenarios that existing node types cannot satisfy\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom nodes built from scratch require handling all details yourself, including graphics rendering, event response, state changes, etc., with higher development difficulty. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) for implementation.\n:::\n\n## Create Your First Custom Node in Three Steps\n\nLet's start with a simple example - creating a **rectangle node with main and subtitle**:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// Step 1: Create custom node class\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// Step 2: Register custom node\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// Step 3: Use custom node\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Node Class\n\nInherit from G6's `Rect` (rectangle node) and add a subtitle:\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// Create custom node, inheriting from Rect\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### Step 2: Register Custom Node\n\nUse the `register` method to register the node type so that G6 can recognize your custom node:\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `dual-label-node` is the name we give to this custom node, which will be used in configuration later\n- Class definition: `DualLabelNode` is the node class we just created\n\n### Step 3: Apply Custom Node\n\nUse the custom node in graph configuration:\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom node. It looks simple, but this process contains the core concept of custom nodes: **inherit from a basic node type**, then **override the `render` method** to add custom content.\n\n## Understanding Data Flow: How to Access Data in Custom Nodes\n\nBefore creating complex custom nodes, understanding how data flows into custom nodes is very important. G6 provides multiple ways to access data for custom nodes:\n\n### Method 1: Through `attributes` Parameter (Recommended)\n\nThe first parameter `attributes` of the `render` method contains processed style attributes, including data-driven styles:\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes contains all style attributes, including data-driven styles\n    console.log('All properties of current node:', attributes);\n\n    // If customData: (d) => d.data.someValue is defined in style\n    // Then you can access it through attributes.customData\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Method 2: Through `this.context.graph` to Access Raw Data\n\nWhen you need to access the node's raw data, you can get it through the graph instance:\n\n```js\nclass CustomNode extends Rect {\n  // Convenient data access method\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Get complete node data\n    const nodeData = this.nodeData;\n    console.log('Complete node data:', nodeData);\n\n    // Get business data from data field\n    const businessData = this.data;\n    console.log('Business data:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Complete Data Flow Process\n\nLet's understand how data flows from graph data to custom nodes through a specific example:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // Method 2: Get raw data through graph\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Method 1: Get processed styles from attributes\n    console.log('Get from attributes:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // Method 2: Get from raw data\n    console.log('Get from raw data:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Use data to render custom content\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // This is the node's business data\n        data: {\n          name: 'Zhang San',\n          role: 'Developer',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // Map data from data field to style attributes\n      iconUrl: (d) => d.data.icon, // This becomes attributes.iconUrl\n      userName: (d) => d.data.name, // This becomes attributes.userName\n      // Main title uses role information\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=Data Flow Summary}\n\n1. **Graph Data Definition**: Define business data in `data.nodes[].data`\n2. **Style Mapping**: Use functions in `node.style` to map data to style attributes\n3. **Node Access**: Access data in custom nodes through `attributes` or `this.context.graph`\n4. **Rendering Usage**: Use the obtained data to render custom graphics\n   :::\n\n## From Simple to Complex: Gradually Building Feature-Rich Nodes\n\nLet's gradually increase the complexity and functionality of nodes through practical examples.\n\n### Example 1: User Card Node with Icon and Badge\n\nThis example shows how to create a user card node containing avatar, name, and status badge:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // Avatar style\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // Circular avatar\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // Status badge style\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // Username style\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // Role label style\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Add various components\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: 'Zhang Xiaoming',\n          role: 'Frontend Engineer',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // Data mapping\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 2: Node with Clickable Action Button\n\nAdd a blue button to the node that triggers events (prints logs or executes callbacks) when clicked.\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // Mouse pointer becomes hand\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // Add click event to button\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // Prevent event bubbling to avoid triggering node click event\n        e.stopPropagation();\n\n        // Execute business logic\n        console.log('Button clicked on node:', this.id);\n\n        // If there's a callback function in data, call it\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // Mark as bound to avoid duplicate binding\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // Add a button\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // Specify using our custom node\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 3: Node Responding to State Changes (Click to Change Color)\n\nCommon interactions require nodes and edges to provide feedback through style changes, such as when the mouse moves over a node, clicking to select nodes/edges, or activating interactions on edges through interaction. All these require changing the styles of nodes and edges. There are two ways to achieve this effect:\n\n1. Get the current state from `data.states` and handle state changes in the custom node class;\n2. Separate interaction state from raw data and node drawing logic, only update the node.\n\nWe recommend users use the second approach to implement node state adjustments, which can be achieved through the following steps:\n\n1. Implement custom node;\n2. Configure node state styles in graph configuration;\n3. Set node state through the `graph.setElementState()` method.\n\nBased on rect, extend a hole shape with default white fill color that turns orange when clicked. The sample code to achieve this effect is as follows:\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. Define node class\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. Register node\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. Create graph instance\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // Mouse selected state\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. Add node interaction\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/custom-node.zh.md":"---\ntitle: 自定义节点\norder: 12\n---\n\nG6 提供了一系列 [内置节点](/manual/element/node/base-node)，包含 [circle（圆形节点）](/manual/element/node/circle)、[diamond（菱形节点）](/manual/element/node/diamond)、[donut（甜甜圈节点）](/manual/element/node/donut)、[ellipse（椭圆节点）](/manual/element/node/ellipse)、[hexagon（六边形节点）](/manual/element/node/hexagon)、[html（HTML节点）](/manual/element/node/html)、[image（图片节点）](/manual/element/node/image)、[rect（矩形节点）](/manual/element/node/rect)、[star（星形节点）](/manual/element/node/star) 和 [triangle（三角形节点）](/manual/element/node/triangle)。这些内置节点能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础节点无法满足的需求。这时，你需要创建自定义节点。别担心，这比你想象的要简单！\n\n## 自定义节点的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义节点的方式主要有两种途径：\n\n### 1. 继承现有节点类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - 最基础的节点类，提供节点的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - 圆形节点\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - 矩形节点\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - 椭圆节点\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - 菱形节点\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - 三角形节点\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - 星形节点\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - 图片节点\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - 甜甜圈节点\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - 六边形节点\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有节点的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有节点类型（推荐），可以直接跳到 [三步创建你的第一个自定义节点](#三步创建你的第一个自定义节点) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有节点类型都不满足需求，你可以基于 G 的底层图形系统从零创建节点。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制节点的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有节点类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义节点需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义节点\n\n让我们从一个简单的例子开始 - 创建一个 **带有主副标题的矩形节点**：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// 第一步：创建自定义节点类\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// 第二步：注册自定义节点\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// 第三步：使用自定义节点\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义节点类\n\n继承 G6 的 `Rect`（矩形节点），并添加一个副标题：\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 创建自定义节点，继承自 Rect\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### 第二步：注册自定义节点\n\n使用 `register` 方法注册节点类型，这样 G6 才能识别你的自定义节点：\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`dual-label-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：`DualLabelNode` 是我们刚刚创建的节点类\n\n### 第三步：应用自定义节点\n\n在图配置中使用自定义节点：\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义节点。它看起来很简单，但这个过程包含了自定义节点的核心思想：**继承一个基础节点类型**，然后 **重写 `render` 方法** 来添加自定义内容。\n\n## 理解数据流：如何在自定义节点中获取数据\n\n在创建复杂的自定义节点之前，理解数据如何流入自定义节点是非常重要的。G6 为自定义节点提供了多种数据获取方式：\n\n### 方式一：通过 `attributes` 参数（推荐）\n\n`render` 方法的第一个参数 `attributes` 包含了经过处理的样式属性，包括数据驱动的样式：\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes 包含了所有样式属性，包括数据驱动的样式\n    console.log('当前节点的所有属性:', attributes);\n\n    // 如果在 style 中定义了 customData: (d) => d.data.someValue\n    // 那么可以通过 attributes.customData 获取\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 方式二：通过 `this.context.graph` 获取原始数据\n\n当你需要访问节点的原始数据时，可以通过图实例获取：\n\n```js\nclass CustomNode extends Rect {\n  // 便捷的数据获取方法\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 获取节点的完整数据\n    const nodeData = this.nodeData;\n    console.log('节点完整数据:', nodeData);\n\n    // 获取 data 字段中的业务数据\n    const businessData = this.data;\n    console.log('业务数据:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 数据传递的完整流程\n\n让我们通过一个具体例子来理解数据是如何从图数据传递到自定义节点的：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // 方式二：通过 graph 获取原始数据\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 方式一：从 attributes 获取处理后的样式\n    console.log('从 attributes 获取:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // 方式二：从原始数据获取\n    console.log('从原始数据获取:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 使用数据渲染自定义内容\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // 这里是节点的业务数据\n        data: {\n          name: '张三',\n          role: '开发者',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // 将 data 中的数据映射到样式属性\n      iconUrl: (d) => d.data.icon, // 这会变成 attributes.iconUrl\n      userName: (d) => d.data.name, // 这会变成 attributes.userName\n      // 主标题使用角色信息\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=数据流总结}\n\n1. **图数据定义**：在 `data.nodes[].data` 中定义业务数据\n2. **样式映射**：在 `node.style` 中使用函数将数据映射到样式属性\n3. **节点获取**：在自定义节点中通过 `attributes` 或 `this.context.graph` 获取数据\n4. **渲染使用**：使用获取到的数据渲染自定义图形\n   :::\n\n## 从简单到复杂：逐步构建功能丰富的节点\n\n让我们通过实际例子，逐步增加节点的复杂度和功能。\n\n### 示例一：带图标和徽章的用户卡片节点\n\n这个例子展示如何创建一个包含头像、姓名、状态徽章的用户卡片节点：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // 头像样式\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // 圆形头像\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // 状态徽章样式\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // 用户名样式\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // 角色标签样式\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 添加各个组件\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: '张小明',\n          role: '前端工程师',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // 数据映射\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例二：可点击操作按钮的节点\n\n给节点加一个蓝色按钮，点击后触发事件（打印日志或执行回调）。\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // 鼠标指针变为手型\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // 为按钮添加点击事件\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // 阻止事件冒泡，避免触发节点的点击事件\n        e.stopPropagation();\n\n        // 执行业务逻辑\n        console.log('Button clicked on node:', this.id);\n\n        // 如果数据中有回调函数，则调用\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // 标记已绑定事件，避免重复绑定\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // 添加一个按钮\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // 指定使用我们的自定义节点\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例三：响应状态变化的节点（点击变色）\n\n常见的交互都需要节点和边通过样式变化做出反馈，例如鼠标移动到节点上、点击选中节点/边、通过交互激活边上的交互等，都需要改变节点和边的样式，有两种方式来实现这种效果：\n\n1. 从 `data.states` 获取当前状态，在自定义节点类中处理状态变化；\n2. 将交互状态同原始数据和绘制节点的逻辑分开，仅更新节点。\n\n我们推荐用户使用第二种方式来实现节点的状态调整，可以通过以下方式来实现：\n\n1. 实现自定义节点；\n2. 在图配置项中配置节点状态样式；\n3. 通过 `graph.setElementState()` 方法来设置节点状态。\n\n基于 rect 扩展出一个 hole 图形，默认填充色为白色，当鼠标点击时变成橙色，实现这一效果的示例代码如下：\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. 定义节点类\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. 注册节点\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. 创建图实例\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // 鼠标选中状态\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. 添加节点交互\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/element/node/overview.en.md":"---\ntitle: Node Overview\norder: 0\n---\n\n## What is a Node\n\nA node is one of the basic elements in a graph, representing an entity or an abstract concept, such as a person, a place, an organization, etc. Nodes can contain attributes like ID, name, type, etc. In G6, nodes can have various shapes and styles, and support rich interactions and customization.\n\nYou can create any number of nodes in a graph and connect them with edges to represent relationships.\n\n## Node System\n\nThe G6 node system includes three main categories: built-in nodes, extended nodes, and custom nodes. **In most cases, built-in nodes are sufficient.**\n\n### Built-in Nodes\n\nG6 provides a variety of built-in node types, **which can be used directly without registration**:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| Node Type      | Registration Name | Description                                     |\n| -------------- | ----------------- | ----------------------------------------------- |\n| Circle Node    | `circle`          | Commonly used for entities                      |\n| Rectangle Node | `rect`            | Suitable for more text and details              |\n| Ellipse Node   | `ellipse`         | A variant of the circle                         |\n| Diamond Node   | `diamond`         | Often used for decision points or special nodes |\n| Triangle Node  | `triangle`        | Can indicate direction or special marks         |\n| Hexagon Node   | `hexagon`         | Suitable for grid layouts and honeycomb charts  |\n| Star Node      | `star`            | Highlights important nodes                      |\n| Donut Node     | `donut`           | Can display proportions or progress             |\n| Image Node     | `image`           | Uses an image as the node body                  |\n| HTML Node      | `html`            | Supports custom HTML content                    |\n\n### 3D Nodes\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` provides 3D nodes:\n\n- `Capsule` - Capsule-shaped node\n- `Cone` - Cone-shaped node\n- `Cube` - Cube-shaped node\n- `Cylinder` - Cylinder-shaped node\n- `Plane` - Plane node\n- `Sphere` - Sphere node\n- `Torus` - Torus node\n\n### React Nodes\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` provides React nodes, supporting the use of React components as the node body. For detailed tutorials, please refer to the [Using React to Define Nodes](/en/manual/element/node/react-node) document.\n\n### Custom Nodes\n\nWhen built-in and extended nodes cannot meet the requirements, G6 offers powerful customization capabilities:\n\n- Extend built-in nodes\n- Create entirely new node types\n\nUnlike built-in nodes, **custom nodes need to be registered before use**. For detailed tutorials, please refer to the [Custom Nodes](/en/manual/element/node/custom-node) document.\n\n## Data Structure\n\nWhen defining nodes, you need to add a `nodes` field to the graph's data object. Each node is an object with the following structure:\n\n| Property | Description                                                                                                                             | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                     | string         | -       | ✓        |\n| type     | Node type, either a built-in node type name or a custom node name                                                                       | string         | -       |          |\n| data     | Node data, used to store custom data such as the node's name, description, etc. Can be accessed via callback functions in style mapping | object         | -       |          |\n| style    | Node style, including visual attributes like position, size, color, etc.                                                                | object         | -       |          |\n| states   | Initial states of the node, such as selected, active, hover, etc.                                                                       | string[]       | -       |          |\n| combo    | The ID of the combo to which the node belongs, used to organize hierarchical relationships. If none, it is null                         | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                         | string[]       | -       |          |\n\nAn example of a data item in the `nodes` array:\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure nodes, listed in order of priority from high to low:\n\n- Use `graph.setNode()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setNode()`\n\nAfter creating the graph instance, you can use `graph.setNode()` to dynamically set the node's style mapping logic.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nWhen instantiating the graph, you can configure node style mapping through `node`, which is a global configuration and will apply to all nodes.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different nodes, you can write the configuration into the node data. This configuration method can be directly written into the data in the following form:\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can do so as follows:\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### Dynamically Updating Nodes\n\nG6 supports dynamically updating the style and state of nodes at runtime:\n\n```typescript\n// Update the style of a single node\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// Set node state\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=Note}\nWhen updating nodes, only the specified attributes will be updated, and unspecified attributes will remain unchanged.\n:::\n\nFor more node-related APIs, please refer to [API - Element Operations](/en/api/element).\n\n## Node States\n\nNodes can have different states, such as selected, highlighted, disabled, etc. You can define the display effect of nodes in different states by configuring state styles:\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // Default style\n      fill: '#C6E5FF',\n    },\n    // State styles\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\nThe state system is the foundation for implementing node interaction effects. For more information on states, please refer to [Element States](/en/manual/element/state).\n","packages/site/docs/manual/element/node/overview.zh.md":"---\ntitle: 节点总览\norder: 0\n---\n\n## 什么是节点\n\n节点（Node）是图中的基本元素之一，表示图中的实体或者抽象概念，例如一个人、一个地点、一个组织等，节点可以包含一些属性，例如节点的 ID、名称、类型等。在 G6 中，节点可以具有多种形状和样式，并支持丰富的交互和自定义功能。\n\n你可以在图中创建任意数量的节点，并通过边连接它们以表示关系。\n\n## 节点体系\n\nG6 的节点体系包括三大类：内置节点、扩展节点和自定义节点。**大多数场景下，内置节点即可满足需求**。\n\n### 内置节点\n\nG6 提供了丰富的内置节点类型，**无需注册，直接配置即可使用**：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| 节点类型   | 注册名称   | 描述                     |\n| ---------- | ---------- | ------------------------ |\n| 圆形节点   | `circle`   | 常用于表示普通实体       |\n| 矩形节点   | `rect`     | 适合展示更多文本和细节   |\n| 椭圆节点   | `ellipse`  | 类似圆形的变体           |\n| 菱形节点   | `diamond`  | 常用于决策点或特殊节点   |\n| 三角形节点 | `triangle` | 可用于指示方向或特殊标记 |\n| 六边形节点 | `hexagon`  | 适合网格布局和蜂窝图     |\n| 星形节点   | `star`     | 突出显示重要节点         |\n| 甜甜圈节点 | `donut`    | 可展示比例或进度信息     |\n| 图片节点   | `image`    | 使用图片作为节点主体     |\n| HTML节点   | `html`     | 支持自定义HTML内容       |\n\n### 3D 节点\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` 提供了 3D 节点：\n\n- `Capsule` - 胶囊型节点\n- `Cone` - 圆锥型节点\n- `Cube` - 立方体节点\n- `Cylinder` - 圆柱型节点\n- `Plane` - 平面节点\n- `Sphere` - 球体节点\n- `Torus` - 圆环节点\n\n### React 节点\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` 提供了 React 节点，支持使用 React 组件作为节点的主体，详细教程请查看 [使用 React 定义节点](/manual/element/node/react-node) 文档。\n\n### 自定义节点\n\n当内置节点和扩展节点无法满足需求时，G6提供了强大的自定义能力：\n\n- 继承内置节点进行扩展\n- 创建全新的节点类型\n\n与内置节点不同，**自定义节点需要先注册后使用**。详细教程请参考 [自定义节点](/manual/element/node/custom-node) 文档。\n\n## 数据结构\n\n定义节点时，需要在图的数据对象中添加 `nodes` 字段。每个节点是一个对象，结构如下：\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n`nodes` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## 配置方法\n\n配置节点的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setNode()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setNode()`\n\n可在图实例创建后，使用 `graph.setNode()` 动态设置节点的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `node` 配置节点样式映射，这里的配置是全局的配置，将会在所有节点上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同节点进行不同的配置，可以将配置写入到节点数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### 动态更新节点\n\nG6 支持在运行时动态更新节点的样式和状态：\n\n```typescript\n// 更新单个节点样式\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// 设置节点状态\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=注意}\n更新节点时，只有指定的属性会被更新，未指定的属性保持不变。\n:::\n\n更多与节点相关的 API 请参考 [API - 元素操作](/api/element)。\n\n## 节点状态\n\n节点可以拥有不同的状态，例如选中、高亮、禁用等。可以通过配置状态样式来定义节点在不同状态下的显示效果：\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // 默认样式\n      fill: '#C6E5FF',\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n状态系统是实现节点交互效果的基础，更多状态的介绍，请参考 [元素状态](/manual/element/state)。\n","packages/site/docs/manual/element/node/react-node.en.md":"---\ntitle: Define Nodes with React\norder: 13\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the `@antv/g6-extension-react` ecosystem library, you can directly use React components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Ant Design\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing React design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a React project**: Ensure a React project is installed and created.\n- **React version requirement**: Ensure the React version used is >=16.8.0.\n\n### Install Dependencies\n\nTo use `@antv/g6-extension-react`, run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register React Node Type\n\nRegister the React node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `react-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: ReactNode is the implementation class exported by `@antv/g6-extension-react`\n\n#### 2. Define Business Component\n\nDefine a simple React component as the content of the node:\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. Use the Component\n\nUse the custom React node in the graph configuration. Specify the node type and style in the graph configuration to use the custom React component.\n\n- `type`: Specify the node type as `react-node` (use the name given during registration)\n- `style.component`: Define the React component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // Set border color based on selection state\n        cursor: 'pointer', // Add mouse pointer style\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","packages/site/docs/manual/element/node/react-node.zh.md":"---\ntitle: 使用 React 定义节点\norder: 13\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 `@antv/g6-extension-react` 一方生态库，可以直接使用 React 组件作为节点内容，提升开发效率与可维护性。\n\n## 自定义节点方案选择\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Ant Design 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 React 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 React 项目**：确保已安装并创建 React 项目。\n- **React 版本要求**：确保使用的 React 版本 >=16.8.0。\n\n### 安装依赖\n\n要使用 `@antv/g6-extension-react`，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 React 节点类型\n\n通过扩展机制注册 React 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`react-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：ReactNode 是 `@antv/g6-extension-react` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 React 组件作为节点的内容：\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 React 节点。通过在图配置中指定节点类型和样式，来使用自定义的 React 组件。\n\n- `type`：指定节点类型为 `react-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 React 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n        cursor: 'pointer', // 添加鼠标指针样式\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","packages/site/docs/manual/element/node/vue-node.en.md":"---\ntitle: Define Nodes with Vue\norder: 14\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) ecosystem library, you can directly use Vue components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Element Plus / Ant Design Vue\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing Vue design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a Vue project**: Ensure a Vue project is installed and created.\n- **Vue version requirement**: Ensure the Vue version used is >=2.6.0. (Vue 3 is recommended)\n\n### Install Dependencies\n\nTo use [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue), run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register Vue Node Type\n\nRegister the Vue node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `vue-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: VueNode is the implementation class exported by `g6-extension-vue`\n\n#### 2. Define Business Component\n\nDefine a simple Vue component as the content of the node:\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. Use the Component\n\nUse the custom Vue node in the graph configuration. Specify the node type and style in the graph configuration to use the custom Vue component.\n\n- `type`: Specify the node type as `vue-node` (use the name given during registration)\n- `style.component`: Define the Vue component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // Set border color based on selection state\n          cursor: 'pointer', // Add mouse pointer style\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","packages/site/docs/manual/element/node/vue-node.zh.md":"---\ntitle: 使用 Vue 定义节点\norder: 14\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) 社区生态库，可以直接使用 Vue 组件作为节点内容，提升开发效率与可维护性。\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Element Plus / Ant Design Vue 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 Vue 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 Vue 项目**：确保已安装并创建 Vue 项目。\n- **Vue 版本要求**：确保使用的 Vue 版本 >=2.6.0。(推荐使用 Vue 3)\n\n### 安装依赖\n\n要使用 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue)，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 Vue 节点类型\n\n通过扩展机制注册 Vue 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`vue-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：VueNode 是 `g6-extension-vue` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 Vue 组件作为节点的内容：\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 Vue 节点。通过在图配置中指定节点类型和样式，来使用自定义的 Vue 组件。\n\n- `type`：指定节点类型为 `vue-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 Vue 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n          cursor: 'pointer', // 添加鼠标指针样式\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","packages/site/docs/manual/element/overview.en.md":"---\ntitle: Element Overview\norder: 1\n---\n\n## Element System\n\nThe core of G6 charts is composed of three basic elements: **Node**, **Edge**, and **Combo**. These elements are the fundamental units for building complex graphical networks.\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### Node\n\n[Nodes](/en/manual/element/node/overview) represent entities or concepts in the graph, such as people, places, objects, etc. G6 provides a rich set of built-in node types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 also supports [defining nodes using React](/en/manual/element/node/react-node) or [custom nodes](/en/manual/element/node/custom-node) to meet specific needs.\n\n### Edge\n\n[Edges](/en/manual/element/edge/overview) represent the connections between nodes, such as friendships, transactions, etc. G6 has multiple built-in edge types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nWhen built-in edges do not meet the requirements, complex connection expressions can be achieved through [custom edges](/en/manual/element/edge/custom-edge).\n\n### Combo\n\n[Combos](/en/manual/element/combo/overview) are special elements that can contain nodes and other combos, used to represent collections, groups, or hierarchical relationships. G6 has two built-in combo types:\n\n- **Circle Combo**(`circle`): Suitable for compact grouping\n- **Rectangle Combo**(`rect`): Suitable for regular layout grouping\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nCombos support nesting, dragging, expanding/collapsing, and other interactions, and more complex container behaviors can be achieved through [custom combos](/en/manual/element/combo/custom-combo).\n\n## Element Composition Principle\n\nEach element is composed of one or more basic shapes. Shapes are the smallest graphical units in G6, including [rectangle](/en/manual/element/shape/properties#rectstyleprops), [circle](/en/manual/element/shape/properties#circlestyleprops), [text](/en/manual/element/shape/properties#textstyleprops), [path](/en/manual/element/shape/properties#pathstyleprops), etc.\n\nFor example:\n\n- A node may consist of a background shape (such as a circle) and a text label\n- An edge may consist of a path, arrow, and text label\n- A combo may consist of a container shape, title text, and expand/collapse button\n\nFor more information about shapes, see [Shape Overview](/en/manual/element/shape/overview) and [Shape Style Properties](/en/manual/element/shape/properties).\n\n## Element State\n\n[Element State](/en/manual/element/state) is a powerful mechanism for displaying visual changes of elements in different interactions or business scenarios. G6 provides a complete state management system:\n\n- **Preset States**: `selected`, `highlight`, `active`, etc.\n- **State Overlay**: Elements can have multiple states simultaneously, with styles overlaying according to priority\n- **Custom States**: Any state can be defined according to business needs\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Configure Elements\n\nG6 5.x adopts a flat configuration structure, where all element configurations are at the same level, making it easy to find and manage:\n\n```typescript\n{\n  node: {\n    // Default node style\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // Node styles in different states\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // Default edge style\n    style: {\n      stroke: '#aaa',\n    },\n    // Edge styles in different states\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // Default combo style\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\nThere are three configuration methods, in order of priority from high to low:\n\n1. **Dynamic configuration using instance methods**: such as `graph.setNode()`, `graph.setEdge()`, `graph.setCombo()`\n2. **Global configuration when instantiating the graph**: specify configuration items in `new Graph()`\n3. **Configuration in data**: set in the data objects of nodes, edges, and combos\n\nIn editors like VSCode, you can see all configurable properties of elements and search based on keywords:\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Extension Capabilities\n\nG6 provides powerful extension capabilities to meet various customization needs:\n\n- **Custom Nodes**: [Custom Node Guide](/en/manual/element/node/custom-node)\n- **Custom Edges**: [Custom Edge Guide](/en/manual/element/edge/custom-edge)\n- **Custom Combos**: [Custom Combo Guide](/en/manual/element/combo/custom-combo)\n- **React Nodes**: [Define Nodes Using React](/en/manual/element/node/react-node)\n- **3D Extension**: Use 3D nodes through `@antv/g6-extension-3d`\n\n## Built-in Element Reference\n\n### Node Types\n\n- [Built-in Node Library](/en/manual/element/node/base-node)\n\n### Edge Types\n\n- [Built-in Edge Library](/en/manual/element/edge/base-edge)\n\n### Combo Types\n\n- [Built-in Combo Library](/en/manual/element/combo/base-combo)\n","packages/site/docs/manual/element/overview.zh.md":"---\ntitle: 元素总览\norder: 1\n---\n\n## 元素体系\n\nG6 图表的核心是由三种基本元素构成：**节点(Node)**、**边(Edge)** 和 **组合(Combo)**。这些元素是构建复杂图形网络的基础单元。\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 节点 (Node)\n\n[节点](/manual/element/node/overview) 表示图中的实体或概念，如人物、地点、对象等。G6 提供了丰富的内置节点类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 还支持 [使用 React 定义节点](/manual/element/node/react-node) 或 [自定义节点](/manual/element/node/custom-node) 以满足特定需求。\n\n### 边 (Edge)\n\n[边](/manual/element/edge/overview)表示节点间的连接关系，如朋友关系、交易往来等。G6 内置多种边类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n当内置边不满足需求时，可以通过 [自定义边](/manual/element/edge/custom-edge) 来实现复杂的连接表现。\n\n### 组合 (Combo)\n\n[组合](/manual/element/combo/overview)是一种特殊元素，可以包含节点和其他组合，用于表示集合、分组或层级关系。G6 内置两种组合类型：\n\n- **圆形组合**(`circle`)：适合紧凑型分组\n- **矩形组合**(`rect`)：适合规则布局的分组\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n组合支持嵌套、拖拽、展开/收起等交互，可以通过 [自定义组合](/manual/element/combo/custom-combo) 来实现更复杂的容器行为。\n\n## 元素构成原理\n\n每个元素由一个或多个基础图形(Shape)组成。图形是 G6 中的最小图形单元，包括 [矩形](/manual/element/shape/properties#rectstyleprops)、[圆形](/manual/element/shape/properties#circlestyleprops)、[文本](/manual/element/shape/properties#textstyleprops)、[路径](/manual/element/shape/properties#pathstyleprops)等。\n\n例如：\n\n- 一个节点可能由背景图形(如圆形)和文本标签组成\n- 一条边可能由路径、箭头和文本标签组成\n- 一个组合可能由容器图形、标题文本和展开/收起按钮组成\n\n要了解更多关于图形的信息，请参阅 [图形 Shape 总览](/manual/element/shape/overview) 和 [Shape 样式属性](/manual/element/shape/properties)。\n\n## 元素状态\n\n[元素状态](/manual/element/state) 是一种强大的机制，用于展示元素在不同交互或业务场景下的视觉变化。G6 提供了一套完整的状态管理系统：\n\n- **预设状态**：`selected`(选中)、`highlight`(高亮)、`active`(激活)等\n- **状态叠加**：元素可同时拥有多个状态，样式按优先级叠加\n- **自定义状态**：可根据业务需求定义任意状态\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 配置元素\n\nG6 5.x 采用扁平化的配置结构，所有元素的配置都在同一层级，便于查找和管理：\n\n```typescript\n{\n  node: {\n    // 节点默认样式\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // 节点在不同状态下的样式\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // 边默认样式\n    style: {\n      stroke: '#aaa',\n    },\n    // 边在不同状态下的样式\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // 组合默认样式\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\n配置方式有三种，按优先级从高到低：\n\n1. **使用实例方法动态配置**：如 `graph.setNode()`、`graph.setEdge()`、`graph.setCombo()`\n2. **实例化图时全局配置**：在 `new Graph()` 时指定配置项\n3. **在数据中配置**：在节点、边、组合的数据对象中设置\n\n在 VSCode 等编辑器中，你可以看到元素的全部可配置属性，并基于关键字进行搜索：\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 扩展能力\n\nG6 提供了强大的扩展能力，满足各种自定义需求：\n\n- **自定义节点**：[自定义节点指南](/manual/element/node/custom-node)\n- **自定义边**：[自定义边指南](/manual/element/edge/custom-edge)\n- **自定义组合**：[自定义组合指南](/manual/element/combo/custom-combo)\n- **React 节点**：[使用 React 定义节点](/manual/element/node/react-node)\n- **3D 扩展**：通过 `@antv/g6-extension-3d` 使用 3D 节点\n\n## 内置元素参考\n\n### 节点类型\n\n- [内置节点库](/manual/element/node/base-node)\n\n### 边类型\n\n- [内置边库](/manual/element/edge/base-edge)\n\n### 组合类型\n\n- [内置组合库](/manual/element/combo/base-combo)\n","packages/site/docs/manual/element/shape/label-shape.en.md":"---\ntitle: Design and Implementation of Composite Shape\norder: 3\n---\n\nG6 provides a flexible Shape mechanism, allowing developers to customize various graphics and efficiently reuse them in elements such as nodes, edges, and combos. This article uses Label as an example to explain how to customize a Shape and how to apply it in elements.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 1. Customization and Encapsulation of Shape\n\n### 1. Base Class Design of Shape\n\nAll Shapes inherit from `BaseShape`, which centrally manages the lifecycle (creation, update, destruction), property parsing, animation, event binding, etc. You only need to focus on implementing the `render` method.\n\n**Core Abstraction:**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // Lifecycle management, property parsing, animation, etc...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. Hierarchical Structure of Composite Shape\n\nA node usually contains multiple child Shapes, for example:\n\n```\nNode\n├── keyShape (main shape)\n├── label (label, auxiliary information)\n│   ├── text\n│   └── rect\n├── icon\n│   ├── text\n│   └── image\n├── badge\n│   ├── text\n│   └── rect\n└── port\n│   ├── circle\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Implementation of Label Shape\n\nLabel is a typical composite Shape, consisting of text (Text) and an optional background (Rect). The implementation idea is as follows:\n\n- **Property Separation**: The style properties of Label are divided into text style and background style, which are passed to Text and Rect respectively.\n- **Smart Layout**: The background automatically adjusts its size and position based on the text content, padding, border radius, etc.\n- **Reuse upsert**: The `upsert` method is used to automatically manage the creation, update, and destruction of child Shapes.\n\n**Main code snippet of Label:**\n\n```js\nimport { Text, Rect } from '@antv/g'; // Import atomic graphics\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... Omitted style extraction methods\n}\n```\n\n- `getTextStyle` and `getBackgroundStyle` extract the style properties for text and background respectively to avoid interference.\n- The `upsert` method ensures automatic CRUD of Shapes, greatly improving reusability and robustness.\n\n### 4. Complete Custom Shape Example\n\nBelow is an example of customizing a label with special decoration, demonstrating the complete definition, registration, and usage of a Shape:\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // Main text\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // Background\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // Extra decoration: small dot on the left\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...implement getTextStyle/getBackgroundStyle\n}\n\n// Register custom Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// Define custom node\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// Register custom node\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 2. Prefix Separation of Style Properties\n\nIn G6, elements such as nodes, edges, and combos often contain multiple child Shapes (such as main shape, label, badge, port, etc.). To ensure that the style of each child Shape does not interfere with each other, G6 adopts a **prefix separation** design for style properties.\n\n### 1. Significance of Prefix Separation\n\n- **Decoupling**: Each child Shape only cares about its own style properties, avoiding style pollution.\n- **Easy Expansion**: Adding a new child Shape only requires defining a new prefix, without modifying the original logic.\n- **Intuitive Configuration**: When configuring nodes/edges/combos, users can clearly set the style of each part.\n\n### 2. Code Implementation\n\nTake Label as an example:\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` means all properties starting with `background` belong to the label background style.\n- During rendering, tools such as `subStyleProps` and `subObject` are used to automatically extract prefixed styles and pass them to the corresponding Shape.\n\n**Label background style extraction example**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...Omitted layout calculation\n  return backgroundStyle;\n}\n```\n\n**Style configuration example**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 3. Relationship between Label and keyShape\n\n- **keyShape** is the main shape of a node/edge/combo, determining interaction picking, bounding box, main style, etc.\n- **Label**, icon, badge, port, etc. usually exist as auxiliary Shapes and are not used as keyShape.\n- When customizing a node, you can specify the keyShape via `drawKeyShape` or similar methods. Label is only responsible for displaying text information and does not affect the main interaction control of the node.\n\n## 4. How to Apply Custom Shape in Elements\n\nTake nodes as an example. The node base class `BaseNode` has built-in support for multiple child Shapes (keyShape, label, icon, badge, port, halo, etc.). You only need to focus on drawing the keyShape, and other child Shapes can be automatically managed through configuration and style prefixing.\n\n### 1. Node Rendering Process\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. Draw keyShape (main shape)\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. Draw halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. Draw icon\n  this.drawIconShape(attributes, container);\n\n  // 4. Draw badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. Draw label\n  this.drawLabelShape(attributes, container);\n\n  // 6. Draw ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- The style of each child Shape is automatically extracted by prefix separation and passed to the corresponding Shape instance.\n- You can flexibly control the display and style of each child Shape through configuration options.\n\n### 2. Example of Applying Label\n\nSuppose you want to add a label with a background to a node, just configure the label-related properties in the node data:\n\n```js\n{\n  label: true,\n  labelText: 'I am a label',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`, `labelFill`, `labelFontSize`, etc. will be automatically extracted and passed to the text part of the Label.\n- `labelBackground`, `labelBackgroundFill`, `labelBackgroundRadius`, `labelPadding`, etc. will be automatically extracted and passed to the background part of the Label.\n\nYou do not need to manually manage the creation, update, or destruction of the Label. G6 will handle it automatically.\n\n## 5. Common Issues and Debugging Suggestions\n\n### 1. Why is the label style not effective?\n\n- Check whether the style property prefix is correct (such as `labelFill`, `labelBackgroundFill`).\n- Make sure the `label` configuration of the node/edge/combo is `true` and `labelText` is set.\n- Check if it is overridden by other styles.\n\n### 2. How to debug the rendering of custom Shape?\n\n- Use the browser console to view `shapeMap` and confirm whether each child Shape is created correctly.\n\n### 3. How to make Label respond to node states (such as hover, selected)?\n\n- Directly set node state styles in the graph configuration (recommended)\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- Or listen for state changes in the implementation of Label and dynamically adjust the style. You can get the current state value through data.\n\n---\n\nFor more details, it is recommended to read the source code [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts), [`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts).\n","packages/site/docs/manual/element/shape/label-shape.zh.md":"---\ntitle: 复合 Shape 的设计与实现\norder: 3\n---\n\nG6 提供了灵活的 Shape 机制，支持开发者自定义各种图形，并在节点、边、Combo 等元素中高效复用。本文将以 Label（标签）为例，讲解如何自定义 Shape、如何在元素中应用。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 一、Shape 的自定义与封装\n\n### 1. Shape 的基类设计\n\n所有 Shape 都继承自 `BaseShape`，它统一管理了 Shape 的生命周期（创建、更新、销毁）、属性解析、动画、事件绑定等。你只需关注如何实现 `render` 方法即可。\n\n**核心抽象：**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // 生命周期管理、属性解析、动画等...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. 复合 Shape 层级结构示意\n\n一个节点通常包含多个子 Shape，例如：\n\n```\n节点（Node）\n├── keyShape（主图形）\n├── label（标签，辅助信息）\n│   ├── text（文本）\n│   └── rect（背景）\n├── icon（图标）\n│   ├── text（文本）\n│   └── image（图片）\n├── badge（徽标）\n│   ├── text（文本）\n│   └── rect（背景）\n└── port（锚点）\n│   ├── circle（圆形）\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Label Shape 的实现\n\nLabel 是一个典型的复合 Shape，由文本（Text）和可选的背景（Rect）组成。其实现思路如下：\n\n- **属性分离**：Label 的样式属性分为文本样式和背景样式，分别传递给 Text 和 Rect。\n- **智能布局**：背景自动根据文本内容、内边距、圆角等动态调整尺寸和位置。\n- **复用 upsert**：通过 `upsert` 方法自动管理子 Shape 的创建、更新、销毁。\n\n**Label 主要代码片段：**\n\n```js\nimport { Text, Rect } from '@antv/g'; // 引入原子图形\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... 省略样式提取方法\n}\n```\n\n- `getTextStyle`、`getBackgroundStyle` 分别提取文本和背景的样式属性，避免相互干扰。\n- `upsert` 方法保证了 Shape 的自动增删改查，极大提升了复用性和健壮性。\n\n### 4. 完整自定义 Shape 示例\n\n下面以自定义一个带特殊装饰的标签为例，演示 Shape 的完整定义、注册与使用：\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // 主文本\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // 背景\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // 额外装饰：左侧小圆点\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...实现 getTextStyle/getBackgroundStyle\n}\n\n// 注册自定义 Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// 定义自定义节点\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// 注册自定义节点\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 二、样式属性的前缀分离\n\nG6 中节点、边、Combo 等元素往往包含多个子 Shape（如主图形、标签、徽标、锚点等）。为了让每个子 Shape 的样式互不干扰，G6 采用了**样式属性前缀分离**的设计。\n\n### 1. 前缀分离的意义\n\n- **解耦**：每个子 Shape 只关心属于自己的样式属性，避免样式污染。\n- **易扩展**：新增子 Shape 只需定义新的前缀，无需修改原有逻辑。\n- **配置直观**：用户在配置节点/边/Combo 时，可以一目了然地设置各部分样式。\n\n### 2. 代码实现\n\n以 Label 为例：\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` 表示所有以 `background` 开头的属性都属于标签背景样式。\n- 在实际渲染时，通过 `subStyleProps`、`subObject` 等工具函数，自动提取带前缀的样式，传递给对应的 Shape。\n\n**Label 背景样式提取示例**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...省略布局计算\n  return backgroundStyle;\n}\n```\n\n**样式配置示例**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 三、Label 与 keyShape 的关系\n\n- **keyShape** 是节点/边/Combo 的主图形，决定交互拾取、包围盒、主样式等。\n- **Label**、icon、badge、port 等通常作为辅助 Shape 存在，不会作为 keyShape。\n- 你可以在自定义节点时通过 `drawKeyShape` 或类似方法指定 keyShape，Label 只负责展示文本信息，不影响节点的交互主控。\n\n## 四、如何在元素中应用自定义 Shape\n\n以节点为例，节点基类 `BaseNode` 已经内置了对多种子 Shape 的支持（keyShape、label、icon、badge、port、halo 等）。你只需专注于 keyShape 的绘制，其他子 Shape 可以通过配置和样式前缀自动管理。\n\n### 1. 节点渲染流程\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. 绘制 keyShape（主图形）\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. 绘制 halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. 绘制 icon\n  this.drawIconShape(attributes, container);\n\n  // 4. 绘制 badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. 绘制 label\n  this.drawLabelShape(attributes, container);\n\n  // 6. 绘制 ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- 每个子 Shape 的样式都通过前缀分离自动提取，传递给对应的 Shape 实例。\n- 你可以通过配置项灵活控制每个子 Shape 的显示与样式。\n\n### 2. 应用 Label 的示例\n\n假设你要为节点添加带背景的标签，只需在节点数据中配置 label 相关属性：\n\n```js\n{\n  label: true,\n  labelText: '我是标签',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`、`labelFill`、`labelFontSize` 等会被自动提取并传递给 Label 的文本部分。\n- `labelBackground`、`labelBackgroundFill`、`labelBackgroundRadius`、`labelPadding` 等会被自动提取并传递给 Label 的背景部分。\n\n你无需手动管理 Label 的创建、更新、销毁，G6 会自动完成。\n\n## 五、常见问题与调试建议\n\n### 1. 为什么 label 样式没有生效？\n\n- 检查样式属性前缀是否正确（如 `labelFill`、`labelBackgroundFill`）。\n- 确认节点/边/Combo 的 `label` 配置为 `true`，且 `labelText` 已设置。\n- 检查是否被其他样式覆盖。\n\n### 2. 如何调试自定义 Shape 的渲染？\n\n- 使用浏览器控制台查看 `shapeMap`，确认各子 Shape 是否被正确创建。\n\n### 3. 如何让 Label 响应节点状态（如 hover、selected）？\n\n- 直接在图配置中设置节点状态样式（推荐）\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- 或者在 Label 的实现中监听状态变化，动态调整样式。可以通过 data 获取到当前的状态值\n\n---\n\n如需更深入了解，建议阅读源码 [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts)、[`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts)。\n","packages/site/docs/manual/element/shape/overview.en.md":"---\ntitle: Shape and KeyShape\norder: 1\n---\n\n## Shape\n\nA Shape in G6 refers to a graphical element, such as a circle, rectangle, or path. Shapes are generally associated with nodes, edges, or combos in G6. **💡 Every node/edge/combo in G6 is composed of one or more shapes. The style configuration of nodes, edges, and combos is reflected on their corresponding shapes.**\n\nFor example, in the images below: the node on the left contains a single circular shape; the node in the middle contains a circle and a text shape; the node on the right contains five circles (the blue-green main circle and four anchor points at the top, bottom, left, and right) and a text shape. Each node/edge/combo has its unique key shape (keyShape). In the examples below, the keyShape for all three nodes is the blue-green circle. The keyShape is mainly used for interaction detection and automatic style updates with [element states](/en/manual/element/state), see [keyShape](#keyshape).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> (Left) A node with only one circular shape, whose keyShape is the circle. (Middle) A node with a circle and a text shape, whose keyShape is the circle. (Right) A node with a main circle, text, and four small circles at the top, bottom, left, and right, whose keyShape is the main circle.\n\nG6 uses different combinations of shapes to design various built-in nodes/edges/combos. Built-in nodes include 'circle', 'rect', 'ellipse', ... (see [Built-in Nodes](/en/manual/element/node/base-node)); built-in edges include 'line', 'polyline', 'cubic', ... (see [Built-in Edges](/en/manual/element/edge/base-edge)); built-in combos include 'circle', 'rect', ... (see [Built-in Combos](/en/manual/element/combo/base-combo)).\n\nIn addition to using built-in nodes/edges/combos, G6 also allows users to customize nodes/edges/combos by combining shapes as needed. See [Custom Node](/en/manual/element/node/custom-node), [Custom Edge](/en/manual/element/edge/custom-edge), and [Custom Combo](/en/manual/element/combo/custom-combo) for details.\n\n## KeyShape\n\nIn G6, each node, edge, or combo consists of one or more shapes, but one of them is called the keyShape, which is the \"key graphical element\" of the item:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> The key graphical element of the node is the colored area in the image above.\n\n### Bounding Box Determination\n\n**Determines the bounding box of a node/combo**, which is used to calculate the connection point of related edges (the intersection with the edge). If the keyShape is different, the intersection calculation between the node and the edge will also differ.\n\n#### Example\n\nIn this example, a node consists of a rect shape and a circle shape with a gray stroke and transparent fill.\n\n- When the node's keyShape is the circle:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- When the node's keyShape is the rect:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape Lifecycle\n\n> If you need to [customize nodes](/en/manual/element/node/custom-node), [customize edges](/en/manual/element/edge/custom-edge), or [customize combos](/en/manual/element/combo/custom-combo), you need to understand the lifecycle of shapes. If you use built-in nodes/edges/combos, you can skip this section.\n\nThe shape lifecycle includes:\n\n- **Initial Rendering**: Draws the shape for the first time based on data and style configuration.\n- **Update**: Automatically updates the appearance of the shape when data or style changes.\n- **Operation**: Responds to interaction states (such as selected, active, hover, etc.) and dynamically adjusts the style.\n- **Destruction**: Cleans up when the shape is removed (usually managed automatically by the Graph, so users don't need to worry).\n\nWhen customizing shapes, the most common requirement is \"how to efficiently manage the creation, update, and destruction of shapes.\" For this, G6 provides a very useful method in BaseShape:\n\n### Principle and Advantages of upsert\n\nupsert is a combination of \"update\" and \"insert\", meaning \"update if exists, insert if not\". Its function can be simply understood as:\n\n- **Automatic Judgment**: You only need to describe the desired appearance of the shape. `upsert` will automatically determine whether the shape already exists. If not, it will create it; if it exists, it will update it; if it needs to be deleted, it will remove it automatically.\n- **Simplified Logic**: Developers do not need to manually manage the CRUD of shapes, avoiding duplicate code and state confusion.\n- **Improved Robustness**: Whether it's the initial rendering, data changes, or state switching, upsert ensures that the shape always stays in sync with the data and configuration.\n\n**Type Definition:**\n\n```js\n/**\n * Create, update, or delete a shape\n * @param className Shape name\n * @param Ctor Shape type\n * @param style Shape style. Pass false to delete the shape\n * @param container Container\n * @param hooks Hooks\n * @returns Shape instance\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\nYou only need to describe \"what kind of shape you want now\" without worrying about whether it is being created, updated, or deleted. upsert will handle it for you. This makes customizing and managing complex composite shapes very simple and safe.\n","packages/site/docs/manual/element/shape/overview.zh.md":"---\ntitle: 图形 Shape 与 KeyShape\norder: 1\n---\n\n## 图形 Shape\n\nShape 指 G6 中的图形、形状，可以是圆形、矩形、路径等。它一般与 G6 中的节点、边、Combo 相关。**💡 G6 中的每一种节点/边/Combo 都是由一个或多个 Shape 组合而成。节点、边、Combo 的样式配置都会被体现到对应的图形上。**\n\n例如下图（左）的节点包含了一个圆形图形；下图（中）的节点含有一个圆形和一个文本图形；下图（右）的节点中含有 5 个圆形（蓝绿色的圆和上下左右四个锚点）、一个文本图形。但每种节点/边/Combo 都会有自己的唯一关键图形 keyShape，下图中三个节点的 keyShape 都是蓝绿色的圆，keyShape 主要用于交互检测、样式随 [元素状态](/manual/element/state) 自动更新等，见 [keyShape](#keyshape)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> （左）只含有一个圆形图形的节点，keyShape 是该圆形。（中）含有圆形和文本图形的节点，keyShape 是圆形。（右）含有主要圆形、文本、上下左右四个小圆形的节点，keyShape 是圆形。\n\nG6 使用不同的 shape 组合，设计了多种内置的节点/边/ Combo 。G6 内置节点的有 'circle'， 'rect'，'ellipse'，...（详见 [内置节点](/manual/element/node/base-node)）；内置边的有 'line'，'polyline'，'cubic'，...（详见 [内置边](/manual/element/edge/base-edge)）；内置 Combo 有 'circle'，'rect'，（详见 [内置 Combo](/manual/element/combo/base-combo)）。\n\n除了使用内置的节点/边/ Combo 外，G6 还允许用户通过自己搭配和组合 shape 进行节点/边/ Combo 的自定义，详见 [自定义节点](/manual/element/node/custom-node)，[自定义边](/manual/element/edge/custom-edge)，[自定义 Combo](/manual/element/combo/custom-combo)。\n\n## KeyShape\n\n在 G6 中，每个节点、边、Combo 都由一个或多个 Shape 组成，但其中有一个 Shape 被称为 keyShape，它是该元素的“关键图形”：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> 节点的关键图形就是上图的颜色区域\n\n### 包围盒确定\n\n**确定节点 / Combo 的包围盒（Bounding Box）** ，从而计算相关边的连入点（与相关边的交点）。若 keyShape 不同，节点与边的交点计算结果不同。\n\n#### 示例  \n\n本例中的一个节点由一个 rect 图形和一个带灰色描边、填充透明的 circle 图形构成。\n\n- 当节点的 keyShape 为 circle 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- 当节点的 keyShape 为 rect 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape 的生命周期\n\n> 当用户需要 [自定义节点](/manual/element/node/custom-node)、[自定义边](/manual/element/edge/custom-edge)、[自定义 Combo](/manual/element/combo/custom-combo) 时，需要了解 Shape 的生命周期。使用内置节点/边/Combo 则可以跳过这一部分内容。\n\n从整体来看，Shape 的生命周期分为：\n\n- **初始化渲染**：首次根据数据和样式配置绘制出 Shape。\n- **更新**：当数据或样式发生变化时，自动更新 Shape 的表现。\n- **操作**：响应交互状态（如 selected、active、hover 等），动态调整样式。\n- **销毁**：Shape 被移除时的清理（通常由 Graph 自动管理，用户无需关心）。\n\n在自定义 Shape 时，最常见的需求就是“如何高效地管理 Shape 的创建、更新和销毁”。G6 为此在 BaseShape 中设计了一个非常实用的方法：\n\n### upsert 的原理与优势\n\nupsert 是“update” 和 “insert” 的合成词，意思是“有则更新，无则创建”。它的作用可以简单理解为：\n\n- **自动判断**：你只需描述希望 Shape 呈现的样子，`upsert` 会自动判断当前 Shape 是否已存在。如果不存在则创建，如果已存在则更新，如果需要删除则自动移除。\n- **简化逻辑**：开发者无需手动管理 Shape 的增删改查，避免了重复代码和状态混乱。\n- **提升健壮性**：无论是初次渲染、数据变更还是状态切换，upsert 都能保证 Shape 始终与数据和配置保持同步。\n\n**类型定义：**\n\n```js\n/**\n * 创建、更新或删除图形\n * @param className 图形名称\n * @param Ctor 图形类型\n * @param style 图形样式。若要删除图形，传入 false\n * @param container 容器\n * @param hooks 钩子函数\n * @returns 图形实例\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\n你只需要描述“我现在想要什么样的图形”，不用关心它是新建、更新还是删除，upsert 都会帮你处理好。这让自定义和管理复杂的复合 Shape 变得非常简单和安全。\n","packages/site/docs/manual/element/shape/properties.en.md":"---\ntitle: Atomic Shapes and Their Properties\norder: 2\n---\n\nElements (nodes/edges) in G6 are composed of **one or more [shapes](/en/manual/element/shape/overview)**, mainly added via `upsert` in the `render` method when customizing nodes or edges. G6 supports the following shapes:\n\n1. [Circle](#circlestyleprops)\n2. [Ellipse](#ellipsestyleprops)\n3. [Rect](#rectstyleprops)\n4. [HTML Element](#htmlstyleprops)\n5. [Image](#imagestyleprops)\n6. [Line](#linestyleprops)\n7. [Path](#pathstyleprops)\n8. [Polygon](#polygonstyleprops)\n9. [Polyline](#polylinestyleprops)\n10. [Text](#textstyleprops)\n\n## Common Properties of All Shapes\n\n### BaseShapeStyle\n\n| Property       | Description                                                                                      | Type                                     | Required |\n| -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------- | -------- |\n| x              | x coordinate                                                                                     | number                                   | ✓        |\n| y              | y coordinate                                                                                     | number                                   | ✓        |\n| width          | Width                                                                                            | number                                   | ✓        |\n| height         | Height                                                                                           | number                                   | ✓        |\n| fill           | Fill color                                                                                       | string \\| Pattern \\| null                |          |\n| stroke         | Stroke color                                                                                     | string \\| Pattern \\| null                |          |\n| opacity        | Overall opacity                                                                                  | number \\| string                         |          |\n| fillOpacity    | Fill opacity                                                                                     | number \\| string                         |          |\n| strokeOpacity  | Stroke opacity                                                                                   | number \\| string                         |          |\n| lineWidth      | Line width                                                                                       | number \\| string                         |          |\n| lineCap        | Line cap style                                                                                   | `butt` \\| `round` \\| `square`            |          |\n| lineJoin       | Line join style                                                                                  | `miter` \\| `round` \\| `bevel`            |          |\n| lineDash       | Dash array                                                                                       | number \\| string \\| (string \\| number)[] |          |\n| lineDashOffset | Dash offset                                                                                      | number                                   |          |\n| shadowBlur     | Shadow blur                                                                                      | number                                   |          |\n| shadowColor    | Shadow color                                                                                     | string                                   |          |\n| shadowOffsetX  | Shadow X offset                                                                                  | number                                   |          |\n| shadowOffsetY  | Shadow Y offset                                                                                  | number                                   |          |\n| cursor         | Mouse cursor, supports all [CSS cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) | string                                   |          |\n| zIndex         | Render z-index                                                                                   | number                                   |          |\n| visibility     | Visibility                                                                                       | `visible` \\| `hidden`                    |          |\n\n**Example:**\n\n```js\nconst shape = BaseShape.upsert(\n  // Specify the shape key, which must be unique within the same custom element type\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Common Methods of All Shapes\n\n### attr()\n\nSet or get the drawing attributes of the instance.\n\n### attr(name)\n\nGet the value of an attribute.\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\nUpdate a single drawing attribute.\n\n### attr({...})\n\nBatch update drawing attributes.\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## Circle Shape\n\n### CircleStyleProps\n\n| Property          | Description                               | Type             | Required |\n| ----------------- | ----------------------------------------- | ---------------- | -------- |\n| cx                | Center x coordinate                       | number \\| string | ✓        |\n| cy                | Center y coordinate                       | number \\| string | ✓        |\n| cz                | Center z coordinate                       | number \\| string |          |\n| r                 | Radius                                    | number \\| string | ✓        |\n| isBillboard       | Billboard mode (always faces camera)      | boolean          |          |\n| isSizeAttenuation | Size attenuation (size changes with view) | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Rect Shape\n\n### RectStyleProps\n\n| Property          | Description       | Type                         | Required |\n| ----------------- | ----------------- | ---------------------------- | -------- |\n| x                 | Rect x coordinate | number \\| string             |          |\n| y                 | Rect y coordinate | number \\| string             |          |\n| z                 | Rect z coordinate | number                       |          |\n| width             | Rect width        | number \\| string             | ✓        |\n| height            | Rect height       | number \\| string             | ✓        |\n| isBillboard       | Billboard mode    | boolean                      |          |\n| isSizeAttenuation | Size attenuation  | boolean                      |          |\n| radius            | Border radius     | number \\| string \\| number[] |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Ellipse Shape\n\n### EllipseStyleProps\n\n| Property          | Description         | Type             | Required |\n| ----------------- | ------------------- | ---------------- | -------- |\n| cx                | Center x coordinate | number \\| string | ✓        |\n| cy                | Center y coordinate | number \\| string | ✓        |\n| cz                | Center z coordinate | number \\| string |          |\n| rx                | X-axis radius       | number \\| string | ✓        |\n| ry                | Y-axis radius       | number \\| string | ✓        |\n| isBillboard       | Billboard mode      | boolean          |          |\n| isSizeAttenuation | Size attenuation    | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| Property  | Description       | Type                  | Required |\n| --------- | ----------------- | --------------------- | -------- |\n| x         | HTML x coordinate | number \\| string      |          |\n| y         | HTML y coordinate | number \\| string      |          |\n| innerHTML | HTML content      | string \\| HTMLElement | ✓        |\n| width     | HTML width        | number \\| string      |          |\n| height    | HTML height       | number \\| string      |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## Image Shape\n\n### ImageStyleProps\n\n| Property          | Description                      | Type                       | Required |\n| ----------------- | -------------------------------- | -------------------------- | -------- |\n| x                 | Image x coordinate               | number \\| string           |          |\n| y                 | Image y coordinate               | number \\| string           |          |\n| z                 | Image z coordinate               | number                     |          |\n| src               | Image source or HTMLImageElement | string \\| HTMLImageElement | ✓        |\n| width             | Image width                      | number \\| string           |          |\n| height            | Image height                     | number \\| string           |          |\n| isBillboard       | Billboard mode                   | boolean                    |          |\n| isSizeAttenuation | Size attenuation                 | boolean                    |          |\n| billboardRotation | Billboard rotation angle         | number                     |          |\n| keepAspectRatio   | Keep original aspect ratio       | boolean                    |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## Line Shape\n\n### LineStyleProps\n\n| Property          | Description         | Type                  | Required |\n| ----------------- | ------------------- | --------------------- | -------- |\n| x1                | Start x coordinate  | number                | ✓        |\n| y1                | Start y coordinate  | number                | ✓        |\n| x2                | End x coordinate    | number                | ✓        |\n| y2                | End y coordinate    | number                | ✓        |\n| z1                | Start z coordinate  | number                |          |\n| z2                | End z coordinate    | number                |          |\n| isBillboard       | Billboard mode      | boolean               |          |\n| isSizeAttenuation | Size attenuation    | boolean               |          |\n| markerStart       | Marker at start     | DisplayObject \\| null |          |\n| markerEnd         | Marker at end       | DisplayObject \\| null |          |\n| markerStartOffset | Start marker offset | number                |          |\n| markerEndOffset   | End marker offset   | number                |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Path Shape\n\n### PathStyleProps\n\n| Property          | Description          | Type                   | Required |\n| ----------------- | -------------------- | ---------------------- | -------- |\n| d                 | Path string or array | string \\| PathArray    | ✓        |\n| markerStart       | Marker at start      | DisplayObject \\| null  |          |\n| markerEnd         | Marker at end        | DisplayObject \\| null  |          |\n| markerMid         | Marker at middle     | DisplayObject \\| null  |          |\n| markerStartOffset | Start marker offset  | number                 |          |\n| markerEndOffset   | End marker offset    | number                 |          |\n| isBillboard       | Billboard mode       | boolean                |          |\n| isSizeAttenuation | Size attenuation     | boolean                |          |\n| fillRule          | Fill rule            | `nonzero` \\| `evenodd` |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Polygon Shape\n\n### PolygonStyleProps\n\n| Property          | Description             | Type                                             | Required |\n| ----------------- | ----------------------- | ------------------------------------------------ | -------- |\n| points            | Array of polygon points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start         | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end           | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle        | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset     | number                                           |          |\n| markerEndOffset   | End marker offset       | number                                           |          |\n| isClosed          | Is polygon closed       | boolean                                          |          |\n| isBillboard       | Billboard mode          | boolean                                          |          |\n| isSizeAttenuation | Size attenuation        | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Polyline Shape\n\n### PolylineStyleProps\n\n| Property          | Description              | Type                                             | Required |\n| ----------------- | ------------------------ | ------------------------------------------------ | -------- |\n| points            | Array of polyline points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start          | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end            | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle         | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset      | number                                           |          |\n| markerEndOffset   | End marker offset        | number                                           |          |\n| isBillboard       | Billboard mode           | boolean                                          |          |\n| isSizeAttenuation | Size attenuation         | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Text\n\n### TextStyleProps\n\n| Property            | Description              | Type                                                                        | Required |\n| ------------------- | ------------------------ | --------------------------------------------------------------------------- | -------- |\n| x                   | Text x coordinate        | number \\| string                                                            |          |\n| y                   | Text y coordinate        | number \\| string                                                            |          |\n| z                   | Text z coordinate        | number \\| string                                                            |          |\n| text                | Text content             | number \\| string                                                            | ✓        |\n| fontSize            | Font size                | number \\| string                                                            |          |\n| fontFamily          | Font family              | string                                                                      |          |\n| fontStyle           | Font style               | `normal` \\| `italic` \\| `oblique`                                           |          |\n| fontWeight          | Font weight              | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |          |\n| fontVariant         | Font variant             | `normal` \\| `small-caps` \\| string                                          |          |\n| textAlign           | Text horizontal align    | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |          |\n| textBaseline        | Text baseline            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |          |\n| textOverflow        | Text overflow            | `clip` \\| `ellipsis` \\| string                                              |          |\n| lineHeight          | Line height              | number \\| string                                                            |          |\n| letterSpacing       | Letter spacing           | number \\| string                                                            |          |\n| maxLines            | Max lines                | number                                                                      |          |\n| textPath            | Text path                | Path                                                                        |          |\n| textPathSide        | Text path side           | `left` \\| `right`                                                           |          |\n| textPathStartOffset | Text path start offset   | number \\| string                                                            |          |\n| textDecorationLine  | Text decoration line     | string                                                                      |          |\n| textDecorationColor | Text decoration color    | string                                                                      |          |\n| textDecorationStyle | Text decoration style    | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |          |\n| isBillboard         | Billboard mode           | boolean                                                                     |          |\n| billboardRotation   | Billboard rotation angle | number                                                                      |          |\n| isSizeAttenuation   | Size attenuation         | boolean                                                                     |          |\n| wordWrap            | Word wrap                | boolean                                                                     |          |\n| wordWrapWidth       | Word wrap width          | number                                                                      |          |\n| dx                  | X offset                 | number \\| string                                                            |          |\n| dy                  | Y offset                 | number \\| string                                                            |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n**Display in multiply line:**\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","packages/site/docs/manual/element/shape/properties.zh.md":"---\ntitle: 原子 Shape 以及其属性\norder: 2\n---\n\nG6 中的元素（节点/边）是由**一个或多个 [图形 Shape](/manual/element/shape/overview)** 组成，主要通过自定义节点或自定义边时在 `render` 方法中使用 `upsert` 添加，G6 中支持以下的图形 Shape：\n\n1. [Circle - 圆形](#circlestyleprops)\n2. [Ellipse - 椭圆](#ellipsestyleprops)\n3. [Rect - 矩形](#rectstyleprops)\n4. [HTML - HTML元素](#htmlstyleprops)\n5. [Image - 图片](#imagestyleprops)\n6. [Line - 线](#linestyleprops)\n7. [Path - 路径](#pathstyleprops)\n8. [Polygon - 多边形](#polygonstyleprops)\n9. [Polyline - 折线](#polylinestyleprops)\n10. [Text - 文本](#textstyleprops)\n\n## 各图形 Shape 的通用属性\n\n### BaseShapeStyle\n\n| 属性           | 描述                                                                                          | 类型                                     | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------- | ---- |\n| x              | x 坐标                                                                                        | number                                   | ✓    |\n| y              | y 坐标                                                                                        | number                                   | ✓    |\n| width          | 宽度                                                                                          | number                                   | ✓    |\n| height         | 高度                                                                                          | number                                   | ✓    |\n| fill           | 填充颜色                                                                                      | string \\| Pattern \\| null                |      |\n| stroke         | 描边颜色                                                                                      | string \\| Pattern \\| null                |      |\n| opacity        | 整体透明度                                                                                    | number \\| string                         |      |\n| fillOpacity    | 填充透明度                                                                                    | number \\| string                         |      |\n| strokeOpacity  | 描边透明度                                                                                    | number \\| string                         |      |\n| lineWidth      | 线宽度                                                                                        | number \\| string                         |      |\n| lineCap        | 线段端点样式                                                                                  | `butt` \\| `round` \\| `square`            |      |\n| lineJoin       | 线段连接处样式                                                                                | `miter` \\| `round` \\| `bevel`            |      |\n| lineDash       | 虚线配置                                                                                      | number \\| string \\| (string \\| number)[] |      |\n| lineDashOffset | 虚线偏移量                                                                                    | number                                   |      |\n| shadowBlur     | 阴影模糊程度                                                                                  | number                                   |      |\n| shadowColor    | 阴影颜色                                                                                      | string                                   |      |\n| shadowOffsetX  | 阴影 X 方向偏移                                                                               | number                                   |      |\n| shadowOffsetY  | 阴影 Y 方向偏移                                                                               | number                                   |      |\n| cursor         | 鼠标样式，[CSS 的 cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) 选项都支持 | string                                   |      |\n| zIndex         | 渲染层级                                                                                      | number                                   |      |\n| visibility     | 可见性                                                                                        | `visible` \\| `hidden`                    |      |\n\n**示例：**\n\n```js\nconst shape = BaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 各图形 Shape 的通用方法\n\n### attr()\n\n设置或获取实例的绘图属性。\n\n### attr(name)\n\n获取实例的属性值。\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\n更新实例的单个绘图属性。\n\n### attr({...})\n\n批量更新实例绘图属性。\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## 圆图形 Circle\n\n### CircleStyleProps\n\n| 属性              | 描述                               | 类型             | 必选 |\n| ----------------- | ---------------------------------- | ---------------- | ---- |\n| cx                | 圆心 x 坐标                        | number \\| string | ✓    |\n| cy                | 圆心 y 坐标                        | number \\| string | ✓    |\n| cz                | 圆心 z 坐标                        | number \\| string |      |\n| r                 | 圆的半径                           | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式（始终面向相机） | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减（随视距变化大小） | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 矩形图形 Rect\n\n### RectStyleProps\n\n| 属性              | 描述               | 类型                         | 必选 |\n| ----------------- | ------------------ | ---------------------------- | ---- |\n| x                 | 矩形 x 坐标        | number \\| string             |      |\n| y                 | 矩形 y 坐标        | number \\| string             |      |\n| z                 | 矩形 z 坐标        | number                       |      |\n| width             | 矩形宽度           | number \\| string             | ✓    |\n| height            | 矩形高度           | number \\| string             | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean                      |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                      |      |\n| radius            | 矩形圆角半径       | number \\| string \\| number[] |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 椭圆图形 Ellipse\n\n### EllipseStyleProps\n\n| 属性              | 描述               | 类型             | 必选 |\n| ----------------- | ------------------ | ---------------- | ---- |\n| cx                | 椭圆中心 x 坐标    | number \\| string | ✓    |\n| cy                | 椭圆中心 y 坐标    | number \\| string | ✓    |\n| cz                | 椭圆中心 z 坐标    | number \\| string |      |\n| rx                | 椭圆 x 轴半径      | number \\| string | ✓    |\n| ry                | 椭圆 y 轴半径      | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| 属性      | 描述             | 类型                  | 必选 |\n| --------- | ---------------- | --------------------- | ---- |\n| x         | HTML 元素 x 坐标 | number \\| string      |      |\n| y         | HTML 元素 y 坐标 | number \\| string      |      |\n| innerHTML | HTML 内容        | string \\| HTMLElement | ✓    |\n| width     | HTML 元素宽度    | number \\| string      |      |\n| height    | HTML 元素高度    | number \\| string      |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## 图片图形 Image\n\n### ImageStyleProps\n\n| 属性              | 描述                         | 类型                       | 必选 |\n| ----------------- | ---------------------------- | -------------------------- | ---- |\n| x                 | 图片 x 坐标                  | number \\| string           |      |\n| y                 | 图片 y 坐标                  | number \\| string           |      |\n| z                 | 图片 z 坐标                  | number                     |      |\n| src               | 图片资源路径或 HTML 图片元素 | string \\| HTMLImageElement | ✓    |\n| width             | 图片宽度                     | number \\| string           |      |\n| height            | 图片高度                     | number \\| string           |      |\n| isBillboard       | 是否启用公告牌模式           | boolean                    |      |\n| isSizeAttenuation | 是否启用大小衰减             | boolean                    |      |\n| billboardRotation | 公告牌模式下的旋转角度       | number                     |      |\n| keepAspectRatio   | 是否保持图片原有宽高比       | boolean                    |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## 直线 Line\n\n### LineStyleProps\n\n| 属性              | 描述               | 类型                  | 必选 |\n| ----------------- | ------------------ | --------------------- | ---- |\n| x1                | 线段起点 x 坐标    | number                | ✓    |\n| y1                | 线段起点 y 坐标    | number                | ✓    |\n| x2                | 线段终点 x 坐标    | number                | ✓    |\n| y2                | 线段终点 y 坐标    | number                | ✓    |\n| z1                | 线段起点 z 坐标    | number                |      |\n| z2                | 线段终点 z 坐标    | number                |      |\n| isBillboard       | 是否启用公告牌模式 | boolean               |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean               |      |\n| markerStart       | 线段起点的标记     | DisplayObject \\| null |      |\n| markerEnd         | 线段终点的标记     | DisplayObject \\| null |      |\n| markerStartOffset | 起点标记的偏移量   | number                |      |\n| markerEndOffset   | 终点标记的偏移量   | number                |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 路径 Path\n\n### PathStyleProps\n\n| 属性              | 描述                 | 类型                   | 必选 |\n| ----------------- | -------------------- | ---------------------- | ---- |\n| d                 | 路径定义字符串或数组 | string \\| PathArray    | ✓    |\n| markerStart       | 路径起点的标记       | DisplayObject \\| null  |      |\n| markerEnd         | 路径终点的标记       | DisplayObject \\| null  |      |\n| markerMid         | 路径中间点的标记     | DisplayObject \\| null  |      |\n| markerStartOffset | 起点标记的偏移量     | number                 |      |\n| markerEndOffset   | 终点标记的偏移量     | number                 |      |\n| isBillboard       | 是否启用公告牌模式   | boolean                |      |\n| isSizeAttenuation | 是否启用大小衰减     | boolean                |      |\n| fillRule          | 填充规则             | `nonzero` \\| `evenodd` |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 多边形图形 Polygon\n\n### PolygonStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 多边形的顶点数组   | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 多边形起点的标记   | DisplayObject \\| null                            |      |\n| markerEnd         | 多边形终点的标记   | DisplayObject \\| null                            |      |\n| markerMid         | 多边形中间点的标记 | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isClosed          | 是否闭合多边形     | boolean                                          |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 折线 Polyline\n\n### PolylineStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 折线的顶点数组     | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 折线起点的标记     | DisplayObject \\| null                            |      |\n| markerEnd         | 折线终点的标记     | DisplayObject \\| null                            |      |\n| markerMid         | 折线中间点的标记   | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 文字 Text\n\n### TextStyleProps\n\n| 属性                | 描述               | 类型                                                                        | 必选 |\n| ------------------- | ------------------ | --------------------------------------------------------------------------- | ---- |\n| x                   | 文本 x 坐标        | number \\| string                                                            |      |\n| y                   | 文本 y 坐标        | number \\| string                                                            |      |\n| z                   | 文本 z 坐标        | number \\| string                                                            |      |\n| text                | 文本内容           | number \\| string                                                            | ✓    |\n| fontSize            | 字体大小           | number \\| string                                                            |      |\n| fontFamily          | 字体族             | string                                                                      |      |\n| fontStyle           | 字体样式           | `normal` \\| `italic` \\| `oblique`                                           |      |\n| fontWeight          | 字体粗细           | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |      |\n| fontVariant         | 字体变种           | `normal` \\| `small-caps` \\| string                                          |      |\n| textAlign           | 文本水平对齐方式   | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |      |\n| textBaseline        | 文本基线           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |      |\n| textOverflow        | 文本溢出处理方式   | `clip` \\| `ellipsis` \\| string                                              |      |\n| lineHeight          | 行高               | number \\| string                                                            |      |\n| letterSpacing       | 字间距             | number \\| string                                                            |      |\n| maxLines            | 最大行数           | number                                                                      |      |\n| textPath            | 文本路径           | Path                                                                        |      |\n| textPathSide        | 文本路径侧边       | `left` \\| `right`                                                           |      |\n| textPathStartOffset | 文本路径起始偏移   | number \\| string                                                            |      |\n| textDecorationLine  | 文本装饰线         | string                                                                      |      |\n| textDecorationColor | 文本装饰线颜色     | string                                                                      |      |\n| textDecorationStyle | 文本装饰线样式     | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |      |\n| isBillboard         | 是否启用公告牌模式 | boolean                                                                     |      |\n| billboardRotation   | 公告牌旋转角度     | number                                                                      |      |\n| isSizeAttenuation   | 是否启用大小衰减   | boolean                                                                     |      |\n| wordWrap            | 是否自动换行       | boolean                                                                     |      |\n| wordWrapWidth       | 自动换行宽度       | number                                                                      |      |\n| dx                  | X 方向偏移         | number \\| string                                                            |      |\n| dy                  | Y 方向偏移         | number \\| string                                                            |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n多行文字显示：\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","packages/site/docs/manual/element/state.en.md":"---\ntitle: Element State\norder: 2\n---\n\n## What is Element State\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\nElement State refers to the visual representation of elements (nodes, edges, combos) in a graph under different interaction scenarios. For example, when a user clicks on a node, the node might enter a \"selected\" state and change color; when the mouse hovers over an edge, the edge might enter a \"highlight\" state and become bold.\n\n**Simply put, states allow elements to dynamically change their appearance based on user operations or business logic.**\n\n### Characteristics of States\n\n- **Multiple State Coexistence**: An element can have multiple states simultaneously, such as being both \"selected\" and \"highlighted\"\n- **Style Stacking**: Styles from multiple states are stacked together, with later-set state styles having higher priority\n- **Complete Customization**: Besides built-in states, you can create any custom states that meet your business requirements\n\n## Built-in State Types\n\nG6 provides some commonly used built-in states that you can use directly:\n\n| State Name  | Description     | Typical Use Cases                    |\n| ----------- | --------------- | ------------------------------------ |\n| `selected`  | Selected state  | When user clicks to select elements  |\n| `active`    | Active state    | Currently interacting element        |\n| `highlight` | Highlight state | Elements that need emphasis          |\n| `inactive`  | Inactive state  | Dimmed display of unfocused elements |\n| `disabled`   | Disabled state  | Non-interactive elements             |\n\n> 💡 **Tip**: These built-in states are not mandatory. You can completely define your own state names according to business requirements.\n\n## Configuring State Styles\n\n### Basic Configuration\n\nConfigure corresponding styles for different states when creating a graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Node state style configuration\n  node: {\n    // Default style (style when no state is applied)\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // Styles for various states\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // Edge state style configuration\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // Combo state style configuration\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### Custom States\n\nYou can create any custom states that meet your business requirements:\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // Custom state: error\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // Dashed border\n      },\n      // Custom state: success\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // Custom state: warning\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // Add icon\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## Setting Element States\n\n### Setting Initial States in Data\n\nSet initial states for elements in data:\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // Initially in selected state\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // Initially in disabled state\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // Initially has multiple states\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // Initial state of the edge\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### Dynamic State Setting\n\nDynamically change element states through API:\n\n```javascript\n// Set a single state for a single element\ngraph.setElementState('node1', 'selected');\n\n// Set multiple states for a single element\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// Batch set states for multiple elements\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### State Stacking Effect\n\nWhen an element has multiple states, styles are stacked in order:\n\n```javascript\n// Assume a node has both selected and highlight states\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// Final style = default style + selected state style + highlight state style\n// If there are style conflicts, later state styles will override earlier ones\n```\n\n## Clearing Element States\n\n### Clear All States\n\nRestore elements to default state (no states):\n\n```javascript\n// Clear all states of a single element\ngraph.setElementState('node1', []);\n\n// Batch clear states of multiple elements\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### Clear Specific States\n\nIf an element has multiple states, you can clear only some of them:\n\n```javascript\n// Assume node1 currently has ['selected', 'highlight', 'active'] three states\n// Now only want to keep 'selected' state, clear other states\ngraph.setElementState('node1', ['selected']);\n\n// Or get current states, then filter out unwanted states\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### Clear Specific States from All Elements\n\n```javascript\n// Clear 'highlight' state from all nodes\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## Querying Element States\n\n### Get Element States\n\n```javascript\n// Get all states of a specified element\nconst states = graph.getElementState('node1');\nconsole.log(states); // For example: ['selected', 'highlight']\n\n// If element has no states, returns empty array\nconsole.log(states); // []\n```\n\n### Find Elements with Specific States\n\n```javascript\n// Get all node data in 'selected' state\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// Get all edge data in 'highlight' state\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### Check if Element is in Specific State\n\n```javascript\n// Check if element is in specific state\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('Is node selected:', isSelected);\nconsole.log('Is node highlighted:', isHighlight);\n```\n","packages/site/docs/manual/element/state.zh.md":"---\ntitle: 元素状态\norder: 2\n---\n\n## 什么是元素状态\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n元素状态(State)是指图中元素（节点、边、组合）在不同交互场景下的视觉表现形式。比如当用户点击一个节点时，节点可能会变成\"选中\"状态并改变颜色；当鼠标悬停在边上时，边可能会进入\"高亮\"状态并加粗显示。\n\n**简单来说，状态让元素能够根据用户的操作或业务逻辑动态改变外观。**\n\n### 状态的特点\n\n- **多状态共存**：一个元素可以同时拥有多个状态，比如既是\"选中\"又是\"高亮\"\n- **样式叠加**：多个状态的样式会叠加在一起，后设置的状态样式优先级更高\n- **完全自定义**：除了内置状态，您可以创建任何符合业务需求的自定义状态\n\n## 内置状态类型\n\nG6 提供了一些常用的内置状态，您可以直接使用：\n\n| 状态名      | 说明       | 典型使用场景       |\n| ----------- | ---------- | ------------------ |\n| `selected`  | 选中状态   | 用户点击选择元素时 |\n| `active`    | 激活状态   | 当前正在交互的元素 |\n| `highlight` | 高亮状态   | 需要强调显示的元素 |\n| `inactive`  | 非活跃状态 | 淡化显示非关注元素 |\n| `disabled`   | 禁用状态   | 不可交互的元素     |\n\n> 💡 **提示**：这些内置状态并非必须使用，您完全可以根据业务需求定义自己的状态名称。\n\n## 配置状态样式\n\n### 基础配置\n\n在创建图实例时，为不同状态配置相应的样式：\n\n```javascript\nconst graph = new Graph({\n  // 节点的状态样式配置\n  node: {\n    // 默认样式（无状态时的样式）\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // 各种状态下的样式\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // 边的状态样式配置\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // 组合的状态样式配置\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### 自定义状态\n\n您可以创建任何符合业务需求的自定义状态：\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // 自定义状态：错误\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // 虚线边框\n      },\n      // 自定义状态：成功\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // 自定义状态：警告\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // 添加图标\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## 设置元素状态\n\n### 数据中设置初始状态\n\n在数据中为元素设置初始状态：\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // 初始为选中状态\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // 初始为禁用状态\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // 初始有多个状态\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // 边的初始状态\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### 动态设置状态\n\n通过 API 动态改变元素状态：\n\n```javascript\n// 设置单个元素的单个状态\ngraph.setElementState('node1', 'selected');\n\n// 设置单个元素的多个状态\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// 批量设置多个元素的状态\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### 状态的叠加效果\n\n当元素有多个状态时，样式会按顺序叠加：\n\n```javascript\n// 假设节点同时有 selected 和 highlight 状态\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// 最终样式 = 默认样式 + selected状态样式 + highlight状态样式\n// 如果有样式冲突，后面的状态样式会覆盖前面的\n```\n\n## 清除元素状态\n\n### 清除所有状态\n\n将元素恢复到默认状态（无任何状态）：\n\n```javascript\n// 清除单个元素的所有状态\ngraph.setElementState('node1', []);\n\n// 批量清除多个元素的状态\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### 清除特定状态\n\n如果元素有多个状态，您可以只清除其中的某些状态：\n\n```javascript\n// 假设 node1 当前有 ['selected', 'highlight', 'active'] 三个状态\n// 现在只想保留 'selected' 状态，清除其他状态\ngraph.setElementState('node1', ['selected']);\n\n// 或者获取当前状态，然后过滤掉不需要的状态\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### 清除所有元素的特定状态\n\n```javascript\n// 清除所有节点的 'highlight' 状态\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## 查询元素状态\n\n### 获取元素状态\n\n```javascript\n// 获取指定元素的所有状态\nconst states = graph.getElementState('node1');\nconsole.log(states); // 例如：['selected', 'highlight']\n\n// 如果元素没有任何状态，返回空数组\nconsole.log(states); // []\n```\n\n### 查找特定状态的元素\n\n```javascript\n// 获取所有处于 'selected' 状态的节点数据\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// 获取所有处于 'highlight' 状态的边数据\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### 判断元素是否处于某状态\n\n```javascript\n// 检查元素是否处于特定状态\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('节点是否选中:', isSelected);\nconsole.log('节点是否高亮:', isHighlight);\n```\n","packages/site/docs/manual/extension/3d.en.md":"---\ntitle: g6-extension-3d\n---\n","packages/site/docs/manual/extension/3d.zh.md":"---\ntitle: g6-extension-3d\n---\n","packages/site/docs/manual/faq.en.md":"---\ntitle: FAQ\norder: 13\n---\n\n### What is the Difference Between Extension and Plugin?\n\n`Extension` is a concept in G6 that collectively refers to all types of registrable content, including elements, behaviors, layouts, and plugins, among others.\n\n`Plugin` represents a flexible extension mechanism provided by G6 and is a special type of `Extension`.\n\n### Set Text Overflow Ellipsis\n\nTaking `label` as an example, you can set `labelWordWrap` and `labelWordWrapWidth` to achieve text overflow ellipsis.\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### Key Press Not Working\n\nSome plugins or behaviors support configuring key press triggers. Please use standard key names, such as `Control`, `Shift`, `Alt`, `Meta`, as well as letters, numbers, symbols, and so on.\n\n### Canvas Not Updating After Data Update\n\nEnsure that you call `graph.draw()` or `graph.render()` to update the canvas after updating the data.\n\n> G6 merges differences and updates the canvas uniformly after `draw` or `render` for multiple data updates to improve performance.\n\n### How to Resolve Interaction Conflicts\n\nWhen multiple interactions conflict with each other, you can set the enable timing of interactions to avoid multiple interactions being triggered simultaneously.\n\nTaking `drag-canvas` and `brush-select` as an example, if you directly configure these two interactions, dragging on the canvas will cause interaction exceptions. You can disable the `drag-canvas` interaction when the `shift` key is pressed.\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\nAt this point, when the `shift` key is pressed, the `drag-canvas` interaction will be disabled, and the `brush-select` interaction will not be affected.\n\n### Difference Between `draw` and `render`\n\nBoth `draw` and `render` execute drawing operations, but `render` additionally performs **layout** and **auto fit** operations based on `draw`.\n\nYou can simply understand it as: `render` = `draw` + `layout` + `fitView`/`fitCenter`.\n\n### Style in Data Not Effective\n\nReason 1: The style in the data is overridden by the style in the style mapping.\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // No matter what the style in the data is, it will be overridden by the style here\n    }\n  }\n}\n```\n\nSolution: Use a callback method to prioritize obtaining styles from the data to improve data priority.\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### Residual content in the canvas\n\nWhen using the Canvas renderer for drawing, residual content may appear in the canvas, which is referred to as \"dirty rectangles\". This phenomenon occurs because the underlying rendering engine improves performance by only drawing the parts that have changed each time, rather than clearing the entire canvas.\n\nHowever, when the graphics in the canvas change, there may be cases where some graphics are not correctly cleared, resulting in residual content.\n\nYou can solve this issue by:\n\n1. Using the SVG or WebGL renderer;\n2. Checking whether there are illegal values in the element of the nodes, such as null, NaN, and so on;\n3. Using integers as much as possible for numeric style values, such as r, width, height, fontSize, and so on.\n\n### Use Vanilla JavaScript Object Data\n\nPlease avoid using Vue reactive data, Immer.js, and other wrapped objects as the data source for G6, as these objects will be deeply monitored internally, and even freeze the data object, causing G6 to fail to operate normally.\n\n### G6 project startup Warning during compilation Type mapping points to non-existent path\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> Explanation: [@antv/util](https://github.com/antvis/util) is a tool library that AntV relies on at the bottom.\n\nFrom the partial warning message above, we can see that there is a problem with the type declaration file of the `@antv/util` tool library that G6 depends on.**This warning does not affect the normal operation of the project**.\n\nThis message will only appear in TypeScript projects. The following are ways to turn it off:\n\n1. Turn off TypeScript sourcemap\n\nCreate a `.env` file in the root directory of the project and add the following content:\n\ntext\nGENERATE_SOURCEMAP=false\ntext\n\n2. Disable sourcemapping for specific modules\n\nDisabling sourcemapping directly is too simple and crude, and is not user-friendly for developers who may have debugging needs. Therefore, sourcemapping can be disabled for specific modules by configuring the build tool separately.\n\na. webpack configuration\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite configuration\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // Ignore warnings for specific modules\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // For other warnings, use the default warning handling\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### Manually configuring the color palette does not take effect\n\n> In v5, the built-in colors are: export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\nThe solution is as follows:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line plugin does not take effect\n\n> In v5, built-in plugins include `bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [Detailed reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\nActual reason: The parent container of the `graph` instance, `<div ref={containerRef} />`, does not have a height set, so the G6 Graph may not be able to calculate the correct size.**If you want to enable the `grid-line` canvas plugin, you need to set the width and height of the parent element, which is not valid in the graph configuration**.\n\n### v5 cannot use the tree layout\n\nUse `new Graph({xxx})` uniformly.\n\n> In v5, built-in layouts include `antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [Specific reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5 merges the graph and tree graph, no longer creates the tree graph layout by instantiating `G6.TreeGraph`, and removes this method. For details, see [Features - Merge Graph and Tree Graph](https://g6.antv.antgroup.com/manual/feature#-%E5%90%88%E5%B9%B6%E5%9B%BE%E4%B8%8E%E6%A0%91%E5%9B%BE)\n\n### edge does not have a connection at the center of the node\n\nis configured [portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter) to `true`.\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### How to dynamically set the width of a node based on the length of the label content\n\nImplementation solution: [#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent node event object type is not complete\n\nYou can manually specify the `IPointerEvent` type. For details, see [#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### Remove the parent combo of the node\n\nUpdate the node data, set the `combo` value to `null`.\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","packages/site/docs/manual/faq.zh.md":"---\ntitle: 常见问题\norder: 13\n---\n\n### Extension 和 Plugin 有什么区别？\n\n`Extension` 是 G6 中的一个概念，是所有可注册内容的统称，包含元素、交互、布局、插件等。\n\n`Plugin` 是 G6 提供的灵活扩展机制，是一种特殊的 `Extension`。\n\n### 设置文本超出省略\n\n以 label 为例，设置 `labelWordWrap` 和 `labelWordWrapWidth` 即可实现文本超出省略。\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### 按键不生效\n\n一些插件或交互支持配置触发按键，请使用标准按键名：如 `Control`, `Shift`, `Alt`, `Meta`，以及字母、数字、符号等。\n\n### 更新数据后画布不更新\n\n请确保数据更新后调用 `graph.draw()` 或者 `graph.render()` 更新画布。\n\n> G6 对于多次数据更新，会在 `draw` 或 `render` 后合并差异并统一更新画布，以提高性能。\n\n### 交互有冲突如何解决\n\n当多个交互之间存在冲突时，你可以设置交互的启用时机来避免多个交互被同时触发。\n\n以 `drag-canvas` 和 `brush-select` 为例，如果直接配置这两个交互，当指针在画布上进行拖拽时，会导致交互异常。可以设置为在按下 `shift` 键时禁用 `drag-canvas` 交互。\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\n此时，当按下 `shift` 键时，`drag-canvas` 交互会被禁用，`brush-select` 交互会不会受到影响。\n\n### draw 和 render 的区别\n\n`draw` 和 `render` 都会执行绘制操作，但 `render` 会在 `draw` 的基础上额外进行**布局**、**视图自适应**操作。\n\n可以简单理解为：`render` = `draw` + `layout` + `fitView`/`fitCenter`。\n\n### 数据中的样式不生效\n\n原因一：被样式映射中的样式覆盖\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // 无论数据中的样式如何，都会被这里的样式覆盖\n    }\n  }\n}\n```\n\n解决方式：使用回调方法，优先从数据中获取样式以提高数据优先级\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### 画布中出现残影\n\n在使用 Canvas 渲染器进行绘制时，可能会出现残影现象，这些图形被称为“脏矩形”。该现象出现的原因是底层渲染引擎为了提高性能，每次绘制时只会绘制发生变化的部分，而不会清空整个画布。\n\n但是，当画布中的图形发生变化时，可能会出现部分图形未被正确清除的情况，从而导致残影现象。\n\n可以通过以下方式解决：\n\n1. 使用 SVG 或 WebGL 渲染器；\n2. 检查节点中的图形样式中是否存在非法值，例如 null、NaN 等；\n3. 尽量使用整数作为数值型的样式值，例如 r、width、height、fontSize 等；\n\n### 使用原生 JavaScript 对象数据\n\n请避免使用 Vue 响应式数据、Immer.js 等包装过的对象作为 G6 的数据源，因为这些对象会在内部进行深度监听，甚至冻结数据对象，导致 G6 无法正常操作数据。\n\n### G6 项目启动在编译时警告类型映射指向不存在路径\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> 解释: [@antv/util](https://github.com/antvis/util) 是 AntV 底层依赖的工具库。\n\n从上面部分警告信息中我们可以得知是 G6 依赖的 `@antv/util` 工具库的类型声明文件存在问题，**该警告不影响项目正常运行**。\n\n该信息只会在 TypeScript 项目中出现，关闭办法如下:\n\n1. 关闭TypeScript 的sourcemap源码映射\n\n在项目根目录下创建`.env`文件，并添加以下内容:\n\n```text\nGENERATE_SOURCEMAP=false\n```\n\n2. 单独禁用指定模块的源码映射\n\n直接禁用sourcemap映射的方式过于简单粗暴，对于部分可能有调试需求的开发者不太友好，所以也可以通过在构建工具单独配置，单独禁用这些特定模块的源码映射。\n\na. webpack配置\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite配置\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // 忽略特定模块的警告\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // 对于其他警告,使用默认的警告处理\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### 手动配置色板颜色不生效\n\n> 在 v5 中内置颜色有：export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\n解决办法如下:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line 插件不生效\n\n> 在 v5 中内置插件有`bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\n实际原因: `graph`实例的父容器`<div ref={containerRef} />`本身没有设置高度，G6 Graph图 可能无法正确计算出合适的大小。**如果要启用`grid-line`画布插件，需要给父元素 div 设置宽高，在 graph 配置中是无效的**。\n\n### v5无法使用树图布局\n\n统一使用`new Graph({xxx})`。\n\n> 在 v5 中内置布局有`antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5合并了图和树图，不再通过实例化`G6.TreeGraph`创建树图布局，并且移除该方式。具体参考[特性-合并图与树图](/manual/whats-new/feature#🌲-合并图与树图)\n\n### edge 没有连接在 node 的边缘中心\n\n配置[portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter)为 `true`。\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### 如何根据label内容长度动态设置node宽度\n\n参考方案：[#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent节点事件对象类型不齐全问题\n\n可以手动指定`IPointerEvent`类型。具体参考[#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### 解除节点所在组合\n\n更新节点数据，`combo` 值设置为 `null`。\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","packages/site/docs/manual/further-reading/3d.en.md":"---\ntitle: Use 3D\norder: 5\n---\n\n## Install Dependencies\n\nBefore using 3D capabilities, please install the 3D extension package first:\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\nThe extension package exports the following:\n\n- renderer: 3D renderer\n\n**Elements**\n\n- Capsule: capsule node\n- Cone: cone node\n- Cube: cube node\n- Cylinder: cylinder node\n- Sphere: sphere node\n- Torus: torus node\n- Line3D: 3D line\n\n**Layout**\n\n- D3Force3DLayout: 3D force-directed layout\n\n**Behaviors**\n\n- DragCanvas3D: drag canvas\n- ObserveCanvas3D: observe canvas\n- RollCanvas3D: rotate canvas\n- ZoomCanvas3D: zoom canvas\n\n**Plugin**\n\n- Light: light source\n\n## Register Extensions\n\nThe following extensions are required:\n\n- renderer\n- at least one 3D node\n- Line3D\n- Light\n\n> The renderer does not need to be registered, it can be passed in during the instantiation of Graph.\n\nRegister as follows:\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## Create 3D Graph\n\nAfter completing the above steps, you can create a 3D graph:\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... other options\n  // use 3d renderer\n  renderer,\n  node: {\n    type: 'sphere', // use 3d node\n    style: {\n      materialType: 'phong', // use Phong material\n    },\n  },\n  edge: {\n    type: 'line3d', // use 3D edge\n  },\n  plugins: [\n    {\n      type: 'light', // Add light source\n      // configure directional light\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\nYou can also refer to:\n\n- [Lite Solar System](/examples/feature/default/#lite-solar-system)\n- [3D Force Layout](/examples/layout/force-directed/#3d-force)\n\n## Tips\n\n`@antv/g6` has a built-in registered plugin for CameraSetting for camera configuration, refer to [plugin](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts).\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","packages/site/docs/manual/further-reading/3d.zh.md":"---\ntitle: 使用 3D\norder: 5\n---\n\n## 安装依赖\n\n在使用 3D 能力之前，请首先安装 3D 扩展包：\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\n该扩展包导出了以下内容：\n\n- renderer：3D 渲染器\n\n**元素**\n\n- Capsule：胶囊节点\n- Cone：圆锥节点\n- Cube：立方体节点\n- Cylinder：圆柱节点\n- Sphere：球体节点\n- Torus：圆环节点\n- Line3D：3D 线\n\n**布局**\n\n- D3Force3DLayout：3D 力导向布局\n\n**交互**\n\n- DragCanvas3D：拖拽画布\n- ObserveCanvas3D：观察画布\n- RollCanvas3D：旋转画布\n- ZoomCanvas3D：缩放画布\n\n**插件**\n\n- Light：光源\n\n## 注册扩展\n\n其中下列扩展是必须的：\n\n- renderer\n- 至少一个 3D 节点\n- Line3D\n- Light\n\n> renderer 无需注册，实例化 Graph 过程中传入即可。\n\n使用如下方式进行注册：\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## 创建 3D 图\n\n完成上述步骤后，即可创建 3D 图：\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 3D 渲染器\n  renderer,\n  node: {\n    type: 'sphere', // 使用 3D 节点\n    style: {\n      materialType: 'phong', // 使用 Phong 材质\n    },\n  },\n  edge: {\n    type: 'line3d', // 使用 3D 边\n  },\n  plugins: [\n    {\n      type: 'light', // 添加光源\n      // 配置方向光\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n你可以参考以下示例：\n\n- [精简太阳系](/examples/feature/default/#lite-solar-system)\n- [3D 力导向布局](/examples/layout/force-directed/#3d-force)\n\n## 其他\n\n`@antv/g6` 中内置注册了 `CameraSetting` 插件，可用于配置相机，具体可参考[插件](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts)。\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","packages/site/docs/manual/further-reading/bundle.en.md":"---\ntitle: Bundle Project\norder: 6\n---\n\nIn general, if you are using modern build tools such as Webpack, Rollup, or ESBuild, you can easily build projects that depend on `@antv/g6`.\n\nSome build tools, such as Vite, use ESBuild as the underlying tool, so you can refer to ESBuild's configuration.\n\nBelow are some example configurations that you can refer to when building your project. If you find that these configurations do not work properly, make sure that your build tool version is up to date.\n\n## Bundle Project with Webpack\n\n1. Make sure that `webpack` and `webpack-cli` are installed in your project:\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. Refer to the following `webpack.config.js` for configuration:\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx webpack\n```\n\n> The above configuration works with `\"webpack\": \"^5.94.0\"`, `\"webpack-cli\": \"^5.1.4\"`.\n\n:::error{title=Webpack4}\n⚠️ It is strongly recommended that projects use Webpack 5. If you are using Webpack 4, follow the steps below to configure:\n\n1. Install the necessary dependencies: `babel-loader` (<9), `@babel/preset-env`, `@open-wc/webpack-import-meta-loader`\n\n> If you are using TypeScript, you also need to install `ts-loader`.\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. Modify the `webpack.config.js` configuration:\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> This configuration is for a standard webpack project. If you are using vue-cli, you should REMOVE the `mode: 'production'` option as it is unnecessary.\n\n## Bundle Project with Rollup\n\n1. First, make sure that `rollup` and the necessary plugins are installed in your project:\n\n- `@rollup/plugin-commonjs`: Used to load CommonJS modules\n- `@rollup/plugin-node-resolve`: Used to load Node.js modules\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. Refer to the following `rollup.config.js` for configuration:\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx rollup -c\n```\n\n## Bundle Project with ESBuild\n\n1. First, make sure that `esbuild` is installed in your project:\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. Run the build command:\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","packages/site/docs/manual/further-reading/bundle.zh.md":"---\ntitle: 项目打包\norder: 6\n---\n\n通常情况下，如果你使用的现代构建工具，如 Webpack、Rollup 或 ESBuild，你可以很容易地构建依赖于 `@antv/g6` 的项目。\n\n一些构建工具例如 Vite，其底层是使用 ESBuild，因此你可以参考 ESBuild 的配置。\n\n下面是一些示例配置，你可以参考这些配置来构建你的项目。如果你发现这些配置无法正常工作，请确保你的构建工具版本较新。\n\n## 使用 Webpack 打包项目\n\n1. 确保你的项目中已经安装了 `webpack` 和 `webpack-cli`：\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. 参考下面的 `webpack.config.js` 进行配置：\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx webpack\n```\n\n> 上述配置在：\"webpack\": \"^5.94.0\"，\"webpack-cli\": \"^5.1.4\" 可以正常工作。\n\n:::error{title=Webpack4}\n⚠️ 强烈建议项目使用 Webpack 5，如果你使用的是 Webpack 4，按以下步骤配置：\n\n1. 安装相关依赖：babel-loader(<9)、@babel/preset-env、@open-wc/webpack-import-meta-loader\n\n> 如果你使用的 typescript，还需要安装 ts-loader\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. 修改 `webpack.config.js` 配置：\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> 如果你使用的是 vue-cli，请移除 mode: 'production' 配置，否则可能会影响开发模式下的构建性能。\n\n## 使用 Rollup 打包项目\n\n1. 首先，确保你的项目中已经安装了 `rollup` 及必要的插件：\n\n- `@rollup/plugin-commonjs`：用于加载 CommonJS 模块\n- `@rollup/plugin-node-resolve`：用于加载 Node.js 模块\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. 参考下面的 `rollup.config.js` 进行配置：\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx rollup -c\n```\n\n## 使用 ESBuild 打包项目\n\n1. 首先，确保你的项目中已经安装了 `esbuild`：\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. 执行构建命令：\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","packages/site/docs/manual/further-reading/coordinate.en.md":"---\ntitle: coordinate\norder: 2\n---\n\n## Overview\n\nThere are three coordinate systems in G6 5.0: Canvas, Viewport, and Client.\n\n### Canvas Coordinate System\n\nThe coordinate system used when drawing G6 elements is not affected by camera zooming or panning. To change the position of an element, you need to directly modify the element's position properties (x/y/z).\n\nThe canvas space is theoretically infinite. In the initial state (no panning, zoom ratio is 1), the origin of the canvas coordinate system is located at the upper-left corner of the viewport.\n\n### Viewport Coordinate System\n\nThe viewport coordinate system is the projection of the camera coordinate system. When the camera pans or zooms, the position of elements in the canvas will also change in the viewport coordinate system.\n\nThe size of the viewport is the size of the canvas DOM container. The origin of the viewport coordinate system is located at the upper-left corner of the viewport, with the x-axis pointing to the right and the y-axis pointing down.\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### Client Coordinate System\n\nThe client coordinate system has the browser's upper-left corner as the origin, with the x-axis pointing to the right and the y-axis pointing down.\n\nThe following figure describes the relationship between the viewport coordinate system and the client coordinate system:\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Coordinate System Conversion\n\nG6 provides methods for coordinate system conversion, making it easy to convert between different coordinate systems.\n\n- Canvas coordinate system to viewport coordinate system: [getViewportByCanvas](/en/api/coordinate#graphgetviewportbycanvaspoint)\n- Client coordinate system to canvas coordinate system: [getCanvasByClient](/en/api/coordinate#graphgetcanvasbyclientpoint)\n- Viewport coordinate system to canvas coordinate system: [getCanvasByViewport](/en/api/coordinate#graphgetcanvasbyviewportpoint)\n- Canvas coordinate system to client coordinate system: [getClientByCanvas](/en/api/coordinate#graphgetclientbycanvaspoint)\n\nOther related APIs are also provided:\n\n- Get the viewport center in viewport coordinates: [getCanvasCenter](/en/api/viewport#graphgetcanvascenter)\n- Get the viewport center in canvas coordinates: [getViewportCenter](/en/api/viewport#graphgetviewportcenter)\n- Get the position of the graph origin in the viewport coordinate system: [getPosition](/en/api/viewport#graphgetposition)\n","packages/site/docs/manual/further-reading/coordinate.zh.md":"---\ntitle: 坐标系\norder: 2\n---\n\n## 概述\n\n在 G6 5.0 中主要会涉及三个坐标系：画布坐标系(Canvas)、视口坐标系(Viewport)和浏览器坐标系(Client)。\n\n### 画布坐标系\n\nG6 元素绘制时所使用的坐标系，其不受相机缩放、平移的影响，要改变一个元素的位置，需要直接修改元素的位置属性(x/y/z)。\n\n画布空间理论上是无限大的，在初始状态下（无平移、缩放倍率为1），画布坐标系的原点位于视口左上角位置。\n\n### 视口坐标系\n\n视口坐标系是相机坐标系的投影，当相机发生平移、缩放时，画布中元素位置在视口坐标系中的位置也会发生变化。\n\n视口的大小即画布 DOM 容器的大小，视口坐标系的原点位于视口左上角位置，x 轴正方向向右，y 轴正方向向下。\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### 浏览器坐标系\n\n浏览器坐标系以浏览器左上角为原点，x 轴正方向向右，y 轴正方向向下。\n\n下图描述了视口坐标系和浏览器坐标系之间的关系：\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 坐标系转换\n\nG6 提供了坐标系转换的方法，可以方便地在不同坐标系之间进行转换。\n\n- 画布坐标系转视口坐标系：[getViewportByCanvas](/api/coordinate#graphgetviewportbycanvaspoint)\n- 浏览器坐标系转画布坐标系：[getCanvasByClient](/api/coordinate#graphgetcanvasbyclientpoint)\n- 视口坐标系转画布坐标系：[getCanvasByViewport](/api/coordinate#graphgetcanvasbyviewportpoint)\n- 画布坐标系转浏览器坐标系：[getClientByCanvas](/api/coordinate#graphgetclientbycanvaspoint)\n\n另外还提供了其他相关 API：\n\n- 获取视口中心的视口坐标：[getCanvasCenter](/api/viewport#graphgetcanvascenter)\n- 获取视口中心的画布坐标：[getViewportCenter](/api/viewport#graphgetviewportcenter)\n- 获取图原点在视口坐标系中的位置：[getPosition](/api/viewport#graphgetposition)\n","packages/site/docs/manual/further-reading/download-image.en.md":"---\ntitle: download-image\norder: 3\n---\n\nG6 5.0 only provides an API for exporting the canvas as a Base64 image ([toDataURL](/en/api/export-image#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=note}\nThe exported image may not contain the complete canvas content; the export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., and this content will not appear in the exported image.\n:::\n","packages/site/docs/manual/further-reading/download-image.zh.md":"---\ntitle: 下载图片\norder: 3\n---\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](/api/export-image#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","packages/site/docs/manual/further-reading/event.en.md":"---\ntitle: Event\norder: 0\n---\n\n## Overview\n\nThe event system in G6 is encapsulated based on the event system of [G](https://g.antv.antgroup.com/en/api/event/intro), providing a wider range of event types and more convenient methods for event binding and unbinding.\n\n## Event Types\n\nThe event types in G6 are mainly divided into the following categories:\n\n1. Graph events\n2. Canvas events\n3. Element events\n\n### Graph Events\n\nGraph events refer to events associated with the entire graph instance, such as the graph's rendering completion event, the graph's update event, etc. The complete list of graph events can be found at [GraphEvent](/en/api/event#graph-lifecycle-events-graphevent).\n\n#### Listening to Graph Events\n\nListening to graph events is consistent with the default event listening method. For example, to listen to the graph's rendering completion event:\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### Canvas Events\n\nCanvas events refer to events associated with the canvas, such as the canvas's click event, the canvas's drag event, etc. The complete list of canvas events can be found at [CanvasEvent](/en/api/event#canvas-events-canvasevent).\n\n#### Listening to Canvas Events\n\nFor example, to listen to the canvas's click event:\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### Element Events\n\nElement events primarily refer to events that are triggered on element objects, such as a node's drag event, an edge's click event, etc. Elements are categorized into three types: nodes (`node`), edges (`edge`), and combos (`combo`). The complete list of corresponding events can be found at: [NodeEvent](/en/api/event#node-events-nodeevent), [EdgeEvent](/en/api/event#edge-events-edgeevent), [ComboEvent](/en/api/event#combo-events-comboevent).\n\n#### Listening to Element Events\n\nSimilar to canvas events, for example, to listen to a node's drag event and an edge's click event:\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## Event Listening and Unlistening\n\nG6 provides the following APIs for event listening and unlistening:\n\n### on\n\nAdd an event listener\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\nRemove an event listener\n\n```typescript\ngraph.off('event_name', handler);\n```\n\nWhen no arguments are passed, it will remove all event listeners:\n\n```typescript\ngraph.off();\n```\n\n### once\n\nAdd a one-time event listener, which means the event listener will be automatically removed after the event is triggered\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\nIf you want to manually trigger an event, you can use the `emit` method:\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","packages/site/docs/manual/further-reading/event.zh.md":"---\ntitle: 事件\norder: 0\n---\n\n## 概述\n\nG6 中的事件系统是在 [G](https://g.antv.antgroup.com/api/event/intro) 的事件系统基础上进行了封装，提供了更多的事件类型，以及更加方便的事件绑定和解绑方法。\n\n## 事件类型\n\nG6 中的事件类型主要分为以下几类：\n\n1. 图(Graph)事件\n2. 画布(Canvas)事件\n3. 元素(Element)事件\n\n### 图事件\n\n图事件是指与整个图实例相关的事件，例如图的渲染完成事件、图的更新事件等。图事件的完整列表见[GraphEvent](/api/event#图表生命周期事件-graphevent)。\n\n#### 监听图事件\n\n图事件的监听与默认的事件监听方式一致，例如监听图的渲染完成事件：\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### 画布事件\n\n画布事件是指与画布相关的事件，例如画布的点击事件、画布的拖拽事件等。画布事件的完整列表见[CanvasEvent](/api/event#画布事件-canvasevent)。\n\n#### 监听画布事件\n\n例如监听画布的点击事件：\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### 元素事件\n\n元素事件主要指在元素对象上触发的事件，例如节点的拖拽事件、边的点击事件等。元素分为节点(`node`)、边(`edge`)、组合(`combo`)三类，对应的事件完整列表分别见：[NodeEvent](/api/event#节点事件-nodeevent) 、[EdgeEvent](/api/event#边事件-edgeevent)、[ComboEvent](/api/event#combo事件-comboevent)。\n\n#### 监听元素事件\n\n与画布事件类似，例如监听节点的拖拽和边的点击事件：\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## 事件监听与解除\n\nG6 提供以下 API 用于事件监听和解除：\n\n### on\n\n添加事件监听\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\n移除事件监听\n\n```typescript\ngraph.off('event_name', handler);\n```\n\n当不传入任何参数时，会移除所有事件监听：\n\n```typescript\ngraph.off();\n```\n\n### once\n\n添加一次性事件监听，即事件触发后会自动移除事件监听\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\n如果你想手动触发一个事件，可以使用 `emit` 方法：\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","packages/site/docs/manual/further-reading/iconfont.en.md":"---\ntitle: Using Iconfont\norder: 4\n---\n\n## Overview\n\nWhy use iconfont? It offers great compatibility, a wide variety of icons, and multicolor options. For more details, please visit the [Alibaba Iconfont Platform](https://www.iconfont.cn).\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## Usage\n\n### Download Font Icons\n\nFirst, you need to download the desired font icons from the [iconfont](https://www.iconfont.cn) website. Create a project, select the required icons, and then download the generated icon files.\n\n### Add Font Icons\n\nAfter downloading, place the directory containing the icon font files (typically including `.eot`, `.woff`, `.ttf`, and `.svg` files, as well as the `iconfont.css` stylesheet) into your project.\n\nYou can choose how to include them. Below is an example of how to include them in HTML:\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### Using the Font\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // Corresponds to the `font-family` value in iconfont.css\n      iconText: '\\ue7f1', // Corresponds to the `content` value in iconfont.css, make sure to add `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### Utility Function `getIcon()`\n\nTo make it easier to retrieve icons, you can create a utility function `getIcon`. This function reads the icon information from the `iconfont.json` file and returns the corresponding Unicode character. Note that manually concatenating Unicode (`\\\\u${icon.unicode}`) won't work. Refer to [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) for details.\n\nFirst, ensure you have an `iconfont.json` file containing the detailed icon information.\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\nUse it in your project:\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","packages/site/docs/manual/further-reading/iconfont.zh.md":"---\ntitle: 使用 iconfont\norder: 4\n---\n\n## 概述\n\n为什么使用 iconfont？ 兼容性好、种类多、多色等。在此不做过多介绍，请直接移步 [阿里巴巴-iconfont 平台](https://www.iconfont.cn)。\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## 使用\n\n### 下载字体图标\n\n首先，你需要从 [iconfont](https://www.iconfont.cn) 网站下载所需的图标字体。创建一个项目并选择所需的图标，然后下载生成的图标文件。\n\n### 添加字体图标\n\n下载完成后，将包含图标字体文件的目录（通常包括 `.eot`、`.woff`、`.ttf` 和 `.svg` 文件，以及 `iconfont.css` 样式文件）放入你的项目中。\n\n引入方式可自行选择，下面为在 HTML 中引入的例子：\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### 使用字体\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // 对应 iconfont.css 中的 `font-family` 属性值\n      iconText: '\\ue7f1', // 对应 iconfont.css 中的 `content` 属性值，注意加 `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### 工具函数 `getIcon()`\n\n为了更方便地获取图标，可以创建一个工具函数 `getIcon`。该函数会从图标文件 `iconfont.json` 中读取图标信息并返回相应的 Unicode 字符。这里注意，手动拼接 unicode 是不行的（`\\\\u${icon.unicode}`）。详细参考 [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)。\n\n首先，确保你有一个 `iconfont.json` 文件，包含图标的详细信息。\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type: string) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\n在项目中使用：\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","packages/site/docs/manual/further-reading/renderer.en.md":"---\ntitle: renderer\norder: 1\n---\n\nG6 uses Canvas as the default renderer, but also supports rendering with SVG and WebGL. To switch to the SVG or WebGL renderer, simply pass the `renderer` parameter during initialization.\n\n## Using the SVG Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the SVG renderer here\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## Using the WebGL Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the WebGL renderer here\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## Using Different Renderers for Different Layers\n\nG6 uses layered canvases for rendering, so `renderer` is a callback function that takes the canvas type as a parameter and returns the renderer instance. If you want to use different renderers on different canvases, you can configure it like this:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // The main canvas uses the WebGL renderer, and the other canvases use the SVG renderer\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## Switch Renderers Dynamically\n\nG6 does not provide a API to switch the renderer, but you can still update the `renderer` option through the `setOptions` method.\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// Use the WebGL renderer by default\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// Switch to the SVG renderer\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","packages/site/docs/manual/further-reading/renderer.zh.md":"---\ntitle: 渲染器\norder: 1\n---\n\nG6 默认使用 Canvas 作为渲染器，但也支持通过 SVG 和 WebGL 进行渲染，要切换到 SVG 或 WebGL 渲染器，只需在初始化时传入 `renderer` 参数即可。\n\n## 使用 SVG 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 SVG 渲染器\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## 使用 WebGL 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 WebGL 渲染器\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## 分层使用不同的渲染器\n\nG6 采用了分层画布进行渲染，因此 `renderer` 是一个回调函数，参数是画布类型，返回渲染器实例，如果你想在不同的画布上使用不同的渲染器，可以这样配置：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // 主画布使用 WebGL 渲染器，其他画布使用 SVG 渲染器\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## 动态切换渲染器\n\nG6 没有提供单独的 API 来切换渲染器，但你仍可以通过 `setOptions` 方法来更新 `renderer` 参数：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// 初始化时使用 WebGL 渲染器\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// 切换到 SVG 渲染器\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","packages/site/docs/manual/getting-started/installation.en.md":"---\ntitle: Installation\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\nImport G6 in the code:\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\nVisit [G6 npm Example](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) to view the complete example code.\n\n## CDN\n\n`@antv/g6` Available on multiple CDNs:\n\n- unpkg: https://unpkg.com/@antv/g6@5/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\nImport G6 using a `script` tag:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\nVisit [G6 CDN Example](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) to view the complete example code.\n","packages/site/docs/manual/getting-started/installation.zh.md":"---\ntitle: 安装\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\n在代码中引入 G6：\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\n访问 [G6 npm 示例](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) 查看完整示例代码。\n\n## CDN\n\n`@antv/g6` 在多个 CDN 上提供：\n\n- unpkg: https://unpkg.com/@antv/g6@latest/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\n使用 `script` 标签引入 G6：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n访问 [G6 CDN 示例](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) 查看完整示例代码。\n","packages/site/docs/manual/getting-started/integration/angular.en.md":"---\ntitle: angular\norder: 2\n---\n\nRefer to the example below, you can use G6 in Angular, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/angular.zh.md":"---\ntitle: 在 Angular 中使用\norder: 2\n---\n\n参考下面的示例，你可以在 Angular 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/react.en.md":"---\ntitle: react\norder: 0\n---\n\n## Non-Strict Mode\n\nRefer to the example below, you can use G6 in React, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## Strict Mode\n\nIn strict mode, React intentionally mounts, unmounts, and remounts components in development. Create the Graph instance inside an effect, keep it in a ref, and destroy it in the cleanup callback so the first development-only mount does not leave a stale graph behind. The following complete example also shows how to register and render a React node.\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","packages/site/docs/manual/getting-started/integration/react.zh.md":"---\ntitle: 在 React 中使用\norder: 0\n---\n\n:::info{title=建议}\n如果你需要更完善的 React 与 G6 集成解决方案，可以使用 AntV 官方封装库 [`@antv/graphin`](https://github.com/antvis/graphin)。\n:::\n\n## 非严格模式\n\n参考下面的示例，你可以在 React 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## 严格模式\n\n在严格模式下，React 会在开发环境中有意执行挂载、卸载、再挂载。请把 Graph 实例放在 effect 里创建，用 ref 保存，并在清理函数中销毁，这样第一次开发态挂载不会留下旧实例。下面的完整示例同时演示了如何注册和渲染 React 节点。\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","packages/site/docs/manual/getting-started/integration/vue.en.md":"---\ntitle: vue\norder: 1\n---\n\n:::warning\nPlease do not pass Vue reactive data directly to the G6 instance, which may cause G6 to fail to render correctly, or even cause the page to crash.\n:::\n\nRefer to the example below, you can use G6 in Vue, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","packages/site/docs/manual/getting-started/integration/vue.zh.md":"---\ntitle: 在 Vue 中使用\norder: 1\n---\n\n:::warning{title=注意}\n请不要将 Vue 响应式数据直接传递给 G6 实例，这可能会导致 G6 无法正确渲染，甚至导致页面崩溃。\n:::\n\n参考下面的示例，你可以在 Vue 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","packages/site/docs/manual/getting-started/quick-start.en.md":"---\ntitle: Quick Start\norder: 0\n---\n\n## Online Experience with G6\n\nVisit [Chart Examples](/en/examples) to experience G6 online without any environment setup.\n\n## Creating a Simple Graph\n\nIn this example, we will create a simple graph using G6 based on an HTML page.\n\nCopy the following code into an HTML file and then open this file in a browser:\n\n```html\n<!-- Prepare a container -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- Import G6's JS file -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\nYou will get a graph as shown below:\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\nLet's analyze the following code snippet:\n\n1. First, we create a `div` element to serve as the container for the graph:\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. Then, include the G6's JS file:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. Use the `fetch` method to obtain the graph's data:\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. Finally, create an instance of the graph, pass in the configuration object, and call the `render` method to render the graph:\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\nIf you are using frameworks such as React, Vue, Angular, etc., you can refer to:\n\n- [Using G6 in React](./integration/react)\n- [Using G6 in Vue](./integration/vue)\n- [Using G6 in Angular](./integration/angular)\n","packages/site/docs/manual/getting-started/quick-start.zh.md":"---\ntitle: 快速开始\norder: 0\n---\n\n## 在线体验 G6\n\n访问 [图表示例](/examples) 无需任何环境配置即可在线体验 G6。\n\n## 创建一个简单的图\n\n在本例子中，我们将基于 HTML 页面使用 G6 创建一个简单的图。\n\n将下面的代码复制到一个 HTML 文件中，然后在浏览器中打开这个文件：\n\n```html\n<!-- 准备一个容器 -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- 引入 G6 的 JS 文件 -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\n会得到如下所示的图：\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\n下面分析一下这段代码：\n\n1. 首先我们创建一个 `div` 元素作为图的容器：\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. 然后引入 G6 的 JS 文件：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. 使用 `fetch` 方法获取图的数据：\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. 最后创建一个图实例，传入配置对象，并调用 `render` 方法渲染图：\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n如果你使用 React、Vue、Angular 等框架，可以查看：\n\n- [在 React 中使用 G6](./integration/react)\n- [在 Vue 中使用 G6](./integration/vue)\n- [在 Angular 中使用 G6](./integration/angular)\n","packages/site/docs/manual/getting-started/step-by-step.en.md":"---\ntitle: Step-by-step guide\norder: 3\n---\n\nThis tutorial will guide you through the development of a G6 chart from scratch, and along the way, you will learn and understand the main concepts of G6.\n\n## Create Application\n\nWe will use Vite to create a simple front-end application.\n\n### Initialization\n\nFirst, create an empty directory:\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\nInitialize the project:\n\n```bash\nnpm init -y\n```\n\nInstall G6:\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite is a new type of front-end build tool that is based on ESModule and can quickly start up projects.\n\nInstall Vite:\n\n```bash\nnpm install vite --save-dev\n```\n\nAdd a start script to the `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### Create Files\n\nCreate the `index.html` and `main.ts` files with the following content:\n\n**index.html**:\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### Start project\n\n```bash\nnpm run dev\n```\n\nOpen a web browser and visit the address output in the terminal (typically: http://127.0.0.1:5173/), and you will see a pop-up displaying \"Hello, G6!\".\n\n## Creating a Simple Graph\n\nNext, we will create a simple chart using G6.\n\n### Preparing the Data\n\nG6 uses JSON-formatted data to describe the graph, which usually includes nodes and edges. We will use the following prepared data:\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\nThe data includes two nodes and one edge. The `id` attribute for nodes is mandatory, and the position of each node is set in the `style`. The `source` and `target` attributes of the edge represent the `id` of the starting node and the ending node, respectively.\n\n### Creating and Drawing the Graph\n\nCreate an instance of the Graph, pass in a configuration object that includes the container and data, and then call the `render` method to draw the Graph:\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\nAs shown below, you can see that the chart has been successfully drawn:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### Element\n\nNext, we will introduce how to configure the style and types of elements in the canvas.\n\nG6 provides various mechanisms to configure element styles, which can be done in the data itself or within the chart instance. In the previous example, we configured the position of the nodes in the data. Next, we will configure the styles of nodes and edges in the graph configuration options:\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\nAs the code shows, we have configured the fill color of the nodes to be pink and the stroke color of the edges to be light green within the chart instance. You can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\nThe key parts are the `node.style` and `edge.style` options, which are used to configure the styles of nodes and edges, respectively.\n\n> In the subsequent code examples, we will only display the parts of the options. For the complete code of this project, please refer to the [Complete Example](https://codesandbox.io/s/g6-tutorial).\n\nNext, we will demonstrate more types of nodes by setting the node type:\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\nIn the code above, we set the `type` attribute of the node, which can be a string or a function. When `type` is a function, the argument of the function is the current node's data object, and the return value is the type of the node.\n\n> Similarly, each attribute under the `style` style of an element can also be a function, with the argument being the current element's data object.\n\n> You can even set the entire `style` property as a function, allowing you to dynamically set the element's style based on the data object.\n\nThe circular node (`circle`) is the default node type in G6. Here, we set the type of the first node to a circle and the type of the second node to a rectangle.\n\nAt the same time, we also set the size of the nodes to 20, so the first node is a circle with a radius of 10, and the second node is a square with a side length of 20.\n\n> If you want to set the size of the rectangular node to 20x10, you can set `size` to an array `[20, 10]`.\n\nYou can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### Behaviors\n\nThe chart provided in the previous example is static. Next, we will add some interactive behaviors.\n\nG6 offers a variety of interactive behaviors. We will add a few commonly used Behaviors to allow users to drag, zoom the canvas, and drag nodes.\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\nTry dragging nodes and the canvas in the example below, and use the scroll wheel to zoom in and out on the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### Layout\n\nIn the previous example, we manually set the positions of the nodes. However, this can become very difficult when there are many nodes.\n\nLayout algorithms can automatically adjust the positions of nodes based on certain rules. G6 provides a variety of layout algorithms, such as tree layout, force-directed layout, and so on.\n\nFirst, generate a set of data that does not include position information:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nBy default, if a node does not have position information, G6 will place the node at the top-left corner, that is, at the coordinates `(0, 0)`.\n\nNext, we will use the `d3-force` layout algorithm, which is a force-directed layout algorithm that can simulate the forces of attraction and repulsion between nodes, allowing the nodes to automatically adjust to suitable positions.\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\nView the example below, and you can see that the nodes have automatically adjusted to suitable positions:\n\n<details>\n<summary>Complete Code</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### Palette\n\nSimilarly, when there are many nodes, manually setting the color of each node can become difficult. G6 provides a palette mechanism that makes it easy to assign colors to elements.\n\nPalettes typically assign colors to elements based on a specific field in the data, such as the type of node, the weight of an edge, etc.\n\nBelow, we add a `category` field in the data:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nThen, use the `tableau` palette to set the colors for the nodes, where the `field` attribute specifies the field in the data, and the `color` attribute specifies the name of the palette.\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> It is important to note that the `fill` style in `node.style` should be removed, as its priority is higher than the colors assigned by the palette.\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### Plugins\n\nThe plugin mechanism is an important feature of G6, which allows you to extend the functionality of G6 through plugins. G6 provides a wealth of built-in plugins, such as `tooltip`, `legend`, etc., and also supports user-defined plugins.\n\nBelow, we will use the `grid-line` plugin to add grid lines to the canvas:\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\nYou can see that grid lines have been added to the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\nThe plugin configuration mentioned above used a shorthand form. Most plugins support the passing of additional parameters. For example, the `grid-line` plugin allows you to configure the `follow` property to specify whether the grid lines should follow the canvas when it is dragged.\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\nTry dragging the canvas in the example below, and you will see that the grid lines move along with the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## Summary\n\nIn this tutorial, we created a G6 chart from scratch and became acquainted with the main concepts of G6. We learned how to create a simple chart, how to configure the style and types of elements, how to add interactive behaviors, how to use layout algorithms, how to use palettes, and how to use plugins.\n\nFor a more detailed introduction to the concepts of G6, you can refer to [Core Concepts](/en/manual/graph/graph).\n\nDetailed explanations of options such as elements, layouts, and plugins can be found in the [API](/en/api/data).\n","packages/site/docs/manual/getting-started/step-by-step.zh.md":"---\ntitle: 详细教程\norder: 3\n---\n\n本教程将引导你从头开始完成一个 G6 图表开发，并在过程中了解和学习 G6 的主要概念。\n\n## 创建应用\n\n我们将使用 Vite 来创建一个简单的前端应用。\n\n### 初始化\n\n首先创建一个空目录：\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\n初始化项目：\n\n```bash\nnpm init -y\n```\n\n安装 G6：\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite 是一个新型的前端构建工具，它基于 ESModule，可以快速启动项目。\n\n安装 Vite：\n\n```bash\nnpm install vite --save-dev\n```\n\n在 `package.json` 中添加启动脚本：\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### 创建文件\n\n创建 `index.html` 和 `main.ts` 文件，内容如下：\n\n**index.html**：\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### 启动项目\n\n```bash\nnpm run dev\n```\n\n打开浏览器访问终端中输出的地址（通常为：http://127.0.0.1:5173/ ），你将看到一个弹窗显示 \"Hello, G6!\"。\n\n## 创建一个简单的图表\n\n接下来，我们将使用 G6 创建一个简单的图表。\n\n### 准备数据\n\nG6 使用 JSON 格式的数据来描述图，通常包括节点和边。我们将使用下面准备的数据：\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\n数据中包括两个节点和一条边，节点的 `id` 属性是必须的，并在 `style` 设置了每个节点的位置。边的 `source` 和 `target` 属性分别表示边的起始节点 `id` 和结束节点 `id`。\n\n### 创建并绘制图表\n\n创建一个图表实例，传入一个配置对象，包括容器和数据，然后调用 `render` 方法渲染图表：\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\n如下所示，可以看到图表已经顺利绘制出来：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### 元素\n\n接下来将介绍如何配置画布中的元素样式和种类。\n\nG6 提供了多种机制来配置元素样式，可以在数据中进行配置，也可以在图表实例中进行配置。前面的示例中，我们在数据中配置了节点的位置，接下来我们在图配置项中配置节点和边的样式：\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\n正如代码所示，我们在图表实例中配置了节点的填充颜色为粉色，边的描边颜色为浅绿色。你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\n其中的关键部分是 `node.style` 和 `edge.style` 配置项，分别用来配置节点和边的样式。\n\n> 在后续的代码示例中，我们仅展示配置项的部分代码，本项目的完整代码请查看 [完整示例](https://codesandbox.io/s/g6-tutorial)。\n\n下面我们将通过设置节点的类型来展示更多的节点种类：\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\n上面的代码中，我们设置了节点的 `type` 属性，其值可以是一个字符串，也可以是一个函数。当 `type` 是一个函数时，函数的参数是当前节点的数据对象，函数的返回值是节点的类型。\n\n> 同样的，元素中 `style` 样式下的每个属性都可以是一个函数，函数的参数是当前元素的数据对象。\n\n> 你甚至可以将整个 `style` 属性设置为一个函数，这样你可以根据数据对象动态设置元素的样式。\n\n圆形节点(`circle`)是 G6 的默认节点类型，这里我们将第一个节点的类型设置为圆形，第二个节点的类型设置为矩形。\n\n同时我们还将节点的大小设置为 20，因此第一个节点是一个半径为 10 的圆形，第二个节点是一个边长为 20 的正方形。\n\n> 如果你想将矩形节点的大小设置为 20x10，可以将 `size` 设置为一个数组 `[20, 10]`。\n\n你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### 交互\n\n在上面的例子中提供的图表是静态的，接下来我们将添加一些交互行为。\n\nG6 提供了多种交互行为，我们添加几个常用的交互，使得用户可以拖拽、缩放画布，拖拽节点。\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\n尝试在下面的示例中拖拽节点和画布，并使用滚轮缩放画布：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### 布局\n\n在上面的示例中，我们手动设置了节点的位置。但当节点数量较多时，这会变得非常困难。\n\n布局算法可以基于一定的规则自动调整节点的位置，G6 提供了多种布局算法，例如树形布局、力导向布局等。\n\n首先生成一组不包括位置信息的数据：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n默认情况下，如果节点没有位置信息，G6 会将节点放置在左上角，即 `(0, 0)`。\n\n接下来我们使用 `d3-force` 布局算法，它是一种力导向布局算法，可以模拟节点之间的引力和斥力，使得节点自动调整到合适的位置。\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\n查看下面的示例，可以看到节点已经自动调整到合适的位置：\n\n<details>\n<summary>完整代码</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### 色板\n\n同样的，当节点数量较多时，手动设置节点的颜色也会变得困难。G6 提供了色板机制，可以便捷地为元素设置颜色。\n\n色板通常会基于数据的某个字段为元素设置颜色，例如节点的类型、边的权重等。\n\n下面我们在数据中的添加 `category` 字段：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n然后使用 `tableau` 色板为节点设置颜色，`field` 属性指定了数据中的字段，`color` 属性指定了色板的名称。\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> 需要注意将 `node.style` 中的 `fill` 样式移除，因为其优先级高于色板分配的颜色。\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### 插件\n\n插件机制是 G6 的一个重要特性，可以通过插件扩展 G6 的功能。G6 提供了丰富的内置插件，例如 `tooltip`、`legend` 等，也支持用户自定义插件。\n\n下面我们将使用 `grid-line` 插件为画布添加网格线：\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\n可以看到画布已经添加了网格线：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\n上面的插件配置项中使用了简写形式，大部分的插件都支持传递额外的参数，例如 `grid-line` 插件可以配置 `follow` 属性来指定拖拽画布时网格线是否跟随画布移动。\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\n尝试在下面的示例中拖拽画布，可以看到网格线跟随画布移动：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## 小结\n\n在本教程中，我们从头开始创建了一个 G6 图表，并了解了 G6 的主要概念。我们学习了如何创建一个简单的图表，如何配置元素的样式和种类，如何添加交互行为，如何使用布局算法，如何使用色板，如何使用插件。\n\n关于 G6 更加详细的概念介绍可以在 [核心概念](/manual/graph/graph) 中查看。\n\n图的 API 详细说明可以在 [API](/api/graph) 中查看。\n","packages/site/docs/manual/graph/extension.en.md":"---\ntitle: extension\norder: 9\n---\n\n## Concept\n\nExtension is an important concept in G6, it is a general term for all expandable parts in G6, including the following types:\n\n- Animation\n- Behavior\n- Element\n  - Node\n  - Edge\n  - Combo\n- Layout\n- Palette\n- Plugin\n- Theme\n- Transform\n\n## Register Extension\n\nG6 provides the `register` function for registering extensions, for example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// # Registering Nodes\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\nThe first parameter of the `register` function is the type of the extension, the second parameter is the name of the extension, and the third parameter is the implementation of the extension(refer to the custom-related sections in the documentation for each extension type).\n\nDifferent types of extensions **can** use the same extension name, but when registering extensions of the same type, only the first registration will take effect.\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## Use Extension\n\nThe configuration location for different types of extensions varies, but all are used by specifying the name that was used during registration, for example:\n\n- Using node extensions: `options.node.type`\n- Using edge extensions: `options.edge.type`\n- Using combo extensions: `options.combo.type`\n- Using behavior extensions: `options.behaviors`\n- Using layout extensions: `options.layout.type`\n- Using plugin extensions: `options.plugins`\n- Using theme extensions: `options.theme`\n- Using data transform extensions: `options.transform`\n- Using palette extensions: `options.node.palette`, `options.edge.palette`, etc.\n- Using animation extensions: `options.node.animate`, `options.edge.animate`, etc.\n\n## Get Extension\n\nG6 provides the `getExtension` and `getExtensions` methods to obtain a single extension and all extensions of a specified type, respectively, for example:\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// To get the implementation of the node extension registered with the name 'custom-node'\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// Retrieve all registered node extension implementations\ngetExtensions(ExtensionCategory.NODE);\n```\n","packages/site/docs/manual/graph/extension.zh.md":"---\ntitle: Extension - 扩展\norder: 9\n---\n\n## 概念\n\n扩展 (Extension) 是 G6 中的一个重要概念，它是 G6 中所有可扩展部分的统称，包括以下几种：\n\n- 动画 (Animation)\n- 交互 (Behavior)\n- 元素 (Element)\n- 节点 (Node)\n  - 边 (Edge)\n  - 组合 (Combo)\n- 布局 (Layout)\n- 色板 (Palette)\n- 插件 (Plugin)\n- 主题 (Theme)\n- 数据转换 (Transform)\n\n## 注册扩展\n\nG6 提供了 `register` 函数用于注册扩展，例如：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// 注册节点\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\n`register` 函数的第一个参数是扩展的类型，第二个参数是扩展的名称，第三个参数是扩展的实现(扩展实现参考各扩展类型所在文档的自定义相关章节)。\n\n不同的扩展类型之间**可以**使用相同的扩展名称，但同一类型的扩展重复注册时仅会在第一次注册时生效。\n\n<!-- TODO: 详细的参数签名见：[API 文档](/api/reference/g6/register) -->\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## 使用扩展\n\n不同的扩展类型的配置位置有所不同，但都是通过指定注册时所使用的名称来使用扩展，例如：\n\n- 使用节点扩展：`options.node.type`\n- 使用边扩展：`options.edge.type`\n- 使用组合扩展：`options.combo.type`\n- 使用交互扩展：`options.behaviors`\n- 使用布局扩展：`options.layout.type`\n- 使用插件扩展：`options.plugins`\n- 使用主题扩展：`options.theme`\n- 使用数据转换扩展：`options.transform`\n- 使用色板扩展：`options.node.palette` `options.edge.palette` 等\n- 使用动画扩展：`options.node.animate` `options.edge.animate` 等\n\n## 获取扩展\n\nG6 提供了 `getExtension` 和 `getExtensions` 方法分别用于获取指定扩展类型下的单个扩展和所有扩展，例如：\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// 获取注册的名称为 'custom-node' 的节点扩展实现\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// 获取所有注册的节点扩展实现\ngetExtensions(ExtensionCategory.NODE);\n```\n","packages/site/docs/manual/graph/extensions.en.md":"---\n\ntitle: Built-in Extensions\norder: 4\n\nThe G6 built-in extensions and registered types are as follows:\n\n## Animations\n\n| Extension     | Registration Type |\n| ------------- | ----------------- |\n| ComboCollapse | 'combo-collapse'  |\n| ComboExpand   | 'combo-expand'    |\n| NodeCollapse  | 'node-collapse'   |\n| NodeExpand    | 'node-expand'     |\n| PathIn        | 'path-in'         |\n| PathOut       | 'path-out'        |\n| Fade          | 'fade'            |\n| Translate     | 'translate'       |\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].animation.[stage]`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    animation: {\n      update: 'translate', // Only use translation animation in the update stage\n    },\n  },\n});\n```\n\n## Behaviors\n\n| Extension                 | Registration Type             | Description                                    |\n| ------------------------- | ----------------------------- | ---------------------------------------------- |\n| BrushSelect               | 'brush-select'                | /                                              |\n| ClickSelect               | 'click-select'                | /                                              |\n| CollapseExpand            | 'collapse-expand'             | /                                              |\n| CreateEdge                | 'create-edge'                 | /                                              |\n| DragCanvas                | 'drag-canvas'                 | /                                              |\n| DragElementForce          | 'drag-element-force'          | Drag element when use d3-force layout          |\n| DragElement               | 'drag-element'                | /                                              |\n| FixElementSize            | 'fix-element-size'            | Keep the size of element during zooming canvas |\n| FocusElement              | 'focus-element'               | /                                              |\n| HoverActivate             | 'hover-activate'              | /                                              |\n| LassoSelect               | 'lasso-select'                | /                                              |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | Hide elements during manipulate the canvas     |\n| ScrollCanvas              | 'scroll-canvas'               | /                                              |\n| ZoomCanvas                | 'zoom-canvas'                 | /                                              |\n\nUsage:\n\nIn `GraphOptions.behaviors`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## Elements\n\n### Nodes\n\n| Extension | Registration Type |\n| --------- | ----------------- |\n| circle    | Circle            |\n| diamond   | Diamond           |\n| ellipse   | Ellipse           |\n| hexagon   | Hexagon           |\n| html      | HTML              |\n| image     | Image             |\n| rect      | Rect              |\n| star      | Star              |\n| donut     | Donut             |\n| triangle  | Triangle          |\n\nUsage:\n\n1. In `GraphOptions.data.nodes[number].type`;\n2. In `GraphOptions.node.type`;\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### Edges\n\n| Extension       | Registration Type  | Description                   |\n| --------------- | ------------------ | ----------------------------- |\n| Cubic           | 'cubic'            | Cubic Bezier Curve            |\n| Line            | 'line'             | /                             |\n| Polyline        | 'polyline'         | /                             |\n| Quadratic       | 'quadratic'        | Quadratic Bezier Curve        |\n| CubicHorizontal | 'cubic-horizontal' | Horizontal Cubic Bezier Curve |\n| CubicVertical   | 'cubic-vertical'   | Vertical Cubic Bezier Curve   |\n| CubicRadial     | 'cubic-radial'     | Radial Cubic Bezier Curve     |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.edges[number].type`;\n2. In `GraphOptions.edge.type`;\n\n### Combos\n\n| Extension   | Registration Type |\n| ----------- | ----------------- |\n| CircleCombo | 'circle'          |\n| RectCombo   | 'rect'            |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.combos[number].type`;\n2. In `GraphOptions.combo.type`;\n\n## Layouts\n\n| Extension           | Registration Type | Description                     |\n| ------------------- | ----------------- | ------------------------------- |\n| AntVDagreLayout     | 'antv-dagre'      | /                               |\n| ComboCombinedLayout | 'combo-combined'  | /                               |\n| CompactBoxLayout    | 'compact-box'     | /                               |\n| ForceAtlas2Layout   | 'force-atlas2'    | /                               |\n| CircularLayout      | 'circular'        | /                               |\n| ConcentricLayout    | 'concentric'      | /                               |\n| D3ForceLayout       | 'd3-force'        | /                               |\n| DagreLayout         | 'dagre'           | /                               |\n| DendrogramLayout    | 'dendrogram'      | /                               |\n| ForceLayout         | 'force'           | /                               |\n| FruchtermanLayout   | 'fruchterman'     | /                               |\n| GridLayout          | 'grid'            | /                               |\n| IndentedLayout      | 'indented'        | /                               |\n| MDSLayout           | 'mds'             | Multidimensional Scaling Layout |\n| MindmapLayout       | 'mindmap'         | /                               |\n| RadialLayout        | 'radial'          | /                               |\n| RandomLayout        | 'random'          | /                               |\n\nUsage:\n\nIn `GraphOptions.layout`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## Palettes\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].palette`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## Themes\n\n| Registration Type |\n| ----------------- |\n| dark              |\n| light             |\n\nUsage:\n\nIn `GraphOptions.theme`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  theme: 'dark',\n});\n```\n\n## Plugins\n\n| Extension      | Registration Type  |\n| -------------- | ------------------ |\n| BubbleSets     | 'bubble-sets'      |\n| EdgeFilterLens | 'edge-filter-lens' |\n| GridLine       | 'grid-line'        |\n| Background     | 'background'       |\n| Contextmenu    | 'contextmenu'      |\n| Fisheye        | 'fisheye'          |\n| Fullscreen     | 'fullscreen'       |\n| History        | 'history'          |\n| Hull           | 'hull'             |\n| Legend         | 'legend'           |\n| Minimap        | 'minimap'          |\n| Snapline       | 'snapline'         |\n| Timebar        | 'timebar'          |\n| Toolbar        | 'toolbar'          |\n| Tooltip        | 'tooltip'          |\n| Watermark      | 'watermark'        |\n\nUsage:\n\nIn `GraphOptions.plugins`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## Transforms\n\n| Extension            | Registration Type        | Description |\n| -------------------- | ------------------------ | ----------- |\n| ProcessParallelEdges | 'process-parallel-edges' | /           |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签    |\n\nUsage:\n\nIn `GraphOptions.transform`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## Shapes\n\n| Registration Type |\n| ----------------- |\n| circle            |\n| ellipse           |\n| group             |\n| html              |\n| image             |\n| line              |\n| path              |\n| polygon           |\n| polyline          |\n| rect              |\n| text              |\n| label             |\n| badge             |\n\nUsage:\n\nIn the [upsert](http://localhost:8000/en/manual/custom-extension/element#methods) method of the element class when customizing the shape, pass the second parameter:\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","packages/site/docs/manual/graph/extensions.zh.md":"---\ntitle: 内置扩展\norder: 4\n---\n\nG6 内置扩展及注册扩展类型如下：\n\n## 动画\n\n| 扩展          | 注册类型         | 描述     |\n| ------------- | ---------------- | -------- |\n| ComboCollapse | 'combo-collapse' | 组合收起 |\n| ComboExpand   | 'combo-expand'   | 组合展开 |\n| NodeCollapse  | 'node-collapse'  | 节点收起 |\n| NodeExpand    | 'node-expand'    | 节点展开 |\n| PathIn        | 'path-in'        | 路径进入 |\n| PathOut       | 'path-out'       | 路径退出 |\n| Fade          | 'fade'           | 渐变     |\n| Translate     | 'translate'      | 平移     |\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].animation.[stage]` 中使用，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    animation: {\n      update: 'translate', // 更新阶段仅使用平移动画\n    },\n  },\n});\n```\n\n## 交互\n\n| 扩展                      | 注册类型                      | 描述                   |\n| ------------------------- | ----------------------------- | ---------------------- |\n| BrushSelect               | 'brush-select'                | 框选                   |\n| ClickSelect               | 'click-select'                | 点击选中               |\n| CollapseExpand            | 'collapse-expand'             | 展开/收起元素          |\n| CreateEdge                | 'create-edge'                 | 创建边                 |\n| DragCanvas                | 'drag-canvas'                 | 拖拽画布               |\n| DragElementForce          | 'drag-element-force'          | 力导向拖拽元素         |\n| DragElement               | 'drag-element'                | 拖拽元素               |\n| FixElementSize            | 'fix-element-size'            | 缩放画布时固定元素大小 |\n| FocusElement              | 'focus-element'               | 聚焦元素               |\n| HoverActivate             | 'hover-activate'              | 悬停激活               |\n| LassoSelect               | 'lasso-select'                | 套索选择               |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | 操作画布时隐藏元素     |\n| ScrollCanvas              | 'scroll-canvas'               | 滚动画布               |\n| ZoomCanvas                | 'zoom-canvas'                 | 缩放画布               |\n\n配置方式：\n\n在 `GraphOptions.behaviors` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## 元素\n\n### 节点\n\n| 扩展     | 注册类型 | 描述       |\n| -------- | -------- | ---------- |\n| circle   | Circle   | 圆形节点   |\n| diamond  | Diamond  | 菱形节点   |\n| ellipse  | Ellipse  | 椭圆节点   |\n| hexagon  | Hexagon  | 六边形节点 |\n| html     | HTML     | HTML节点   |\n| image    | Image    | 图片节点   |\n| rect     | Rect     | 矩形节点   |\n| star     | Star     | 星形节点   |\n| donut    | Donut    | 甜甜圈节点 |\n| triangle | Triangle | 三角形节点 |\n\n配置方式：\n\n1. 在 `GraphOptions.data.nodes[number].type` 中配置；\n2. 在 `GraphOptions.node.type` 中配置；\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### 边\n\n| 扩展            | 注册类型           | 描述               |\n| --------------- | ------------------ | ------------------ |\n| Cubic           | 'cubic'            | 三次贝塞尔曲线     |\n| Line            | 'line'             | 直线               |\n| Polyline        | 'polyline'         | 折线               |\n| Quadratic       | 'quadratic'        | 二次贝塞尔曲线     |\n| CubicHorizontal | 'cubic-horizontal' | 水平三次贝塞尔曲线 |\n| CubicVertical   | 'cubic-vertical'   | 垂直三次贝塞尔曲线 |\n| CubicRadial     | 'cubic-radial'     | 径向三次贝塞尔曲线 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.edges[number].type` 中配置；\n2. 在 `GraphOptions.edge.type` 中配置；\n\n### 组合\n\n| 扩展        | 注册类型 | 描述     |\n| ----------- | -------- | -------- |\n| CircleCombo | 'circle' | 圆形组合 |\n| RectCombo   | 'rect'   | 矩形组合 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.combos[number].type` 中配置；\n2. 在 `GraphOptions.combo.type` 中配置；\n\n## 布局\n\n| 扩展                | 注册类型         | 描述                   |\n| ------------------- | ---------------- | ---------------------- |\n| AntVDagreLayout     | 'antv-dagre'     | AntV Dagre 布局        |\n| ComboCombinedLayout | 'combo-combined' | 组合布局               |\n| CompactBoxLayout    | 'compact-box'    | 紧凑树                 |\n| ForceAtlas2Layout   | 'force-atlas2'   | ForceAlas2 力导向布局  |\n| CircularLayout      | 'circular'       | 环形布局               |\n| ConcentricLayout    | 'concentric'     | 同心圆布局             |\n| D3ForceLayout       | 'd3-force'       | D3 力导向布局          |\n| DagreLayout         | 'dagre'          | Dagre 布局             |\n| DendrogramLayout    | 'dendrogram'     | 生态树                 |\n| ForceLayout         | 'force'          | 力导向布局             |\n| FruchtermanLayout   | 'fruchterman'    | Fruchterman 力导向布局 |\n| GridLayout          | 'grid'           | 网格布局               |\n| IndentedLayout      | 'indented'       | 缩进树                 |\n| MDSLayout           | 'mds'            | 高维数据降维布局       |\n| MindmapLayout       | 'mindmap'        | 脑图树                 |\n| RadialLayout        | 'radial'         | 径向布局               |\n| RandomLayout        | 'random'         | 随机布局               |\n\n配置方式：\n\n在 `GraphOptions.layout` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## 色板\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].palette` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## 主题\n\n| 注册类型 | 描述     |\n| -------- | -------- |\n| dark     | 深色主题 |\n| light    | 浅色主题 |\n\n配置方式：\n\n在 `GraphOptions.theme` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  theme: 'dark',\n});\n```\n\n## 插件\n\n| 扩展           | 注册类型           | 描述       |\n| -------------- | ------------------ | ---------- |\n| BubbleSets     | 'bubble-sets'      | 气泡集     |\n| EdgeFilterLens | 'edge-filter-lens' | 边过滤镜   |\n| GridLine       | 'grid-line'        | 网格线     |\n| Background     | 'background'       | 背景       |\n| Contextmenu    | 'contextmenu'      | 上下文菜单 |\n| Fisheye        | 'fisheye'          | 鱼眼放大镜 |\n| Fullscreen     | 'fullscreen'       | 全屏展示   |\n| History        | 'history'          | 历史记录   |\n| Hull           | 'hull'             | 轮廓包围   |\n| Legend         | 'legend'           | 图例       |\n| Minimap        | 'minimap'          | 小地图     |\n| Snapline       | 'snapline'         | 对齐线     |\n| Timebar        | 'timebar'          | 时间条     |\n| Toolbar        | 'toolbar'          | 工具栏     |\n| Tooltip        | 'tooltip'          | 提示框     |\n| Watermark      | 'watermark'        | 水印       |\n\n配置方式：\n\n在 `GraphOptions.plugins` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## 数据转换\n\n| 扩展                 | 注册类型                 | 描述     |\n| -------------------- | ------------------------ | -------- |\n| ProcessParallelEdges | 'process-parallel-edges' | 平行边   |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签 |\n\n配置方式：\n\n在 `GraphOptions.transforms` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## 图形\n\n| 注册类型 | 描述   |\n| -------- | ------ |\n| circle   | 圆形   |\n| ellipse  | 椭圆   |\n| group    | 分组   |\n| html     | HTML   |\n| image    | 图片   |\n| line     | 直线   |\n| path     | 路径   |\n| polygon  | 多边形 |\n| polyline | 折线   |\n| rect     | 矩形   |\n| text     | 文本   |\n| label    | 标签   |\n| badge    | 徽标   |\n\n使用方式：\n\n自定义图形时，元素类成员方法 [upsert](/manual/element/node/custom-node) 方法第二个参数传入：\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","packages/site/docs/manual/graph/graph.en.md":"---\ntitle: Graph\norder: 0\n---\n\n## Overview\n\n### Definition of Graph\n\nIn Chinese, the character \"图\" (Graph) can often be used to represent many different concepts, such as image,shape,and chart or diagram,etc.\n\nIn Graph Theory, a graph is a mathematical structure used to model pairwise relationships between objects, which we typically represent with nodes (or Vertex) and edges (or Link) to denote the objects and the relationships between them.\n\nThe \"graph\" in G6:\n\n- Conceptually, it is the \"graph\" from Graph Theory, a data structure composed of nodes and edges.\n- Visually, a \"graph\" is a figure composed of a set of graphical elements representing nodes and edges.\n- In terms of code implementation, a \"graph\" is a class capable of transforming data into a graphical display.\n\n### Types of Graph\n\nGraph Theory categorizes graphs into many different types based on their structure and properties, such as:\n\n- Directed Graph and Undirected Graph\n- Weighted Graph and Unweighted Graph\n- Simple Graph and Multigraph\n- Cyclic Graph and Acyclic Graph\n- Connected Graph and Disconnected Graph\n- Complete Graph and Non-Complete Graph\n- Sparse Graph and Dense Graph\n- ...\n\nIn G6, we provide a universal graph representation capable of depicting the various types of graphs mentioned above, for example:\n\n- Directed Graph and Undirected Graph: Defined by the start and end points of the edges.\n- Weighted Graph and Unweighted Graph: Defined by the `weight` data on the edges.\n- Simple Graph and Multigraph: Defined by the uniqueness of the edges.\n- ...\n\n### Use Scenarios\n\nGraphs are a very versatile data structure that can be used to represent a variety of scenarios, such as:\n\n- Social Networks\n- Knowledge Graphs\n- Traffic Networks\n- Power Grids\n\nIn G6, we provide a rich expression capability for graphs that can meet the needs of different scenarios. We also offer a wealth of interactive and animated effects to make the graphs more vivid and intuitive.\n\n## Use G6 Graph\n\nTo create a Graph with G6, you first need to import the `@antv/g6` library, and then instantiate the Graph class.\n\n> For installation instructions, refer to: [Getting Started - Installation](/en/manual/getting-started/installation)\n\nThe Graph class accepts an instantiation argument object, known as **options** (Options, in visualization theory it is referred to as: `Specification`), which is used to configure the graph's data, element styles, layout, interactions, etc.\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  // ... other other options\n});\n```\n\n:::warning{title=note}\nThe instantiation process only configures the basic information of the graph. To render the graph onto the page, you still need to call the `render` method.\n:::\n\n- To learn how to quickly create a graph, please refer to [Quick Start](/en/manual/getting-started/quick-start).\n- For more detailed information about the configuration options, please refer to [Options](/en/manual/graph/option).\n- To gain an in-depth understanding of the concepts within the configuration options, please read the rest of the content in this section.\n","packages/site/docs/manual/graph/graph.zh.md":"---\ntitle: Graph - 图\norder: 0\n---\n\n## 什么是 Graph\n\n中文字“图”在大家的传统认知里指的是图画、图像，而图论与可视化中的“图”—— Graph 则有着更精确的定位：主体（objects）与关系（relationships）的组成。它甚至不局限于视觉，主体与关系的数据也可以称为图。\n\n> —— 摘自 [AntV 专栏](https://zhuanlan.zhihu.com/aiux-antv) 文章：[Graph Visualization · 知多少 之 《HelloWorld 图可视化》](https://zhuanlan.zhihu.com/p/83685690)。\n\n在 G6 中，Graph 对象是图的载体，它包含了图上的所有元素（节点、边等），同时挂载了图的相关操作（如交互监听、元素操作、渲染等）。\n\nGraph 对象的完整生命周期包括：\n\n1. **创建**: 通过 `new Graph(options)` 实例化\n2. **初始化**: 在创建时进行内部初始化\n3. **渲染**: 调用 `graph.render()` 进行首次渲染\n4. **更新**: 通过各种 API 更新图的数据和配置\n5. **销毁**: 调用 `graph.destroy()` 销毁实例并释放资源\n\n## 使用 G6 Graph\n\n要使用 G6 创建 Graph，首先需要引入 `@antv/g6` 库，然后实例化 Graph 类。\n\n> 安装教程参考：[开始使用 - 安装](/manual/getting-started/installation)\n\nGraph 类接收一个实例化参数对象，称之为**配置项**(Options，在可视化理论中将其称为：`Specification`)，用于配置图的数据、元素样式、布局、交互等。\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container', // 通过 DOM ID 指定容器\n  width: 800, // 画布宽高（若容器已设尺寸可省略）\n  height: 600,\n  data: {\n    // 初始数据\n    nodes: [{ id: 'start', data: { label: 'Hello G6!' } }],\n  },\n});\n```\n\n:::warning{title=注意}\n实例化过程仅是配置图的基本信息，要将图渲染到页面上，还需要调用 `render` 方法\n:::\n\n## 图配置项\n\n通过下表速查图的配置项，更多类型定义说明和详细用法请参考 [API - 图配置项](/manual/graph/option)。\n\n| 属性             | 类型                               | 默认值      | 描述                                                          |\n| ---------------- | ---------------------------------- | ----------- | ------------------------------------------------------------- |\n| container        | string \\| HTMLElement \\| Canvas    | -           | 图容器，可以是 DOM 元素 ID、DOM 元素实例或 Canvas 实例        |\n| width            | number                             | 容器宽度    | 画布宽度(像素)                                                |\n| height           | number                             | 容器高度    | 画布高度(像素)                                                |\n| autoFit          | 'view' \\| 'center' \\| object       | -           | 自动适配策略，'view'(适应视图)或'center'(居中)                |\n| autoResize       | boolean                            | false       | 是否在窗口大小变化时自动调整画布大小                          |\n| background       | string                             | -           | 画布背景色，也作为导出图片时的背景色                          |\n| canvas           | CanvasConfig                       | -           | 画布配置                                                      |\n| cursor           | Cursor                             | `'default'` | 指针样式                                                      |\n| devicePixelRatio | number                             | 2           | 设备像素比                                                    |\n| padding          | number \\| number[]                 | -           | 画布内边距，在自适应时会根据内边距进行适配                    |\n| renderer         | (layer: string) => IRenderer       | -           | 手动指定渲染器                                                |\n| rotation         | number                             | 0           | 旋转角度(弧度)                                                |\n| zoom             | number                             | 1           | 缩放比例                                                      |\n| zoomRange        | [number, number]                   | [0.01, 10]  | 缩放比例的限制范围                                            |\n| x                | number                             | -           | 视口 x 坐标                                                   |\n| y                | number                             | -           | 视口 y 坐标                                                   |\n| data             | GraphData                          | -           | 图数据，详见 [数据](/manual/data)                             |\n| node             | NodeOptions                        | -           | 节点全局配置，详见 [节点](/manual/element/node/overview)      |\n| edge             | EdgeOptions                        | -           | 边全局配置，详见 [边](/manual/element/edge/overview)          |\n| combo            | ComboOptions                       | -           | 组合全局配置，详见 [组合](/manual/element/combo/overview)     |\n| animation        | boolean \\| AnimationEffectTiming   | -           | 全局动画配置，详见 [动画](/manual/animation/animation)        |\n| theme            | string \\| false                    | `'light'`   | 主题配置，支持 `'light'`、`'dark'` 或自定义主题名             |\n| layout           | LayoutOptions \\| LayoutOptions[]   | -           | 布局配置，详见 [布局](/manual/layout/overview)                |\n| behaviors        | (string \\| CustomBehaviorOption)[] | -           | 交互行为配置，详见 [交互](/manual/behavior/overview)          |\n| plugins          | (string \\| CustomPluginOption)[]   | -           | 插件配置，详见 [插件](/manual/plugin/overview)                |\n| transforms       | TransformOptions                   | -           | 数据转换器配置，详见 [数据转换器](/manual/transform/overview) |\n\n## 图属性\n\n图实例提供了一些只读属性，用于获取图的状态信息：\n\n| 属性      | 类型    | 描述                     |\n| --------- | ------- | ------------------------ |\n| destroyed | boolean | 当前图实例是否已被销毁   |\n| rendered  | boolean | 当前图实例是否已完成渲染 |\n\n## 参考示例\n\n### 完整的创建和配置示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\ngraph.render();\n```\n\n```typescript\nimport { Graph } from '@antv/g6';\n\n// 创建图实例\nconst graph = new Graph({\n  // 基础配置\n  container: 'container',\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\n// 渲染图\ngraph.render();\n```\n\n- 要了解如何快速创建一个图，请参考[快速上手](/manual/getting-started/quick-start)。\n- 要深入了解配置项中个部分的概念，请阅读本章节的其他内容。\n","packages/site/docs/manual/graph/option.en.md":"---\ntitle: Options\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\nWhether to automatically fit the canvas. ⚠️ **Note**: Each time `render` is executed, it will adapt according to `autoFit`.\n\nTwo basic adaptation modes:\n\n- `'view'` - Automatically scale to ensure all content is visible within the view\n- `'center'` - Center the content without changing the zoom level\n\nMore precise adaptation control can be achieved through object form:\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // Adaptation type: 'view' or 'center'\n    options: {\n      // Only applicable to 'view' type\n      when: 'overflow', // When to adapt: 'overflow' (only when content overflows) or 'always' (always adapt)\n      direction: 'x', // Adaptation direction: 'x', 'y', or 'both'\n    },\n    animation: {\n      // Adaptation animation effect\n      duration: 1000, // Animation duration (milliseconds)\n      easing: 'ease-in-out', // Animation easing function\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| Property  | Description                                                                                                                                                             | Type                       | Default    | Required |\n| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | -------- |\n| when      | Adaptation occurs under the following conditions <br/> - `'overflow'` adapt only when content overflows <br/> - `'always'` always adapt                                 | `'overflow'` \\| `'always'` | `'always'` |          |\n| direction | Adapt only in the specified direction <br/> - `'x'` adapt only in x direction <br/> - `'y'` adapt only in y direction <br/> - `'both'` adapt in both x and y directions | `'x'` \\| `'y'` \\| `'both'` | `'both'`   |          |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## autoResize\n\n> _boolean_ **Default:** `false`\n\nWhether to automatically resize the canvas.\n\nImplemented based on the `window.onresize` event. When the browser window size changes, the canvas will automatically resize to fit the container.\n\n## background\n\n> _string_\n\nCanvas background color.\n\nThis color is used as the background color when exporting images. Any valid CSS color value can be used, such as hexadecimal, RGB, RGBA, etc.\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\nCanvas configuration. Related configuration items under GraphOptions (such as `container`, `width`, `height`, `devicePixelRatio`, `background`, `cursor`) are shortcut configuration items and will be converted to canvas configuration items.\n\n#### CanvasConfig\n\n| Property         | Description                                                                                | Type                                                                           | Default | Required |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------- | -------- |\n| container        | Canvas container                                                                           | string \\| HTMLElement                                                          | -       |          |\n| devicePixelRatio | Device pixel ratio                                                                         | number                                                                         | -       |          |\n| width            | Canvas width                                                                               | number                                                                         | -       |          |\n| height           | Canvas height                                                                              | number                                                                         | -       |          |\n| cursor           | Cursor style, same as [GraphOptions.cursor](#cursor)                                       | string                                                                         | -       |          |\n| background       | Canvas background color                                                                    | string                                                                         | -       |          |\n| renderer         | Renderer, same as [GraphOptions.renderer](#renderer)                                       | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -       |          |\n| enableMultiLayer | Whether to enable multi-layer. Non-dynamic parameter, effective only during initialization | boolean                                                                        | -       |          |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\nCanvas container, can be one of the following three assignments:\n\n- ID string of the DOM element, such as `'container'`\n- HTML element object, such as `document.getElementById('container')`\n- Canvas instance, such as `new Canvas(options)`, where `options` is of type [CanvasConfig](#canvasconfig).\n\n## cursor\n\n> string\n\nCursor style, controls the cursor shape when hovering over the canvas. Any valid CSS cursor value can be used.\n\nSupported values include: `'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'.\n\nCursor values are referenced from [MDN - cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n\n## devicePixelRatio\n\n> _number_\n\nDevice pixel ratio.\n\nUsed for high-definition screens, the default is [window.devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio).\n\n## width\n\n> _number_\n\nCanvas width. If not set, the container width will be automatically obtained.\n\n## height\n\n> _number_\n\nCanvas height. If not set, the container height will be automatically obtained.\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\nManually specify the renderer\n\nG6 uses a layered rendering approach, divided into four layers: `background`, `main`, `label`, `transient`. Users can set the renderer for each layer of the canvas through this configuration item.\n\n**Example**: Use SVG renderer for rendering\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\nCanvas padding\n\nUsually, during adaptation, it will be adapted according to the padding. It can be a single value (same padding on all sides) or an array form (specify the padding for top, right, bottom, left in order).\n\n**Example:**\n\n```javascript\n// Single value\nconst graph1 = new Graph({\n  padding: 20, // 20 pixels of padding on all sides\n});\n\n// Array form\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // Padding for top, right, bottom, left\n});\n```\n\n## rotation\n\n> _number_ **Default:** `0`\n\nRotation angle (in radians)\n\n## x\n\n> _number_\n\nViewport x coordinate, sets the initial horizontal position of the viewport.\n\n## y\n\n> _number_\n\nViewport y coordinate, sets the initial vertical position of the viewport.\n\n## zoom\n\n> _number_ **Default:** `1`\n\nSets the initial zoom level of the viewport, 1 means 100% (original size).\n\n## zoomRange\n\n> _[number, number]_ **Default:** `[0.01, 10]`\n\nZoom range, limits the minimum and maximum scale that users can zoom.\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\nEnable or disable global animation\n\nWhen configured as an animation option, animation will be enabled, and this animation configuration will be used as the base configuration for global animation.\n\n#### AnimationEffectTiming\n\n| Property   | Description                    | Type                                                                | Default     | Required |\n| ---------- | ------------------------------ | ------------------------------------------------------------------- | ----------- | -------- |\n| delay      | Animation delay time           | number                                                              | -           |          |\n| direction  | Animation direction            | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |          |\n| duration   | Animation duration             | number                                                              | -           |          |\n| easing     | Animation easing function      | string                                                              | -           |          |\n| fill       | Fill mode after animation ends | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |          |\n| iterations | Animation iteration count      | number                                                              | -           |          |\n\n**Example:**\n\n```javascript\n// Simple enable\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// Detailed configuration\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // Animation duration (milliseconds)\n    easing: 'ease-in-out', // Easing function\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\nData.\n\n#### GraphData\n\n| Property | Description | Type                      | Default | Required |\n| -------- | ----------- | ------------------------- | ------- | -------- |\n| nodes    | Node data   | [NodeData](#nodedata)[]   | -       | ✓        |\n| edges    | Edge data   | [EdgeData](#edgedata)[]   | -       | ✓        |\n| combos   | Combo data  | [ComboData](#combodata)[] | -       | ✓        |\n\n#### NodeData\n\n| Property | Description                                                                                                                                         | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                                 | string         | -       | ✓        |\n| type     | Node type, built-in node type name or custom node name                                                                                              | string         | -       |          |\n| data     | Node data, used to store custom data for the node, such as node name, description, etc. Can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Node style, including visual attributes such as position, size, color, etc.                                                                         | object         | -       |          |\n| states   | Initial state of the node, such as selected, activated, hovered, etc.                                                                               | string[]       | -       |          |\n| combo    | ID of the combo to which it belongs, used to organize the hierarchical relationship of nodes, if none, it is null                                   | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                                     | string[]       | -       |          |\n\n#### EdgeData\n\n| Property | Description                                                                                                    | Type     | Default | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source   | Starting node ID of the edge                                                                                   | string   | -       | ✓        |\n| target   | Target node ID of the edge                                                                                     | string   | -       | ✓        |\n| id       | Unique identifier for the edge                                                                                 | string   | -       |          |\n| type     | Edge type, built-in edge type name or custom edge name                                                         | string   | -       |          |\n| data     | Edge data, used to store custom data for the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style    | Edge style, including visual attributes such as line color, width, arrow, etc.                                 | object   | -       |          |\n| states   | Initial state of the edge                                                                                      | string[] | -       |          |\n\n#### ComboData\n\n| Property | Description                                                                                                      | Type           | Default | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the combo                                                                                  | string         | -       | ✓        |\n| type     | Combo type, built-in combo type name or custom combo name                                                        | string         | -       |          |\n| data     | Combo data, used to store custom data for the combo, can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Combo style                                                                                                      | object         | -       |          |\n| states   | Initial state of the combo                                                                                       | string[]       | -       |          |\n| combo    | Parent combo ID. If there is no parent combo, it is null                                                         | string \\| null | -       |          |\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- Read [Data](/en/manual/data) to learn more about graph data, including but not limited to data formats, how to manipulate data, etc.\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\nNode configuration options.\n\n#### NodeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default  | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name                           | [Type](/en/manual/element/node/base-node#type)           | `circle` |          |\n| style     | Node style, including color, size, etc.                                          | [Style](/en/manual/element/node/base-node#style)         | -        |          |\n| state     | Define the style of the node in different states                                 | [State](/en/manual/element/node/base-node#state)         | -        |          |\n| palette   | Define the color palette of the node, used to map colors based on different data | [Palette](/en/manual/element/node/base-node#palette)     | -        |          |\n| animation | Define the animation effect of the node                                          | [Animation](/en/manual/element/node/base-node#animation) | -        |          |\n\nSee [Node](/en/manual/element/node/base-node) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {\n      fill: '#e6f7ff', // Fill color\n      stroke: '#91d5ff', // Border color\n      lineWidth: 1, // Border width\n      r: 20, // Radius\n      labelText: (d) => d.id, // Label text\n    },\n    // Node state style\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\nEdge configuration options\n\n#### EdgeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name                           | [Type](/en/manual/element/edge/base-edge#type)           | `line`  |          |\n| style     | Edge style, including color, size, etc.                                          | [Style](/en/manual/element/edge/base-edge#style)         | -       |          |\n| state     | Define the style of the edge in different states                                 | [State](/en/manual/element/edge/base-edge#state)         | -       |          |\n| palette   | Define the color palette of the edge, used to map colors based on different data | [Palette](/en/manual/element/edge/base-edge#palette)     | -       |          |\n| animation | Define the animation effect of the edge                                          | [Animation](/en/manual/element/edge/base-edge#animation) | -       |          |\n\nSee [Edge](/en/manual/element/edge/base-edge) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // Edge type\n    style: {\n      stroke: '#91d5ff', // Edge color\n      lineWidth: 2, // Edge width\n      endArrow: true, // Whether there is an arrow\n    },\n    // Edge state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\nCombo configuration options\n\n| Property  | Description                                                                       | Type                                                       | Default  | Required |\n| --------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name                         | [Type](/en/manual/element/combo/base-combo#type)           | `circle` |          |\n| style     | Combo style, including color, size, etc.                                          | [Style](/en/manual/element/combo/base-combo#style)         | -        |          |\n| state     | Define the style of the combo in different states                                 | [State](/en/manual/element/combo/base-combo#state)         | -        |          |\n| palette   | Define the color palette of the combo, used to map colors based on different data | [Palette](/en/manual/element/combo/base-combo#palette)     | -        |          |\n| animation | Define the animation effect of the combo                                          | [Animation](/en/manual/element/combo/base-combo#animation) | -        |          |\n\nSee [Combo](/en/manual/element/combo/base-combo) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {\n      fill: '#f0f0f0', // Background color\n      stroke: '#d9d9d9', // Border color\n      lineWidth: 1, // Border width\n    },\n    // Combo state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\nLayout configuration options, can be an object (normal layout) or an array (pipeline layout).\n\n**Example**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // Force-directed layout\n    preventOverlap: true, // Prevent node overlap\n    nodeStrength: -50, // Repulsion between nodes\n    edgeStrength: 0.5, // Elastic coefficient of edges\n    iterations: 200, // Number of iterations\n    animation: true, // Enable layout animation\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\nSet the theme of the chart, can be the built-in `'light'`, `'dark'` theme, or the name of a custom theme. Set to `false` to use no theme.\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure the interaction behaviors of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // Enable canvas dragging with default configuration\n    'zoom-canvas', // Enable canvas zooming with default configuration\n    {\n      type: 'drag-element', // Custom configuration for dragging elements\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // Only allow dragging nodes\n    },\n    function () {\n      console.log(this); // Output graph instance\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- View [Interaction Overview](/en/manual/behavior/overview) to learn more about interaction principles\n- Browse [Built-in Interactions](/en/manual/behavior/auto-adapt-label) to get a list of all built-in interactions and their configuration options\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nSet the plugins of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // Enable minimap with default configuration\n    {\n      type: 'grid', // Enable grid background\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // Enable toolbar\n      key: 'graph-toolbar',\n      position: 'top-right', // Position\n    },\n  ],\n});\n```\n\n- View [Plugin Overview](/en/manual/plugin/overview) to learn more about plugin principles\n- Browse [Built-in Plugins](/en/manual/plugin/background) to get a list of all built-in plugins and their configuration options\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure data processing, used to process data before rendering, does not affect the original data. Can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // Process parallel edges with default configuration\n    {\n      type: 'map-node-size', // Map node size based on node data\n      field: 'value', // Use the value of the field\n      max: 50, // Maximum radius\n      min: 20, // Minimum radius\n    },\n  ],\n});\n```\n\n- View [Data Processing Overview](/en/manual/transform/overview) to learn more about data processing principles\n- Browse [Built-in Data Processing](/en/manual/transform/map-node-size) to get a list of all built-in data processing and their configuration options\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** Extension type */\n  type: string;\n  /** Extension key, i.e., unique identifier */\n  key?: string;\n}\n```\n","packages/site/docs/manual/graph/option.zh.md":"---\ntitle: Options 配置项\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\n是否自动适应画布。⚠️ **注意**：每次执行 `render` 时，都会根据 `autoFit` 进行自适应。\n\n两种基本自适应模式：\n\n- `'view'` - 自动缩放，确保所有内容都在视图内可见\n- `'center'` - 内容居中显示，但不改变缩放比例\n\n还可通过对象形式实现更精细的自适应控制：\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // 自适应类型：'view' 或 'center'\n    options: {\n      // 仅适用于 'view' 类型\n      when: 'overflow', // 何时适配：'overflow'(仅当内容溢出时) 或 'always'(总是适配)\n      direction: 'x', // 适配方向：'x'、'y' 或 'both'\n    },\n    animation: {\n      // 自适应动画效果\n      duration: 1000, // 动画持续时间(毫秒)\n      easing: 'ease-in-out', // 动画缓动函数\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| 属性      | 描述                                                                                                           | 类型                       | 默认值     | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | ---- |\n| when      | 在以下情况下进行适配 <br/> - `'overflow'` 仅当图内容超出视口时进行适配 <br/> - `'always'` 总是进行适配         | `'overflow`' \\| `'always'` | `'always'` |      |\n| direction | 仅对指定方向进行适配 <br/> - `'x'` 仅适配 x 方向 <br/> - `'y'` 仅适配 y 方向 <br/> - `'both'` 适配 x 和 y 方向 | `'x`' \\| `'y`' \\| `'both'` | `'both'`   |      |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## autoResize\n\n> _boolean_ **默认值:** `false`\n\n是否自动调整画布大小。\n\n基于 `window.onresize` 事件实现。当浏览器窗口大小变化时，画布将自动调整大小以适应容器。\n\n## background\n\n> _string_\n\n画布背景色。\n\n该颜色作为导出图片时的背景色。可以使用任何有效的 CSS 颜色值，如十六进制、RGB、RGBA 等。\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\n画布配置。GraphOptions 下相关配置项（如 `container`、`width`、`height`、`devicePixelRatio`、`background`、`cursor`）为快捷配置项，会被转换为 canvas 配置项。\n\n#### CanvasConfig\n\n| 属性             | 描述                                                   | 类型                                                                           | 默认值 | 必填 |\n| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------ | ------ | ---- |\n| container        | 画布容器                                               | string \\| HTMLElement                                                          | -      |      |\n| devicePixelRatio | 设备像素比                                             | number                                                                         | -      |      |\n| width            | 画布宽度                                               | number                                                                         | -      |      |\n| height           | 画布高度                                               | number                                                                         | -      |      |\n| cursor           | 指针样式，与 [GraphOptions.cursor](#cursor) 配置相同   | string                                                                         | -      |      |\n| background       | 画布背景色                                             | string                                                                         | -      |      |\n| renderer         | 渲染器，与 [GraphOptions.renderer](#renderer) 配置相同 | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -      |      |\n| enableMultiLayer | 是否启用多图层。非动态参数，仅在初始化时生效           | boolean                                                                        | -      |      |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\n画布容器，可以是以下三种赋值之一：\n\n- DOM 元素的 ID 字符串，如 `'container'`\n- HTML 元素对象，如 `document.getElementById('container')`\n- Canvas 实例，如 `new Canvas(options)`，其中 `options` 为 [CanvasConfig](#canvasconfig) 类型。\n\n## cursor\n\n> string\n\n指针样式，控制鼠标悬停在画布上时的光标形状。可以使用任何有效的 CSS cursor 值。\n\n支持的值有： `'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'`。\n\n这里的 Cursor 值参考 [MDN - cursor](https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor)。\n\n## devicePixelRatio\n\n> _number_\n\n设备像素比。\n\n用于高清屏的设备像素比，默认为 [window.devicePixelRatio](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio)。\n\n## width\n\n> _number_\n\n画布宽度。如果未设置，则会自动获取容器宽度。\n\n## height\n\n> _number_\n\n画布高度。如果未设置，则会自动获取容器高度。\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\n手动指定渲染器\n\nG6 采用了分层渲染的方式，分为 `background`、`main`、`label`、`transient` 四层，用户可以通过该配置项分别设置每层画布的渲染器。\n\n**示例**: 使用 SVG 渲染器进行渲染\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\n画布内边距\n\n通常在自适应时，会根据内边距进行适配。可以是单个数值（四边相同）或者数组形式（按顺序指定上、右、下、左的内边距）。\n\n**示例：**\n\n```javascript\n// 单个数值\nconst graph1 = new Graph({\n  padding: 20, // 四边均为 20 像素的内边距\n});\n\n// 数组形式\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // 上、右、下、左的内边距\n});\n```\n\n## rotation\n\n> _number_ **默认值:** `0`\n\n旋转角度（以弧度为单位）\n\n## x\n\n> _number_\n\n视口 x 坐标，设置视口的初始水平位置。\n\n## y\n\n> _number_\n\n视口 y 坐标，设置视口的初始垂直位置。\n\n## zoom\n\n> _number_ **默认值:** `1`\n\n设置视口的初始缩放级别，1 表示 100%（原始大小）。\n\n## zoomRange\n\n> _[number, number]_ **默认值:** `[0.01, 10]`\n\n缩放范围，限制用户可以缩放的最小和最大比例。\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\n启用或关闭全局动画\n\n为动画配置项时，会启用动画，并将该动画配置作为全局动画的基础配置。\n\n#### AnimationEffectTiming\n\n| 属性       | 描述                 | 类型                                                                | 默认值      | 必选 |\n| ---------- | -------------------- | ------------------------------------------------------------------- | ----------- | ---- |\n| delay      | 动画延迟时间         | number                                                              | -           |      |\n| direction  | 动画方向             | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |      |\n| duration   | 动画持续时间         | number                                                              | -           |      |\n| easing     | 动画缓动函数         | string                                                              | -           |      |\n| fill       | 动画结束后的填充模式 | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |      |\n| iterations | 动画迭代次数         | number                                                              | -           |      |\n\n**示例：**\n\n```javascript\n// 简单启用\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// 详细配置\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // 动画持续时间（毫秒）\n    easing: 'ease-in-out', // 缓动函数\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\n数据。\n\n#### GraphData\n\n| 属性   | 描述     | 类型                      | 默认值 | 必选 |\n| ------ | -------- | ------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#nodedata)[]   | -      | ✓    |\n| edges  | 边数据   | [EdgeData](#edgedata)[]   | -      | ✓    |\n| combos | 组合数据 | [ComboData](#combodata)[] | -      | ✓    |\n\n#### NodeData\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n#### EdgeData\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n#### ComboData\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- 阅读 [数据](/manual/data) 深入了解图数据，包括不限于数据格式、如何操作数据等。\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\n节点配置项。\n\n#### NodeOptions\n\n| 属性      | 描述                                         | 类型                                                  | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------------------------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](/manual/element/node/base-node#type)           | `circle` |      |\n| style     | 节点样式，包括颜色、大小等                   | [Style](/manual/element/node/base-node#style)         | -        |      |\n| state     | 定义节点在不同状态下的样式                   | [State](/manual/element/node/base-node#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/node/base-node#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](/manual/element/node/base-node#animation) | -        |      |\n\n详见 [Node](/manual/element/node/base-node)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {\n      fill: '#e6f7ff', // 填充色\n      stroke: '#91d5ff', // 边框色\n      lineWidth: 1, // 边框宽度\n      r: 20, // 半径\n      labelText: (d) => d.id, // 标签文本\n    },\n    // 节点状态样式\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\n边配置项\n\n#### EdgeOptions\n\n| 属性      | 描述                                   | 类型                                                  | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------------------------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](/manual/element/edge/base-edge#type)           | `line` |      |\n| style     | 边样式，包括颜色、大小等               | [Style](/manual/element/edge/base-edge#style)         | -      |      |\n| state     | 定义边在不同状态下的样式               | [State](/manual/element/edge/base-edge#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](/manual/element/edge/base-edge#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](/manual/element/edge/base-edge#animation) | -      |      |\n\n详见 [Edge](/manual/element/edge/base-edge)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // 边类型\n    style: {\n      stroke: '#91d5ff', // 边的颜色\n      lineWidth: 2, // 边的宽度\n      endArrow: true, // 是否有箭头\n    },\n    // 边的状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\n组合配置项\n\n| 属性      | 描述                                         | 类型                                                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ------------------------------------------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](/manual/element/combo/base-combo#type)           | `circle` |      |\n| style     | 组合样式，包括颜色、大小等                   | [Style](/manual/element/combo/base-combo#style)         | -        |      |\n| state     | 定义组合在不同状态下的样式                   | [State](/manual/element/combo/base-combo#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/combo/base-combo#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](/manual/element/combo/base-combo#animation) | -        |      |\n\n详见 [Combo](/manual/element/combo/base-combo)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {\n      fill: '#f0f0f0', // 背景色\n      stroke: '#d9d9d9', // 边框色\n      lineWidth: 1, // 边框宽度\n    },\n    // 组合状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\n布局配置项，可以是对象（普通布局）或数组（流水线布局）。\n\n**示例**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // 力导向布局\n    preventOverlap: true, // 防止节点重叠\n    nodeStrength: -50, // 节点之间的斥力\n    edgeStrength: 0.5, // 边的弹性系数\n    iterations: 200, // 迭代次数\n    animation: true, // 启用布局动画\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\n设置图表的主题，可以是内置的 `'light'`、`'dark'` 主题，也可以是自定义主题的名称。设为 `false` 则不使用任何主题。\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置图表的交互行为，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // 使用默认配置启用画布拖拽\n    'zoom-canvas', // 使用默认配置启用画布缩放\n    {\n      type: 'drag-element', // 自定义配置拖拽元素\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // 只允许拖拽节点\n    },\n    function () {\n      console.log(this); // 输出 graph 实例\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- 查看 [交互总览](/manual/behavior/overview) 深入了解交互原理\n- 浏览 [内置交互](/manual/behavior/auto-adapt-label) 获取所有内置交互列表及其配置选项\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n设置图表的插件，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // 启用小地图，使用默认配置\n    {\n      type: 'grid', // 启用网格背景\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // 启用工具栏\n      key: 'graph-toolbar',\n      position: 'top-right', // 位置\n    },\n  ],\n});\n```\n\n- 查看 [插件总览](/manual/plugin/overview) 深入了解插件原理\n- 浏览 [内置插件](/manual/plugin/background) 获取所有内置插件列表及其配置项\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置数据处理，用于在渲染前对数据进行处理，不会影响原始数据。可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // 处理平行边，使用默认配置\n    {\n      type: 'map-node-size', // 根据节点数据映射节点大小\n      field: 'value', // 使用 value 字段的值\n      max: 50, // 最大半径\n      min: 20, // 最小半径\n    },\n  ],\n});\n```\n\n- 查看 [数据处理总览](/manual/transform/overview) 深入了解数据处理原理\n- 浏览 [内置数据处理](/manual/transform/map-node-size) 获取所有内置数据处理列表及其配置项\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** 拓展类型 */\n  type: string;\n  /** 拓展 key，即唯一标识 */\n  key?: string;\n}\n```\n","packages/site/docs/manual/introduction.en.md":"---\ntitle: Introduction\norder: 0\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 is a graph visualization engine. It provides capabilities for graph drawing, layout, analysis, interaction, animation, and other aspects of graph visualization. It aims to offer developers a set of tools that are easy to use, professionally reliable, and highly customizable for graph visualization development.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Rich Elements</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ elements to meet the needs of common scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Flexible Interactions</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ interactions that can be freely combined according to different scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High-Performance Layout Algorithms</h4>\n\n<p style=\"text-align: center;\">High-performance layouts, built-in 10+ common graph layouts, with support for WebGPU and WASM computational acceleration.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Multicolor Themes for Various Scenarios</h4>\n\n<p style=\"text-align: center;\"><img height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D Scenes</h4>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">Supports 3D elements and layouts to create immersive graph visualization scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High Customizability</h4>\n\n<p style=\"text-align: center;\">Elements, layouts, interactions, and plugins are all customizable, enabling every creative idea you have.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Start Your G6 Journey in Just 3 Minutes</h4>\n\n<p style=\"text-align: center;\">Click to enter 👉 <a href=\"/manual/getting-started/quick-start\">Quick Start</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","packages/site/docs/manual/introduction.zh.md":"---\ntitle: 简介\norder: 0\nsidebar: false\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 是一个图可视化引擎。它提供了图的绘制、布局、分析、交互、动画等图可视化能力。旨在为开发者提供一套简单易用、专业可靠、可高度定制的图可视化开发工具</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">丰富元素</h4>\n\n<p style=\"text-align: center;\">内置 10+ 元素，满足常规场景需求</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">灵活交互</h4>\n\n<p style=\"text-align: center;\">内置 10+ 交互，并可根据不同场景自由组合</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高性能布局算法</h4>\n\n<p style=\"text-align: center;\">高性能布局，内置 10+ 常用的图布局，支持 WebGPU、 WASM 计算加速</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">多色主题，适用多种场景</h4>\n\n<p style=\"text-align: center;\"><image height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D 场景</h4>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">支持 3D 元素、布局，打造沉浸式的图可视化场景</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高可定制性</h4>\n\n<p style=\"text-align: center;\">元素、布局、交互、插件统统可定制，实现你的每一个创意</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">仅需 3 分钟，开启 G6 之旅</h4>\n\n<p style=\"text-align: center;\">点击进入👉 <a href=\"/manual/getting-started/quick-start\">快速开始</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","packages/site/docs/manual/layout/AntvDagreLayout.en.md":"---\ntitle: AntvDagre Layout\norder: 2\n---\n\n## Overview\n\nAntvDagre builds upon the original [dagre](https://github.com/dagrejs/dagre/wiki) layout and adds more useful options, such as `nodeOrder`, `edgeLabelSpace`, and more. The `dagre` layout itself is a hierarchical layout suitable for directed acyclic graphs (DAGs), which can automatically handle node direction and spacing, and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## Options\n\n> For more native `dagre` options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout). Here, only some core and new options are listed.\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Diagram\" />\n\n| Property       | Description                                                                                                                                                                                        | Type                                                | Default | Required |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------- | -------- |\n| type           | Layout type                                                                                                                                                                                        | `antv-dagre`                                        | -       | ✓        |\n| rankdir        | Layout direction, options                                                                                                                                                                          | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`    |          |\n| align          | Node alignment, options                                                                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`    |          |\n| nodesep        | Node spacing (px). For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing.                                                                                             | number                                              | 50      |          |\n| nodesepFunc    | Callback for node spacing (px), allows different spacing for different nodes. For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing. Takes precedence over `nodesep`. | (d?: Node) => number                                |         |          |\n| ranksep        | Rank spacing (px). For `TB` or `BT`, it's vertical spacing between adjacent ranks; for `LR` or `RL`, it's horizontal spacing.                                                                      | number                                              | 50      |          |\n| ranksepFunc    | Callback for rank spacing (px), allows different spacing for different ranks. For `TB` or `BT`, it's vertical spacing; for `LR` or `RL`, it's horizontal spacing. Takes precedence over `ranksep`. | (d?: Node) => number                                |         |          |\n| ranker         | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                                                                         | `network-simplex` \\| `tight-tree` \\| `longest-path` | -       |          |\n| nodeSize       | Specify node size for all nodes or each node, used for occupying space and spacing calculation                                                                                                     | Size \\| ((nodeData: Node) => Size)                  | -       |          |\n| controlPoints  | Whether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that consumes `style.controlPoints` as control points                 | boolean                                             | false   |          |\n| begin          | Top-left alignment position of the layout                                                                                                                                                          | [number, number] \\| [number, number, number]        | -       |          |\n| sortByCombo    | Whether to sort nodes in the same rank based on `parentId` in each node's data to avoid Combo overlap                                                                                              | boolean                                             | false   |          |\n| edgeLabelSpace | Whether to reserve space for edge labels                                                                                                                                                           | boolean                                             | true    |          |\n| nodeOrder      | Reference array for node order in the same rank, storing node ids                                                                                                                                  | string[]                                            | -       |          |\n| radial         | Whether to use radial layout based on `dagre`                                                                                                                                                      | boolean                                             | -       |          |\n| focusNode      | Focus node, only effective when `radial` is true                                                                                                                                                   | ID \\| Node \\| null                                  | -       |          |\n| preset         | Reference node positions for layout calculation, usually used to keep transitions smooth when switching data                                                                                       | NodeData[]                                          | -       |          |\n\n> Note: In G6, the control points computed by `antv-dagre` are written into `edge.style.controlPoints`.\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\nNode alignment: U = upper, D = down, L = left, R = right\n\n- `UL`: align to upper left\n- `UR`: align to upper right\n- `DL`: align to lower left\n- `DR`: align to lower right\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\nLayout direction. T = top, B = bottom, L = left, R = right\n\n- `TB`: top to bottom\n- `BT`: bottom to top\n- `LR`: left to right\n- `RL`: right to left\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\nLayout mode\n\n### ranksep\n\n> _number_ **Default:** 50\n\nRank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. `ranksepFunc` has higher priority.\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\nCallback for rank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. Takes precedence over nodesep if set.\n\n### nodesep\n\n> _number_ **Default:** 50\n\nNode spacing (px)\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. `nodesepFunc` has higher priority.\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\nCallback for node spacing (px), allows different spacing for different nodes\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. Takes precedence over nodesep if set.\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\nTop-left alignment position of the layout\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\nWhether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that uses `style.controlPoints` as control points. Adds `style.controlPoints` to edge data.\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\nWhether to reserve space for edge labels\n\nThis affects whether a dummy node is added in the middle of the edge.\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\nFocus node, only effective when `radial` is true\n\n- ID: node id\n- Node: node instance\n- null: cancel focus\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\nReference array for node order in the same rank, stores node ids\n\nIf not specified, dagre's default order is used.\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\nSpecify node size for all or each node.\n\nUsed for collision detection to prevent node overlap\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\nReference node positions for layout calculation\n\nUsually for smooth transitions when switching data. In G6, if updating data, the existing layout result is used as input.\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout based on dagre\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\nWhether to sort nodes in the same rank by their parentId to prevent Combo overlap\n\nRecommended to enable when using Combo\n\n## Suitable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, node direction and spacing are automatically handled\n- **Dependency Graphs**: Display dependencies between packages or modules\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks\n\n## Related Documentation\n\n> The following documents can help you better understand the Dagre layout\n\n- [Graph Layout Algorithms: In-depth Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/AntvDagreLayout.zh.md":"---\ntitle: AntV Dagre 布局 AntvDagre\norder: 2\n---\n\n## 概述\n\nAntvDagre 在原先[dagre](https://github.com/dagrejs/dagre/wiki)布局的基础上增加了更多有用的设置项，比如`nodeOrder`、`edgeLabelSpace`等等。 `dagre`布局本身一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## 配置项\n\n> 更多`dagre`原生配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)，这里仅列出部分核心配置和新增的配置\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性           | 描述                                                                                                                                               | 类型                                                | 默认值 | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------ | ---- |\n| type           | 布局类型                                                                                                                                           | `antv-dagre`                                        | -      | ✓    |\n| rankdir        | 布局方向，可选值                                                                                                                                   | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`   |      |\n| align          | 节点对齐方式，可选值                                                                                                                               | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`   |      |\n| nodesep        | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                                 | number                                              | 50     |      |\n| nodesepFunc    | 节点间距（px）的回调函数，优先级高于 `nodesep`                                                                                                     | (d?: Node) => number                                | -      |      |\n| ranksep        | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                               | number                                              | 50     |      |\n| ranksepFunc    | 层间距（px）的回调函数，优先级高于 `ranksep`                                                                                                       | (d?: Node) => number                                | -      |      |\n| ranker         | 为每个节点分配等级的算法，共支持三种算法：`longest-path`、`tight-tree`、`network-simplex`                                                          | `network-simplex` \\| `tight-tree` \\| `longest-path` | -      |      |\n| nodeSize       | 统一指定或为每个节点指定节点大小，用于占位与间距计算                                                                                               | Size \\| ((nodeData: Node) => Size)                  | -      |      |\n| controlPoints  | 是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'）时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效 | boolean                                             | false  |      |\n| begin          | 布局的左上角对齐位置                                                                                                                               | [number, number] \\| [number, number, number]        | -      |      |\n| sortByCombo    | 同一层节点是否根据每个节点数据中的 `parentId` 进行排序，以防止 Combo 重叠                                                                          | boolean                                             | false  |      |\n| edgeLabelSpace | 是否为边的 label 预留位置                                                                                                                          | boolean                                             | true   |      |\n| nodeOrder      | 同层节点顺序的参考数组，存放节点 id 值                                                                                                             | string[]                                            | -      |      |\n| radial         | 是否基于 `dagre` 进行辐射布局                                                                                                                      | boolean                                             | -      |      |\n| focusNode      | 关注的节点，仅在 `radial` 为 true 时生效                                                                                                           | ID \\| Node \\| null                                  | -      |      |\n| preset         | 布局计算时参考的节点位置，一般用于切换数据时保证重新布局的连续性                                                                                   | NodeData[]                                          | -      |      |\n\n> 补充：在 G6 中，`antv-dagre` 计算得到的控制点会被写入边的 `style.controlPoints`。\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\n节点对齐方式 U：upper（上）；D：down（下）；L：left（左）；R：right（右）\n\n- `UL`:对齐到左上角\n- `UR`:对齐到右上角\n- `DL`:对齐到左下角\n- `DR`:对齐到右下角\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\n布局的方向。T：top（上）；B：bottom（下）；L：left（左）；R：right（右）\n\n- `TB`:从上至下布局\n- `BT`:从下至上布局\n- `LR`:从左至右布局\n- `RL`:从右至左布局\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\n布局的模式\n\n### ranksep\n\n> _number_ **Default:** 50\n\n层间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。ranksepFunc 拥有更高的优先级\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\n层间距（px）的回调函数\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### nodesep\n\n> _number_ **Default:** 50\n\n节点间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。nodesepFunc 拥有更高的优先级\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\n节点间距（px）的回调函数，通过该参数可以对不同节点设置不同的节点间距\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\n布局的左上角对齐位置\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\n是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'） 时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效。本质上就是给边数据增加了 `style.controlPoints`\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\n是否为边的label留位置\n\n这会影响是否在边中间添加dummy node\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\n关注的节点，注意，仅在`radial` 为 true 时生效\n\n- ID: 节点 id\n- Node: 节点实例\n- null: 取消关注\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\n同层节点顺序的参考数组，存放节点 id 值\n\n若未指定，则将按照 dagre 本身机制排列同层节点顺序\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\n统一指定或为每个节点指定节点大小。\n\n用于防止节点重叠时的碰撞检测\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\n布局计算时参考的节点位置\n\n一般用于切换数据时保证重新布局的连续性。在 G6 中，若是更新数据，则将自动使用已存在的布局结果数据作为输入\n\n### radial\n\n> _boolean_\n\n是否基于 dagre 进行辐射布局\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\n同一层节点是否根据每个节点数据中的 parentId 进行排序，以防止 Combo 重叠\n\n建议在有 Combo 的情况下配置\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解 Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/BaseLayout.en.md":"---\ntitle: Common Layout Configuration Options\norder: 1\n---\n\nThis article introduces the common attribute configurations for built-in layouts.\n\n## General Configuration\n\n| Property               | Description                                                                             | Type                                                  | Default    | Required |\n| ---------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------- | -------- |\n| type                   | Layout type, name of built-in or custom layout                                          | [Type](#Type)                                         | -          | ✓        |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in the layout (takes effect when preLayout is true) | boolean                                               | false      |          |\n| nodeFilter             | Nodes participating in the layout                                                       | (node: NodeData) => boolean                           | () => true |          |\n| comboFilter            | Combos participating in the layout                                                      | (combo: ComboData) => boolean                         | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements                           | boolean                                               | false      |          |\n| enableWorker           | Whether to run the layout in a WebWorker                                                | boolean                                               | -          |          |\n| iterations             | Number of iterations for iterative layout                                               | number                                                | -          |          |\n| animation              | Whether to enable layout animation                                                      | boolean                                               | false      |          |\n| width                  | Width of the layout area, defaults to the current container width                       | number                                                | -          |          |\n| height                 | Height of the layout area, defaults to the current container height                     | number                                                | -          |          |\n| center                 | Layout center point                                                                     | [number, number] \\| [number, number, number]          | -          |          |\n| node                   | Node field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |          |\n| edge                   | Edge field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, source?, target? })                | -          |          |\n\nAdditional notes:\n\n- `width` / `height` / `center` are common layout fields uniformly supported by `@antvis/layout`.\n- `node` / `edge` are used to adapt non-standard business fields such as custom `id` / `source` / `target`.\n- `iterations` is the step count used by the G6 runtime to drive iterative layouts, and is not the same as some layouts' internal algorithm parameters.\n\n### Type\n\nSpecifies the layout type, either the name of a built-in layout type or a custom layout.\n\n```js {4}\nconst graph = new Graph({\n  // Other configurations...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\nOptional values include:\n\n- `antv-dagre`: [Custom layout based on dagre](/en/manual/layout/antv-dagre-layout)\n- `circular`: [Circular layout](/en/manual/layout/circular-layout)\n- `combo-combined`: [Layout suitable for combinations](/en/manual/layout/combo-combined-layout)\n- `concentric`: [Concentric layout](/en/manual/layout/concentric-layout)\n- `d3-force`: [Force-directed layout based on D3](/en/manual/layout/d3-force-layout)\n- `d3-force-3d`: [3D Force-directed layout](/en/manual/layout/d3-force3-d-layout)\n- `dagre`: [Dagre layout](/en/manual/layout/dagre-layout)\n- `fishbone`: [Fishbone layout](/en/manual/layout/fishbone)\n- `force`: [Force-directed layout](/en/manual/layout/force-layout)\n- `force-atlas2`: [ForceAtlas2 layout](/en/manual/layout/force-atlas2-layout)\n- `fruchterman`: [Fruchterman layout](/en/manual/layout/fruchterman-layout)\n- `grid`: [Grid layout](/en/manual/layout/grid-layout)\n- `mds`: [MDS layout for high-dimensional data](/en/manual/layout/mds-layout)\n- `radial`: [Radial layout](/en/manual/layout/radial-layout)\n- `random`: [Random layout](/en/manual/layout/random-layout)\n- `snake`: [Snake layout](/en/manual/layout/snake)\n- `compact-box`: [Compact box tree layout](/en/manual/layout/compact-box-layout)\n- `dendrogram`: [Dendrogram layout](/en/manual/layout/dendrogram-layout)\n- `mindmap`: [Mindmap layout](/en/manual/layout/mindmap-layout)\n- `indented`: [Indented tree layout](/en/manual/layout/indented-layout)\n","packages/site/docs/manual/layout/BaseLayout.zh.md":"---\ntitle: 布局通用配置项\norder: 1\n---\n\n本文介绍内置布局通用属性配置。\n\n## 通用配置\n\n| 属性                   | 描述                                                  | 类型                                                  | 默认值     | 必选 |\n| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ---------- | ---- |\n| type                   | 布局类型，内置布局或自定义布局的名称                  | [Type](#Type)                                         | -          | ✓    |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（当 preLayout 为 true 时生效） | boolean                                               | false      |      |\n| nodeFilter             | 参与该布局的节点                                      | (node: NodeData) => boolean                           | () => true |      |\n| comboFilter            | 参与该布局的combo元素                                 | (combo: ComboData) => boolean                         | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                    | boolean                                               | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                           | boolean                                               | -          |      |\n| iterations             | 迭代布局的迭代次数                                    | number                                                | -          |      |\n| animation              | 是否启用布局动画                                      | boolean                                               | false      |      |\n| width                  | 布局区域宽度，默认使用当前容器宽度                    | number                                                | -          |      |\n| height                 | 布局区域高度，默认使用当前容器高度                    | number                                                | -          |      |\n| center                 | 布局中心点                                            | [number, number] \\| [number, number, number]          | -          |      |\n| node                   | 节点字段映射，用于把业务字段映射为布局字段            | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |      |\n| edge                   | 边字段映射，用于把业务字段映射为布局字段              | (datum) => ({ id?, source?, target? })                | -          |      |\n\n补充说明：\n\n- `width` / `height` / `center` 是 `@antvis/layout` 统一支持的通用布局字段。\n- `node` / `edge` 用于适配非标准 `id/source/target` 业务数据。\n- `iterations` 是 G6 运行时用于驱动迭代布局的步数，不等同于某些布局内部自己的算法参数。\n\n### Type\n\n指定布局类型，内置布局类型名称或自定义布局的名称。\n\n```js {4}\nconst graph = new Graph({\n  // 其他配置...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\n可选值有：\n\n- `antv-dagre`：[基于 dagre 定制的布局](/manual/layout/antv-dagre-layout)\n- `circular`：[环形布局](/manual/layout/circular-layout)\n- `combo-combined`：[适用于存在组合的布局](/manual/layout/combo-combined-layout)\n- `concentric`：[同心圆布局](/manual/layout/concentric-layout)\n- `d3-force`[基于 D3 的力导向布局](/manual/layout/d3-force-layout)\n- `d3-force-3d`：[3D力导向布局](/manual/layout/d3-force3-d-layout)\n- `dagre`：[dagre 布局](/manual/layout/dagre-layout)\n- `fishbone`：[鱼骨布局](/manual/layout/fishbone)\n- `force`：[力导向布局](/manual/layout/force-layout)\n- `force-atlas2`：[ForceAtlas2 布局](/manual/layout/force-atlas2-layout)\n- `fruchterman`：[Fruchterman 布局](/manual/layout/fruchterman-layout)\n- `grid`：[网格布局](/manual/layout/grid-layout)\n- `mds`：[高维数据降维算法布局](/manual/layout/mds-layout)\n- `radial`：[径向布局](/manual/layout/radial-layout)\n- `random`：[随机布局](/manual/layout/random-layout)\n- `snake`：[蛇形布局](/manual/layout/snake)\n- `compact-box`：[紧凑树布局](/manual/layout/compact-box-layout)\n- `dendrogram`：[树状布局](/manual/layout/dendrogram-layout)\n- `mindmap`：[思维导图布局](/manual/layout/mindmap-layout)\n- `indented`：[缩进树布局](/manual/layout/indented-layout)\n","packages/site/docs/manual/layout/CircularLayout.en.md":"---\ntitle: Circular Layout\norder: 3\n---\n\n## Overview\n\nCircular layout arranges nodes evenly or at intervals on a circle, and also supports spiral layouts by configuring different startRadius and endRadius. See more circular layout [examples](en/examples#layout-circular) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n**Circular layout**:\n\n- Suitable for networks with equal relationships and no hierarchical structure\n\n**Spiral layout**:\n\n- Suitable for implicit hierarchies or time series graphs (such as organizational charts, propagation networks)\n\n## Basic Usage\n\nOther settings use the default configuration (layout width and height default to the entire canvas container)\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## Options\n\n| Property    | Description                                                                                                       | Type                                          | Default                                   | Required |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------- | -------- |\n| type        | Layout type                                                                                                       | circular                                      | -                                         | ✓        |\n| angleRatio  | How many 2\\*PI between the first and last node                                                                    | number                                        | 1                                         |          |\n| center      | Center of the layout                                                                                              | [number, number]\\|[number, number, number]    | [`layout width` / 2, `layout height` / 2] |          |\n| clockwise   | Whether to arrange clockwise                                                                                      | boolean                                       | true                                      |          |\n| divisions   | Number of segments on the ring (segments will be evenly distributed, effective when endRadius - startRadius != 0) | number                                        | 1                                         |          |\n| nodeSize    | Node size (diameter), used for collision detection                                                                | Size \\| ((nodeData: Node) => Size)            | 10                                        |          |\n| nodeSpacing | Minimum spacing between rings, used to adjust radius                                                              | number \\| ((nodeData: Node) => number)        | 10                                        |          |\n| ordering    | Node ordering on the ring, [see details](#ordering)                                                               | `topology` \\| `topology-directed` \\| `degree` | -                                         |          |\n| radius      | Circle radius, if set, spiral layout configs `startRadius` and `endRadius` are ignored, [see details](#radius)    | number                                        | -                                         |          |\n| startAngle  | Start angle of the layout                                                                                         | number                                        | 0                                         |          |\n| endAngle    | End angle of the layout                                                                                           | number                                        | 2 \\* Math.PI                              |          |\n| startRadius | Start radius for spiral layout, [usage](#spiral-layout)                                                           | number                                        | -                                         |          |\n| endRadius   | End radius for spiral layout                                                                                      | number                                        | -                                         |          |\n| width       | Layout width                                                                                                      | number                                        | canvas width                              |          |\n| height      | Layout height                                                                                                     | number                                        | canvas height                             |          |\n\n### ordering\n\nNode ordering on the ring\n\n- `topology`: topological order\n- `topology-directed`: topological order (directed graph)\n- `degree`: order by degree\n\nIf not set (`null`), the order in the array is used directly\n\n### radius\n\nIf radius, startRadius, and endRadius are not set, the default is `Math.min(layout width, layout height) / 2`, i.e., fills the entire layout area\n\n## Code Examples\n\n### Basic Circular Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### Spiral Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CircularLayout.zh.md":"---\ntitle: 环形布局 Circular\norder: 3\n---\n\n## 概述\n\n环形布局是一种把节点均匀或者按间隔放置在圆上的布局，也支持通过配置 startRadius 和 endRadius 为不一样的值实现螺旋状布局。参考更多环形布局[样例](/examples#layout-circular)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n**环形布局**:\n\n- 适用于平等关系网络、无层级结构的图\n\n**螺旋状布局**:\n\n- 适用于隐式层级或时间序列图（如组织架构、传播网络）\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## 配置项\n\n| 属性        | 描述                                                                                | 类型                                          | 默认值                           | 必选 |\n| ----------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | -------------------------------- | ---- |\n| type        | 布局类型                                                                            | circular                                      | -                                | ✓    |\n| angleRatio  | 从第一个节点到最后节点之间相隔多少个 2\\*PI                                          | number                                        | 1                                |      |\n| center      | 布局的中心                                                                          | [number, number]\\|[number, number, number]    | [`布局宽度` / 2, `布局高度` / 2] |      |\n| clockwise   | 是否顺时针排列                                                                      | boolean                                       | true                             |      |\n| divisions   | 节点在环上的分段数（几个段将均匀分布，在 endRadius - startRadius != 0 时生效）      | number                                        | 1                                |      |\n| nodeSize    | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                      | Size \\| ((nodeData: Node) => Size)            | 10                               |      |\n| nodeSpacing | 环与环之间最小间距，用于调整半径                                                    | number \\| ((nodeData: Node) => number)        | 10                               |      |\n| ordering    | 节点在环上排序的依据，[说明](#ordering)                                             | `topology` \\| `topology-directed` \\| `degree` | -                                |      |\n| radius      | 圆的半径，设置了则螺旋状布局的配置`startRadius`、`endRadius`不生效，[说明](#radius) | number                                        | -                                |      |\n| startAngle  | 布局的开始角度                                                                      | number                                        | 0                                |      |\n| endAngle    | 布局的结束角度                                                                      | number                                        | 2 \\* Math.PI                     |      |\n| startRadius | 螺旋状布局的开始半径，[用法](#螺旋状布局)                                           | number                                        | -                                |      |\n| endRadius   | 螺旋状布局的结束半径                                                                | number                                        | -                                |      |\n| width       | 布局的宽度                                                                          | number                                        | 画布宽度                         |      |\n| height      | 布局的高度                                                                          | number                                        | 画布高度                         |      |\n\n### ordering\n\n节点在环上排序的依据\n\n- `topology`: 按照拓扑排序\n- `topology-directed`: 按照拓扑排序（有向图）\n- `degree`: 按照度数大小排序\n\n不配置（`null`）则直接使用数组中的顺序\n\n### radius\n\n如果radius、startRadius、endRadius都没配置，则默认为最终计算出来的`Math.min(布局宽度, 布局高度) / 2`，即布满整个布局区域\n\n## 代码示例\n\n### 基础环形布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### 螺旋状布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ComboCombinedLayout.en.md":"---\ntitle: ComboCombined Layout\norder: 4\n---\n\n## Overview\n\nComboCombined composite layout is suitable for graph data with composite group structures. It supports flexible configuration of the layout for elements inside combos as well as the layout between the outermost combos and nodes. By default, the internal elements use the Concentric layout, and the outer layout uses the gForce force-directed layout, balancing layout effect and overall stability. See more ComboCombined layout [examples](/en/examples#layout-combo-layout) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts).\n\n## Usage Scenarios\n\n- User profile analysis: Analyze user behavior and product relationships, use user interest circles as combos, display specific products and behavior tags as internal nodes, and help operators identify user consumption paths.\n- Supply chain management graph: Divide suppliers, manufacturers, warehouses, and distributors into combos by role or region, display resources, personnel, or equipment as internal nodes, and clearly show the internal structure of each link in the supply chain.\n\n## Options\n\n| Property     | Description                                                                                                                                        | Type                                                                                       | Default      | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------ | -------- |\n| type         | Layout type                                                                                                                                        | `combo-combined`                                                                           | -            | ✓        |\n| center       | Layout center                                                                                                                                      | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | Graph center |          |\n| layout       | Layout configuration. Can be fixed, or returned dynamically based on `comboId`                                                                     | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -            |          |\n| nodeSize     | Node size (diameter), used for collision detection                                                                                                 | `number` \\| `number[]` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number     | -            |          |\n| nodeSpacing  | Spacing between nodes                                                                                                                              | `number` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number                   | -            |          |\n| comboSpacing | Spacing between combos                                                                                                                             | `number` \\| (d?: unknown) => number                                                        | -            |          |\n| comboPadding | Padding value inside the combo, used only for force calculation, not for rendering. It is recommended to set the same value as the visual padding. | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -            |          |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\nIn `5.1`, it is recommended to use a single `layout` field to choose layouts for different levels, instead of configuring `innerLayout` and `outerLayout` separately.\n\n**Example**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ComboCombinedLayout.zh.md":"---\ntitle: 复合布局 ComboCombined\norder: 4\n---\n\n## 概述\n\nComboCombined 复合布局适用于复合分组结构的图数据展示场景，支持灵活配置 Combo 内部元素的布局以及最外层 Combo 和节点之间的布局。 默认情况内部元素采用 Concentric 同心圆布局，外部布局采用 gForce 力导向布局，兼顾布局效果与整体稳定性。参考更多 ComboCombined 复合布局[样例](/examples#layout-combo-layout)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts)\n\n## 使用场景\n\n- 用户画像分析: 分析用户行为与商品关系，将用户兴趣圈层作为 Combo，内部节点展示具体商品和行为标签，帮助运营人员识别用户消费路径。\n- 供应链管理图：供应商、制造商、仓储、分销商按角色或区域划分 Combo，内部节点展示资源、人员或设备，清晰展示供应链各环节内部结构。\n\n## 配置项\n\n| 属性         | 描述                                                                                                | 类型                                                                                       | 默认值 | 必选 |\n| ------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---- |\n| type         | 布局类型                                                                                            | `combo-combined`                                                                           | -      | ✓    |\n| center       | 布局中心                                                                                            | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | 图中心 |      |\n| layout       | 布局配置。可固定指定，也可根据 `comboId` 动态返回                                                   | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -      |      |\n| nodeSize     | 节点大小（直径）。用于碰撞检测                                                                      | `number` \\| `number[]` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number        | -      |      |\n| nodeSpacing  | 节点间距                                                                                            | `number` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number                      | -      |      |\n| comboSpacing | Combo 之间的间距                                                                                    | `number` \\| (d?: unknown) => number                                                        | -      |      |\n| comboPadding | Combo 内部的 padding 值，不用于渲染，仅用于计算力。推荐设置为与视图上 Combo 内部 padding 值相同的值 | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -      |      |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\n5.1 中推荐使用单个 `layout` 字段为不同层级选择布局，而不是分别配置 `innerLayout` 和 `outerLayout`。\n\n**示例**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## 示例代码\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CompactBoxLayout.en.md":"---\ntitle: CompactBox Layout\norder: 5\n---\n\n## Overview\n\nThe CompactBox layout is suitable for visualizing structured tree data. It is evolved from the classic [Reingold–Tilford tidy layout algorithm](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf), and considers the bounding box of each tree node during layout, effectively maintaining the compactness and hierarchical clarity of the tree structure. See more CompactBox layout [examples](/en/examples#layout-compact-box) and [source code](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox Tidy Tree Layout Example'/>\n\n## Usage Scenarios\n\n- Decision trees: The compact tree layout can visually and intuitively display each decision path.\n- Knowledge graphs: Show hierarchical relationships and connections between concepts. The compact layout can present complex knowledge networks in limited space.\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## Options\n\n| Property  | Description                                                                                                   | Type                                                         | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------- | -------- |\n| type      | Layout type                                                                                                   | `compact-box`                                                | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                       | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                   | `LR`    |          |\n| getSide   | Set whether the node is on the left or right of the root. Only works for `H` direction. [See below](#getside) | (d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string |         |          |\n| getId     | Callback for node id                                                                                          | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => string |         |          |\n| getWidth  | Callback for node width                                                                                       | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHeight | Callback for node height                                                                                      | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHGap   | Callback for horizontal gap                                                                                   | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getVGap   | Callback for vertical gap                                                                                     | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| radial    | Whether to enable radial layout, [see below](#radial)                                                         | boolean                                                      | false   |          |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\nTree layout direction\n\n- `TB`: Root at the top, layout downwards\n- `BT`: Root at the bottom, layout upwards\n- `LR`: Root at the left, layout to the right\n- `RL`: Root at the right, layout to the left\n- `H`: Root in the middle, horizontal symmetric layout. You can use `getSide` to specify the left/right logic for each node\n- `V`: Root in the middle, vertical symmetric layout\n\n### getSide\n\n> _(d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string_\n\nSet whether the node is on the left or right of the root. Only works for `H` direction. If not set, the algorithm will automatically assign left/right. See [getSide auto logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n({ data }) => {\n  // data is a node\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => string_\n\nCallback for node id\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node width\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node height\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for horizontal gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for vertical gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout. If `radial` is `true`, it is recommended to set `direction` to `'LR'` or `'RL'`.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/CompactBoxLayout.zh.md":"---\ntitle: 紧凑树布局 CompactBox\norder: 5\n---\n\n## 概述\n\n紧凑树布局适用于结构化树形数据的展示，基于经典的 [Reingold–Tilford tidy 布局算法](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf) 演进而来，通过布局时综合考虑每个树节点的包围盒，有效保持树结构的紧凑性与层次清晰。参考更多 CompactBox 布局[样例](/examples#layout-compact-box)和[源码](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js)\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox 紧凑树布局示例'/>\n\n## 使用场景\n\n- 决策树: 通过紧凑树布局可简单直观的图形化展示每个决策路径\n- 知识图谱: 展示概念之间的层级关系和连接，紧凑布局可以在有限空间内呈现复杂的知识网络\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                                                                                    | 类型                                                      | 默认值 | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                                | `compact-box`                                             | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                          | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                | `LR`   |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在 `H` 布局方向上生效 | (d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string |        |      |\n| getId     | 节点 id 的回调函数                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => string |        |      |\n| getWidth  | 计算每个节点的宽度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHeight | 计算每个节点的高度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHGap   | 计算每个节点的水平间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getVGap   | 计算每个节点的垂直间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)                                                                     | boolean                                                   | false  |      |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\n树布局方向\n\n- `TB`：根节点在上，往下布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*KrAqTrFbNjMAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `BT`：根节点在下，往上布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vNmOTJ4q0uwAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `LR`：根节点在左，往右布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ffD6S74MXw4AAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `RL`：根节点在右，往左布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vTg2SJbtj_sAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `H`：根节点在中间，水平对称布局。可传入 `getSide` 方法指定每个节点的左右分布逻辑\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0GsIQISvieYAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n### getSide\n\n> _(d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在 `direction` 为 `H` 时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考 [getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n({ data }) => {\n  // data 是一个节点\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => string_\n\n节点 id 的回调函数\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\n是否按照辐射状布局。若 `radial` 为 `true`，建议 `direction` 设置为 `'LR'` 或 `'RL'`\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/layout/ConcentricLayout.en.md":"---\ntitle: Concentric Layout\norder: 6\n---\n\n## Overview\n\nThe concentric layout arranges nodes in layers according to a certain sorting rule, with each layer of nodes placed around a common center. See more concentric layout [examples](/en/examples#layout-concentric) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n- Layered data visualization, such as permission structures, organizational charts, etc., with the center as the top-level role and outer rings as lower-level nodes.\n- Visualization of ranking analysis results, with high-importance nodes in the center and low-importance nodes on the periphery, quickly expressing the relative influence of nodes in the graph.\n\n## Options\n\n| Property       | Description                                                                                                                                                                 | Type                                               | Default                                                   | Required |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- | -------- | --------- | --- |\n| type           | Layout type                                                                                                                                                                 | `concentric`                                       | -                                                         | ✓        |\n| center         | Center position of the circular layout, defaults to the center of the container                                                                                             | [number, number] \\| [number, number, number]       | -                                                         |          |\n| clockwise      | Whether to arrange nodes clockwise                                                                                                                                          | boolean                                            | false                                                     |          |\n| equidistant    | Whether the distance between rings is equal                                                                                                                                 | boolean                                            | false                                                     |          |\n| width          | Layout width, defaults to container width                                                                                                                                   | number                                             | -                                                         |          |\n| height         | Layout height, defaults to container height                                                                                                                                 | number                                             | -                                                         |          |\n| sortBy         | The property to sort by (node attribute name). The higher the value, the closer to the center. If set to 'degree', nodes with higher degree are placed closer to the center | string                                             | `degree`                                                  |          |\n| maxLevelDiff   | Maximum attribute difference in the same layer. If undefined, set to maxValue / 4, where maxValue is the maximum value of the sorting property                              | number                                             | undefined                                                 |          |\n| nodeSize       | Node size (diameter), used for collision detection                                                                                                                          | number \\| number[] \\| ((nodeData: Node) => number) | 30                                                        |          |\n| nodeSpacing    | Minimum spacing between rings, used to adjust the radius                                                                                                                    | number \\| number[] \\| ((node?: Node) => number)    | 10                                                        |          |\n| preventOverlap | Whether to prevent overlap. Must be used with nodeSize or data.size. Only works if node size is set in data or in this layout config.                                       | boolean                                            | false                                                     |          |\n| startAngle     | The angle (in radians) to start laying out nodes                                                                                                                            | number                                             | 3 / 2 \\* Math.PI                                          |          |\n| sweep          | The angle difference between the first and last node in the same layer. If undefined, it is set to `2 _ Math.PI _ (1 - 1 /                                                  | level.nodes                                        | )`, where `level.nodes` is the set of nodes in that layer | number   | undefined |     |\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: 'Center', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/ConcentricLayout.zh.md":"---\ntitle: 同心圆布局 Concentric\norder: 6\n---\n\n## 概述\n\n同心圆布局是一种将节点根据某种排序规则分层，并以圆心为中心、沿圆周排列每层节点的布局方式。参考更多同心圆布局[样例](/examples#layout-concentric)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n- 分层数据可视化，如权限控制结构、组织架构图等，中心是顶级角色，外圈为下级节点。\n- 排序分析结果可视化，高重要度放中心，低重要度放外围，快速表达图中节点的相对影响力。\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                        | 类型                                               | 默认值           | 必选 |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------- | ---- |\n| type           | 布局类型                                                                                                                                                                                                    | `concentric`                                       | -                | ✓    |\n| center         | 圆形布局的中心位置，默认为当前容器的中心位置                                                                                                                                                                | [number, number] \\| [number, number, number]       | -                |      |\n| clockwise      | 是否按照顺时针排列                                                                                                                                                                                          | boolean                                            | false            |\n| equidistant    | 环与环之间的距离是否相等                                                                                                                                                                                    | boolean                                            | false            |      |\n| width          | 布局的宽度，默认使用容器宽度                                                                                                                                                                                | number                                             | -                |      |\n| height         | 布局的高度，默认使用容器高度                                                                                                                                                                                | number                                             | -                |      |\n| sortBy         | 指定排序的依据（节点属性名）<br>数值越高则该节点被放置得越中心。若为 degree，则会计算节点的度数，度数越高，节点将被放置得越中心                                                                             | string                                             | `degree`         |      |\n| maxLevelDiff   | 同一层节点的最大属性差值<br>若为 undefined，则将会被设置为 maxValue / 4 ，其中 maxValue 为最大的排序依据的属性值。例如，若 sortBy 为 'degree'，则 maxValue 为所有节点中度数最大的节点的度数                 | number                                             | undefined        |      |\n| nodeSize       | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                                                                                                                                              | number \\| number[] \\| ((nodeData: Node) => number) | 30               |      |\n| nodeSpacing    | 环与环之间最小间距，用于调整半径                                                                                                                                                                            | number \\| number[] \\| ((node?: Node) => number)    | 10               |      |\n| preventOverlap | 是否防止重叠<br>必须配合 nodeSize 属性或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测                        | boolean                                            | false            |      |\n| startAngle     | 开始布局节点的弧度                                                                                                                                                                                          | number                                             | 3 / 2 \\* Math.PI |      |\n| sweep          | 同一层中第一个节点与最后一个节点之间的弧度差<br>若为 undefined ，则将会被设置为 2 \\* Math.PI \\* (1 - 1 / \\|level.nodes\\|) ，其中 level.nodes 为该算法计算出的每一层的节点，\\|level.nodes\\| 代表该层节点数量 | number                                             | undefined        |      |\n\n## 代码示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/D3Force3DLayout.en.md":"---\ntitle: 3D Force-Directed Layout\norder: 7\n---\n\n## Overview\n\nThe D3Force3D layout is a 3D extension based on [d3-force](https://d3js.org/d3-force), which simulates physical forces in three-dimensional space to achieve automatic layout. Compared to 2D layouts, it adds force effects in the Z-axis direction, allowing richer data relationships to be displayed in 3D space.\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D Force-Directed Layout Illustration\" />\n\n## Core Concepts\n\n### Force System\n\nD3Force3D extends the traditional 2D force-directed layout with the following forces:\n\n- **3D Centering Force**: Pulls nodes toward the center point in 3D space\n- **3D Collision Force**: Prevents node overlap in 3D space\n- **3D Radial Force**: Attracts nodes to a sphere in 3D space\n- **3D Axis Forces**: Applies forces along the X, Y, and Z axes\n\n### Iteration System\n\nThe layout is computed through iterations, mainly involving the following parameters:\n\n- **alpha**: The current energy value of the iteration, controlling node movement speed\n- **alphaDecay**: The decay rate of the energy value\n- **alphaMin**: The minimum energy value; iteration stops below this value\n- **velocityDecay**: The velocity decay factor\n\n## Options\n\n| Property        | Description                                                      | Type                                                                       | Default       | Required |\n| --------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------- | -------- |\n| type            | Layout type                                                      | string                                                                     | `d3-force-3d` | ✓        |\n| nodeSize        | Node size (diameter), used for collision detection               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -             |          |\n| iterations      | Number of force iterations; higher means more precise but slower | number                                                                     | -             |          |\n| numDimensions   | Number of dimensions (2 or 3)                                    | number                                                                     | 3             |          |\n| forceSimulation | Custom force simulation method                                   | Simulation<NodeDatum, EdgeDatum>                                           | -             |          |\n| onTick          | Callback for each iteration                                      | (data: LayoutMapping) => void                                              | -             |          |\n| randomSource    | Random number generator                                          | () => number                                                               | -             |          |\n\n### Iteration Control\n\n| Property      | Description                   | Type   | Default | Required |\n| ------------- | ----------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold | number | 1       |          |\n| alphaDecay    | Convergence decay rate (0-1)  | number | 0.028   |          |\n| alphaMin      | Stop iteration threshold      | number | 0.001   |          |\n| alphaTarget   | Target convergence threshold  | number | 0       |          |\n| velocityDecay | Velocity decay factor         | number | 0.4     |          |\n\n### Force Model Options\n\n#### Centering Force (center)\n\n| Property        | Description         | Type   | Default | Required |\n| --------------- | ------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate | number | 0       |          |\n| center.y        | Center y coordinate | number | 0       |          |\n| center.z        | Center z coordinate | number | 0       |          |\n| center.strength | Force strength      | number | 1       |          |\n\n#### Collision Force (collide)\n\n| Property           | Description          | Type                                                                       | Default | Required |\n| ------------------ | -------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| collide.radius     | Collision radius     | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10      |          |\n| collide.strength   | Force strength       | number                                                                     | 1       |          |\n| collide.iterations | Collision iterations | number                                                                     | 1       |          |\n\n#### Link Force (link)\n\n| Property        | Description           | Type                                                                       | Default | Required |\n| --------------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| link.id         | Edge id generator     | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |          |\n| link.distance   | Ideal edge length     | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |          |\n| link.strength   | Force strength        | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |          |\n| link.iterations | Link force iterations | number                                                                     | 1       |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                  | Type                                                                       | Default  | Required |\n| -------------------- | ---------------------------- | -------------------------------------------------------------------------- | -------- | -------- |\n| manyBody.strength    | Force strength               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy          | number                                                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum interaction distance | number                                                                     | 1        |          |\n| manyBody.distanceMax | Maximum interaction distance | number                                                                     | Infinity |          |\n\n#### Radial Force (radial)\n\n| Property        | Description     | Type                                                                       | Default | Required |\n| --------------- | --------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| radial.strength | Force strength  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1     |          |\n| radial.radius   | Target radius   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100     |          |\n| radial.x        | Sphere center x | number                                                                     | 0       |          |\n| radial.y        | Sphere center y | number                                                                     | 0       |          |\n| radial.z        | Sphere center z | number                                                                     | 0       |          |\n\n#### Axis Forces (x, y, z)\n\nEach axis can be configured separately:\n\n| Property   | Description           | Type                                                                       | Default | Required |\n| ---------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| x.strength | X-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| x.x        | Target x coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.strength | Y-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.y        | Target y coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.strength | Z-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.z        | Target z coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n","packages/site/docs/manual/layout/D3Force3DLayout.zh.md":"---\ntitle: 3D D3力导向布局 D3Force3D\norder: 7\n---\n\n## 概述\n\nD3Force3D 布局是基于 [d3-force](https://d3js.org/d3-force) 的三维扩展版本，通过在三维空间中模拟物理力的作用来实现自动布局。相比二维布局，它增加了 Z 轴方向的力作用，能够在三维空间中展现更丰富的数据关系。\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D 力导向布局示意图\" />\n\n## 核心概念\n\n### 力系统\n\nD3Force3D 在传统二维力导向布局的基础上，扩展了以下力的作用：\n\n- **三维中心力**：将节点拉向三维空间的中心点\n- **三维碰撞力**：在三维空间中防止节点重叠\n- **三维径向力**：将节点吸引到三维空间中的球面上\n- **三维坐标力**：分别在 X、Y、Z 三个方向上施加作用力\n\n### 迭代系统\n\n布局计算通过迭代来实现，主要涉及以下参数：\n\n- **alpha**：当前迭代的活力值，控制节点移动速度\n- **alphaDecay**：活力值的衰减率\n- **alphaMin**：最小活力值，低于此值停止迭代\n- **velocityDecay**：速度衰减因子\n\n## 配置项\n\n| 属性            | 描述                                         | 类型                                                                       | 默认值        | 必选 |\n| --------------- | -------------------------------------------- | -------------------------------------------------------------------------- | ------------- | ---- |\n| type            | 布局类型                                     | string                                                                     | `d3-force-3d` | ✓    |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10            |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大 | number                                                                     | -             |      |\n| numDimensions   | 维度数量，固定为 3                           | number                                                                     | 3             |      |\n| forceSimulation | 自定义力模拟方法                             | Simulation<NodeDatum, EdgeDatum>                                           | -             |      |\n| onTick          | 每次迭代的回调函数                           | (data: LayoutMapping) => void                                              | -             |      |\n| randomSource    | 随机数生成函数                               | () => number                                                               | -             |      |\n\n### 迭代控制\n\n| 属性          | 描述                  | 类型   | 默认值 | 必选 |\n| ------------- | --------------------- | ------ | ------ | ---- |\n| alpha         | 当前迭代收敛阈值      | number | 1      |      |\n| alphaDecay    | 收敛阈值衰减率（0-1） | number | 0.028  |      |\n| alphaMin      | 停止迭代的阈值        | number | 0.001  |      |\n| alphaTarget   | 目标收敛阈值          | number | 0      |      |\n| velocityDecay | 速度衰减因子          | number | 0.4    |      |\n\n### 力模型配置\n\n#### 中心力（center）\n\n| 属性            | 描述          | 类型   | 默认值 | 必选 |\n| --------------- | ------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标 | number | 0      |      |\n| center.y        | 中心点 y 坐标 | number | 0      |      |\n| center.z        | 中心点 z 坐标 | number | 0      |      |\n| center.strength | 力的强度      | number | 1      |      |\n\n#### 碰撞力（collide）\n\n| 属性               | 描述               | 类型                                                                       | 默认值 | 必选 |\n| ------------------ | ------------------ | -------------------------------------------------------------------------- | ------ | ---- |\n| collide.radius     | 碰撞半径           | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10     |      |\n| collide.strength   | 力的强度           | number                                                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数 | number                                                                     | 1      |      |\n\n#### 链接力（link）\n\n| 属性            | 描述             | 类型                                                                       | 默认值  | 必选 |\n| --------------- | ---------------- | -------------------------------------------------------------------------- | ------- | ---- |\n| link.id         | 边的 id 生成函数 | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |      |\n| link.distance   | 理想边长         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |      |\n| link.strength   | 力的强度         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |      |\n| link.iterations | 链接力的迭代次数 | number                                                                     | 1       |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                      | 类型                                                                       | 默认值   | 必选 |\n| -------------------- | ------------------------- | -------------------------------------------------------------------------- | -------- | ---- |\n| manyBody.strength    | 力的强度                  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数 | number                                                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离              | number                                                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离              | number                                                                     | Infinity |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述        | 类型                                                                       | 默认值 | 必选 |\n| --------------- | ----------- | -------------------------------------------------------------------------- | ------ | ---- |\n| radial.strength | 力的强度    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1    |      |\n| radial.radius   | 目标半径    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100    |      |\n| radial.x        | 球心 x 坐标 | number                                                                     | 0      |      |\n| radial.y        | 球心 y 坐标 | number                                                                     | 0      |      |\n| radial.z        | 球心 z 坐标 | number                                                                     | 0      |      |\n\n#### 坐标力（x、y、z）\n\n每个方向的力可以单独配置：\n\n| 属性       | 描述             | 类型                                                                       | 默认值 | 必选 |\n| ---------- | ---------------- | -------------------------------------------------------------------------- | ------ | ---- |\n| x.strength | X 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| x.x        | 目标 x 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.strength | Y 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.y        | 目标 y 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.strength | Z 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.z        | 目标 z 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n","packages/site/docs/manual/layout/D3ForceLayout.en.md":"---\ntitle: D3 Force-Directed Layout\norder: 8\n---\n\n## Overview\n\nThe D3Force layout is a force-directed layout based on [d3-force](https://d3js.org/d3-force). It simulates physical forces (such as attraction, repulsion, collision, etc.) to make the graph reach a stable state with minimal energy.\n\nThe main features of this layout are:\n\n1. **Automatic arrangement**: No need to manually set node positions, the system will automatically find suitable positions\n2. **Real-time adjustment**: When you drag a node, other nodes will adjust their positions in real time\n3. **Flexible configuration**:\n   - You can adjust the attraction and repulsion between nodes\n   - You can set the ideal length of edges\n   - You can fix the positions of important nodes\n4. **Animation effect**: Nodes move with smooth animation, making changes more natural\n\n<img alt=\"D3Force layout diagram\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Core Concepts\n\n### Force System\n\nThe D3Force layout simulates five different forces to achieve automatic layout. Imagine a physical world where these forces act simultaneously and eventually reach equilibrium:\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> Note: The arrows of different colors in the diagram represent different types of forces. In the actual layout, these forces are invisible and also affected by other forces.\n\n- **Link Force**: Imagine nodes connected by rubber bands, which pull connected nodes to a suitable distance. The tightness of the rubber band is the force strength, and the ideal length is the distance we set.\n- **Many-Body Force**: Similar to magnets, it allows all nodes to attract or repel each other. When the force strength is negative, nodes repel each other (like like poles of magnets); when positive, they attract (like opposite poles). This force determines the density of the graph.\n- **Center Force**: Like all nodes are tied to the center of the canvas by an invisible string. This force prevents nodes from drifting too far and keeps the graph centered.\n- **Collision Force**: Treats nodes as solid balls. When nodes get too close, they automatically bounce apart. This force mainly prevents node overlap and improves readability.\n- **Radial Force**: Imagine an invisible ring that attracts nodes to the ring. By setting the radius and force strength, nodes can form a beautiful circular layout.\n\n### Iteration System\n\nLayout calculation is an iterative process with two key concepts:\n\n#### Alpha Value (Energy)\n\nLike the \"energy\" of the layout, it determines how vigorously nodes move:\n\n- **Initial state**: Alpha = 1, nodes move vigorously\n- **During calculation**: Alpha gradually decreases, node movement slows\n- **End state**: When Alpha < alphaMin, nodes stop moving\n\n#### Iterations\n\nControls the number of times forces are applied in each calculation:\n\n- **Effect**: The larger the value, the more precise the layout, but the slower the computation\n- **Adjustment**:\n  - Simple graphs: use the default value\n  - Complex graphs: increase the number of iterations as needed\n  - Real-time interaction: use fewer iterations\n\n> Tip: Iterations and alpha value work together. Increasing iterations makes each step more precise, while alpha controls the overall progress.\n\n## Options\n\n| Property        | Description                                        | Type                                       | Default    | Required |\n| --------------- | -------------------------------------------------- | ------------------------------------------ | ---------- | -------- |\n| type            | Layout type                                        | string                                     | 'd3-force' | ✓        |\n| centerX         | Layout center x coordinate                         | number                                     | width / 2  |          |\n| centerY         | Layout center y coordinate                         | number                                     | height / 2 |          |\n| centerStrength  | Center force strength                              | number                                     | -          |          |\n| nodeSize        | Node size (diameter), for collision detection      | number \\| ((node, index, nodes) => number) | 10         |          |\n| nodeSpacing     | Extra spacing between nodes                        | number \\| ((node, index, nodes) => number) | 0          |          |\n| iterations      | Number of force iterations, higher is more precise | number                                     | -          |          |\n| onTick          | Callback for each iteration, for real-time results | (data: LayoutMapping) => void              | -          |          |\n| forceSimulation | Custom force simulation, defaults to d3.js method  | Simulation<NodeDatum, EdgeDatum>           | -          |          |\n| randomSource    | Function to generate random numbers                | () => number                               | -          |          |\n\n### Iteration Control\n\n| Property      | Description                                          | Type   | Default | Required |\n| ------------- | ---------------------------------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold, controls activity     | number | 1       |          |\n| alphaMin      | Minimum threshold to stop, when alpha < this, stop   | number | 0.001   |          |\n| alphaDecay    | Decay rate of alpha, [0, 1], 0.028 ≈ 300 iterations  | number | 0.028   |          |\n| alphaTarget   | Target alpha, system tries to converge to this value | number | 0       |          |\n| velocityDecay | Velocity decay factor, higher means slower movement  | number | 0.4     |          |\n\n### Force Model Options\n\n#### Link Force (link)\n\n| Property        | Description                                  | Type                                       | Default     | Required |\n| --------------- | -------------------------------------------- | ------------------------------------------ | ----------- | -------- |\n| link.id         | Function to generate edge id                 | (edge, index, edges) => string             | (e) => e.id |          |\n| link.distance   | Ideal edge length                            | number \\| ((edge, index, edges) => number) | 30          |          |\n| link.strength   | Force strength, higher means closer to ideal | number \\| ((edge, index, edges) => number) | 1           |          |\n| link.iterations | Number of link force iterations              | number                                     | 1           |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                                                     | Type                                       | Default  | Required |\n| -------------------- | --------------------------------------------------------------- | ------------------------------------------ | -------- | -------- |\n| manyBody.strength    | Force strength, negative for repulsion, positive for attraction | number \\| ((node, index, nodes) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy, smaller is more accurate                   | number                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum distance, prevents excessive force                      | number                                     | 1        |          |\n| manyBody.distanceMax | Maximum distance, beyond which no force is applied              | number                                     | Infinity |          |\n\n#### Center Force (center)\n\n| Property        | Description                                   | Type   | Default | Required |\n| --------------- | --------------------------------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate                           | number | -       |          |\n| center.y        | Center y coordinate                           | number | -       |          |\n| center.strength | Force strength, higher means closer to center | number | -       |          |\n\n> Note: In `5.1`, `centerX` / `centerY` are the recommended shortcut fields. If you configure the `center` force directly, it follows the native `d3-force` style.\n\n#### Collision Force (collide)\n\n| Property           | Description                                     | Type                                       | Default | Required |\n| ------------------ | ----------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| collide.radius     | Collision radius, nodes repel if closer         | number \\| ((node, index, nodes) => number) | 10      |          |\n| collide.strength   | Force strength, higher means stronger repulsion | number                                     | 1       |          |\n| collide.iterations | Number of collision iterations                  | number                                     | 1       |          |\n\n#### Radial Force (radial)\n\n| Property        | Description                                   | Type                                       | Default | Required |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| radial.strength | Force strength, higher means closer to radius | number \\| ((node, index, nodes) => number) | 0.1     |          |\n| radial.radius   | Target radius, nodes are attracted to circle  | number \\| ((node, index, nodes) => number) | 100     |          |\n| radial.x        | Center x coordinate                           | number                                     | 0       |          |\n| radial.y        | Center y coordinate                           | number                                     | 0       |          |\n\n#### X Axis Force (x)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| x.strength | Force strength in x direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| x.x        | Target x coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n#### Y Axis Force (y)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| y.strength | Force strength in y direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| y.y        | Target y coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n## Code Examples\n\n### Prevent Node Overlap\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\nSee [Example - Prevent Node Overlap in Force-Directed Layout](/en/examples/layout/force-directed/#prevent-overlap)\n\n### Team Clustering Layout\n\nThis example shows how to use force-directed layout for team clustering, where nodes of different teams automatically cluster together.\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // Team A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // Team B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // Team C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // Team A internal connections\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // Team B internal connections\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // Team C internal connections\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // Few connections between teams\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// Create mock data with nodes from different teams\nconst data = {\n  nodes: [\n    // Team A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // Team B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // Team C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // Team A internal connections\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // Team B internal connections\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // Team C internal connections\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // Few connections between teams\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\nMain configuration notes:\n\n- `link.distance`: Shorter within teams, longer between teams\n- `link.strength`: Stronger within teams, weaker between teams\n- `manyBody.strength`: Controls repulsion between nodes\n- `collide`: Prevents node overlap\n- `center`: Keeps the layout centered\n\nSee also [Customize parameters for different nodes](/en/examples/layout/force-directed/#functional-params).\n","packages/site/docs/manual/layout/D3ForceLayout.zh.md":"---\ntitle: D3力导向布局 D3Force\norder: 8\n---\n\n## 概述\n\nD3Force 布局是基于 [d3-force](https://d3js.org/d3-force) 实现的力导向布局。它通过模拟物理力的作用（如引力、斥力、碰撞等），使图布局达到一个能量最小的稳定状态。\n\n这种布局的主要特点是：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的理想长度\n   - 可以固定某些重要节点的位置\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img alt=\"D3Force 布局示意图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 核心概念\n\n### 力系统 Force System\n\nD3Force 布局通过模拟五种不同的力来实现自动布局。想象一个物理世界，这些力同时作用，最终达到平衡：\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> 注：图中不同颜色的箭头代表不同类型的力，实际布局中这些力是无形的，同时也会受其他力影响。\n\n- **链接力**（Link Force）：想象节点之间连着橡皮筋，可以把相连的节点拉到合适的距离。橡皮筋的松紧度就是力的强度（strength），理想长度就是我们设置的距离（distance）。\n- **多体力**（Many-Body Force）：类似磁铁的效果，可以让所有节点互相吸引或排斥。力的强度为负值时节点会互相排斥（像相同磁极），为正值时会互相吸引（像相反磁极）。这个力决定了图的疏密程度。\n- **中心力**（Center Force）：就像所有节点都被一根看不见的绳子拴在画布中心。这个力可以防止节点飘得太远，让整个图保持在画布的中心位置。\n- **碰撞力**（Collision Force）：让节点变成有实体大小的小球，当节点太近时会自动弹开。这个力主要用来防止节点重叠，提高图的可读性。\n- **径向力**（Radial Force）：想象有一个看不见的圆环，这个力会把节点吸引到圆环上。通过设置圆的半径和力的强度，可以让节点形成漂亮的环形布局。\n\n### 迭代系统（Iteration System）\n\n布局计算是一个反复调整的过程，包含两个关键概念：\n\n#### Alpha 值（活力值）\n\n就像布局的\"能量\"，决定节点移动的剧烈程度：\n\n- **初始状态**：Alpha = 1，节点移动剧烈\n- **计算过程**：Alpha 值逐渐降低，节点移动变缓\n- **结束状态**：当 Alpha < alphaMin 时，节点停止移动\n\n#### 迭代次数（Iterations）\n\n控制每次计算时力的作用次数：\n\n- **作用**：值越大，布局越精确，但计算越慢\n- **调节**：\n  - 简单图：使用默认值即可\n  - 复杂图：可以适当增加迭代次数\n  - 实时交互：建议使用较小的迭代次数\n\n> 提示：迭代次数（iterations）和活力值（alpha）是相互配合的。增加迭代次数可以让每一步计算更精确，而活力值则控制整体计算的进度。\n\n## 配置项\n\n| 属性            | 描述                                          | 类型                                       | 默认值     | 必选 |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ---------- | ---- |\n| type            | 布局类型                                      | string                                     | 'd3-force' | ✓    |\n| centerX         | 布局中心点 x 坐标                             | number                                     | width / 2  |      |\n| centerY         | 布局中心点 y 坐标                             | number                                     | height / 2 |      |\n| centerStrength  | 中心力强度                                    | number                                     | -          |      |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠    | number \\| ((node, index, nodes) => number) | 10         |      |\n| nodeSpacing     | 节点间额外间距                                | number \\| ((node, index, nodes) => number) | 0          |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大  | number                                     | -          |      |\n| onTick          | 每次迭代的回调函数，用于实时获取布局结果      | (data: LayoutMapping) => void              | -          |      |\n| forceSimulation | 自定义力模拟方法，若不指定则使用 d3.js 的方法 | Simulation<NodeDatum, EdgeDatum>           | -          |      |\n| randomSource    | 用于生成随机数的函数                          | () => number                               | -          |      |\n\n### 迭代控制\n\n| 属性          | 描述                                                   | 类型   | 默认值 | 必选 |\n| ------------- | ------------------------------------------------------ | ------ | ------ | ---- |\n| alpha         | 当前迭代的收敛阈值，控制布局的活跃程度                 | number | 1      |      |\n| alphaMin      | 停止迭代的最小阈值，当 alpha 小于该值时停止迭代        | number | 0.001  |      |\n| alphaDecay    | 收敛阈值的衰减率，范围 [0, 1]，0.028 对应约 300 次迭代 | number | 0.028  |      |\n| alphaTarget   | 目标收敛阈值，系统会尝试将 alpha 收敛到该值            | number | 0      |      |\n| velocityDecay | 速度衰减因子，值越大节点运动越缓慢                     | number | 0.4    |      |\n\n### 力模型配置\n\n#### 链接力（link）\n\n| 属性            | 描述                               | 类型                                       | 默认值      | 必选 |\n| --------------- | ---------------------------------- | ------------------------------------------ | ----------- | ---- |\n| link.id         | 边的 id 生成函数                   | (edge, index, edges) => string             | (e) => e.id |      |\n| link.distance   | 理想边长，边会趋向于该长度         | number \\| ((edge, index, edges) => number) | 30          |      |\n| link.strength   | 力的强度，值越大边长越接近理想边长 | number \\| ((edge, index, edges) => number) | 1           |      |\n| link.iterations | 链接力的迭代次数                   | number                                     | 1           |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                                                  | 类型                                       | 默认值   | 必选 |\n| -------------------- | ----------------------------------------------------- | ------------------------------------------ | -------- | ---- |\n| manyBody.strength    | 力的强度，负值为斥力，正值为引力                      | number \\| ((node, index, nodes) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数，值越小越精确但性能消耗越大 | number                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离，防止力过大                              | number                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离，超过该距离的节点不产生力                | number                                     | Infinity |      |\n\n#### 中心力（center）\n\n| 属性            | 描述                               | 类型   | 默认值 | 必选 |\n| --------------- | ---------------------------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标                      | number | -      |      |\n| center.y        | 中心点 y 坐标                      | number | -      |      |\n| center.strength | 力的强度，值越大节点越趋向于中心点 | number | -      |      |\n\n> 补充：5.1 中推荐优先使用 `centerX` / `centerY` 作为快捷配置；如果直接配置 `center` force，则按 d3-force 原生写法生效。\n\n#### 碰撞力（collide）\n\n| 属性               | 描述                                   | 类型                                       | 默认值 | 必选 |\n| ------------------ | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| collide.radius     | 碰撞半径，小于该距离的节点会产生排斥力 | number \\| ((node, index, nodes) => number) | 10     |      |\n| collide.strength   | 力的强度，值越大排斥效果越明显         | number                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数                     | number                                     | 1      |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述                                   | 类型                                       | 默认值 | 必选 |\n| --------------- | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| radial.strength | 力的强度，值越大节点越趋向于目标半径   | number \\| ((node, index, nodes) => number) | 0.1    |      |\n| radial.radius   | 目标半径，节点会被吸引到该半径的圆周上 | number \\| ((node, index, nodes) => number) | 100    |      |\n| radial.x        | 圆心 x 坐标                            | number                                     | 0      |      |\n| radial.y        | 圆心 y 坐标                            | number                                     | 0      |      |\n\n#### X 轴力（x）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| x.strength | X 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| x.x        | 目标 x 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n#### Y 轴力（y）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| y.strength | Y 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| y.y        | 目标 y 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n## 代码示例\n\n### 防止节点重叠\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\n效果见 [示例 - 力导向布局防止节点重叠](/examples/layout/force-directed/#prevent-overlap)\n\n### 团队聚类布局\n\n该示例展示了如何使用力导向布局实现团队聚类效果，不同团队的节点会自动聚集在一起。\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // 团队 A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // 团队 B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // 团队 C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // 团队 A 内部连接\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // 团队 B 内部连接\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // 团队 C 内部连接\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // 团队间的少量连接\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 创建模拟数据，包含不同团队的节点\nconst data = {\n  nodes: [\n    // 团队 A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // 团队 B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // 团队 C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // 团队 A 内部连接\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // 团队 B 内部连接\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // 团队 C 内部连接\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // 团队间的少量连接\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\n主要配置说明：\n\n- `link.distance`：团队内部距离短，团队间距离长\n- `link.strength`：团队内部连接强度大，团队间连接强度小\n- `manyBody.strength`：控制节点间排斥力\n- `collide`：防止节点重叠\n- `center`：保持整体布局在画布中心\n\n还可以参考 [定制不同节点的参数](/examples/layout/force-directed/#functional-params) 示例。\n","packages/site/docs/manual/layout/DagreLayout.en.md":"---\ntitle: Dagre Layout\norder: 9\n---\n\n# Dagre Layout\n\n## Overview\n\nDagre is a hierarchical layout suitable for directed acyclic graphs (DAGs). It can automatically handle the direction and spacing between nodes and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## Options\n\n> For more options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Illustration\" />\n\n| Property        | Description                                                                                                                                | Type                                                | Default           | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- | ----------------- | -------- |\n| type            | Layout type                                                                                                                                | `dagre`                                             | -                 | ✓        |\n| rankdir         | Layout direction, options                                                                                                                  | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |          |\n| align           | Node alignment, options                                                                                                                    | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |          |\n| nodesep         | Node spacing (px). For `TB` or `BT`, it is the horizontal spacing; for `LR` or `RL`, it is the vertical spacing                            | number                                              | 50                |          |\n| ranksep         | Rank spacing (px). For `TB` or `BT`, it is the vertical spacing between adjacent ranks; for `LR` or `RL`, it is the horizontal spacing     | number                                              | 100               |          |\n| ranker          | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                 | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |          |\n| directed        | Whether to treat the graph as directed                                                                                                     | boolean                                             | true              |          |\n| compound        | Whether to support nested structures                                                                                                       | boolean                                             | true              |          |\n| multigraph      | Whether to allow multi-edges                                                                                                               | boolean                                             | true              |          |\n| nodeSize        | G6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |          |\n| edgeMinLen      | Minimum number of ranks crossed by an edge                                                                                                 | number \\| (edge) => number                          | 1                 |          |\n| edgeWeight      | Edge weight, used to affect optimization priority                                                                                          | number \\| (edge) => number                          |                   |          |\n| edgeLabelSize   | Edge label size, used to reserve layout space                                                                                              | number[] \\| (edge) => number[]                      |                   |          |\n| edgeLabelPos    | Edge label position                                                                                                                        | string \\| (edge) => string                          |                   |          |\n| edgeLabelOffset | Offset between the label and the edge                                                                                                      | number \\| (edge) => number                          |                   |          |\n\n> Note: `dagre` does not require configuring `controlPoints` separately. G6 automatically converts the polyline points returned by the layout into `style.controlPoints` on the edge.\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`, **Default**: `TB`\n\nLayout direction\n\n- `TB`: Top to Bottom;\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='Top to Bottom Layout'/>\n\n- `BT`: Bottom to Top;\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='Bottom to Top Layout'/>\n\n- `LR`: Left to Right;\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='Left to Right Layout'/>\n\n- `RL`: Right to Left.\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='Right to Left Layout'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`, **Default**: `UL`\n\nNode alignment\n\n- `UL`: Upper Left\n- `UR`: Upper Right\n- `DL`: Down Left\n- `DR`: Down Right\n\n### nodesep\n\n> number, **Default**: 50\n\nNode spacing (px). For `TB` or `BT`, it's the horizontal spacing; for `LR` or `RL`, it's the vertical spacing\n\n### ranksep\n\n> number, **Default**: 50\n\nRank spacing (px). For `TB` or `BT`, it's the vertical spacing between ranks; for `LR` or `RL`, it's the horizontal spacing between ranks\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`, **Default**: `network-simplex`\n\nAlgorithm for assigning ranks to nodes, supports three algorithms:\n\n- `longest-path`: Uses DFS to recursively find the longest path for each node. Simple and fast, but may result in many long edges.\n- `tight-tree`: An optimization algorithm to reduce the number of long edges. It first uses `longest-path` to compute initial ranks, then adjusts slack edges to build a feasible tree.\n- `network-simplex`: Based on [A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf), iteratively modifies node ranks to minimize slack edges.\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]`\n\n```js\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n## Applicable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, automatically handling direction and spacing between nodes.\n- **Dependency Graphs**: Display dependencies between packages or modules.\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks.\n\n## Related Documentation\n\n> The following documents can help you better understand Dagre layout\n\n- [Graph Layout Algorithms｜Detailed Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Interpretation of Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/DagreLayout.zh.md":"---\ntitle: Dagre 布局\norder: 9\n---\n\n## 概述\n\nDagre 是一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## 配置项\n\n> 更多配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性            | 描述                                                                                                                                            | 类型                                                | 默认值            | 必选 |\n| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ----------------- | ---- |\n| type            | 布局类型                                                                                                                                        | `dagre`                                             | -                 | ✓    |\n| rankdir         | 布局方向，可选值                                                                                                                                | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |      |\n| align           | 节点对齐方式，可选值                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |      |\n| nodesep         | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                              | number                                              | 50                |      |\n| ranksep         | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                            | number                                              | 100               |      |\n| ranker          | 为每个节点分配等级的算法，共支持三种算法，分别是：`longest-path`、`tight-tree`、`network-simplex`                                               | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |      |\n| directed        | 是否按有向图处理                                                                                                                                | boolean                                             | true              |      |\n| compound        | 是否支持嵌套结构                                                                                                                                | boolean                                             | true              |      |\n| multigraph      | 是否允许多重边                                                                                                                                  | boolean                                             | true              |      |\n| nodeSize        | G6 自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个 number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |      |\n| edgeMinLen      | 边跨越的最小层数                                                                                                                                | number \\| (edge) => number                          | 1                 |      |\n| edgeWeight      | 边权重，用于影响优化优先级                                                                                                                      | number \\| (edge) => number                          |                   |      |\n| edgeLabelSize   | 边标签尺寸，用于预留空间                                                                                                                        | number[] \\| (edge) => number[]                      |                   |      |\n| edgeLabelPos    | 边标签位置                                                                                                                                      | string \\| (edge) => string                          |                   |      |\n| edgeLabelOffset | 标签与边的偏移                                                                                                                                  | number \\| (edge) => number                          |                   |      |\n\n> 补充：`dagre` 不需要单独配置 `controlPoints`，G6 会把布局输出的折线点自动转换为边的 `style.controlPoints`。\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`， **Default**: `TB`\n\n布局方向\n\n- `TB`：从上到下；\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='：从上到下布局'/>\n\n- `BT`：从下到上；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='从下到上布局'/>\n\n- `LR`：从左到右；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='从左到右布局'/>\n\n- `RL`：从右到左。\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='水平布局'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`， **Default**: `UL`\n\n节点对齐方式\n\n- `UL`：左上对齐\n- `UR`：右上对齐\n- `DL`：左下对齐\n- `DR`：右下对齐\n\n### nodesep\n\n> number， **Default**: 50\n\n节点间距（px）。在rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距\n\n### ranksep\n\n> number， **Default**: 50\n\n层间距（px）。在rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`， **Default**: `network-simplex`\n\n为每个节点分配层级的算法，共支持三种算法，分别是：\n\n- `longest-path`： 最长路径算法，使用DFS深度优先搜索，递归查找每个节点的最长路径。优点是计算简单速度快，但会导致长边过多；\n- `tight-tree`： 紧凑树算法，一种优化算法，目的是减少长边的数量。先用最长路径算法`longest-path`计算出初始层级，然后调整松弛边的长度，从而构建可行树。\n- `network-simplex`： 网络单形法，参考算法[A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf)，核心思想是迭代修改节点的层级，缩小松弛边。\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]`\n\n```js\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n### controlPoints\n\n> boolean， **Default**: false\n\n是否保留边的控制点。\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","packages/site/docs/manual/layout/DendrogramLayout.en.md":"---\ntitle: Dendrogram Layout\norder: 10\n---\n\n## Overview\n\nThe dendrogram layout is suitable for visualizing hierarchical clustering data. Its feature is that all child nodes are laid out on the same level, node size is not considered, and each node is treated as 1px.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='Dendrogram Layout Example'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"Dendrogram Layout Options Illustration\" />\n\n| Property  | Description                                            | Type                                       | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------------------------------ | ------- | -------- |\n| type      | Layout type                                            | `dendrogram`                               | -       | ✓        |\n| direction | Layout direction, [options](#direction)                | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`    |          |\n| nodeSep   | Node spacing, distance between nodes on the same level | number                                     | 20      |          |\n| rankSep   | Rank spacing, distance between different levels        | number                                     | 200     |          |\n| radial    | Whether to enable radial layout, [see below](#radial)  | boolean                                    | false   |          |\n\n### direction\n\nTree layout direction options:\n\n- `TB`: Root at the top, layout downward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB direction'/>\n\n- `BT`: Root at the bottom, layout upward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT direction'/>\n\n- `LR`: Root at the left, layout to the right\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR direction'/>\n\n- `RL`: Root at the right, layout to the left\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL direction'/>\n\n- `H`: Root in the middle, horizontal symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H direction'/>\n\n- `V`: Root in the middle, vertical symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V direction'/>\n\n### radial\n\nWhether to enable radial layout mode. When enabled, nodes are distributed radially around the root node.\n\nIf `radial` is set to `true`, it is recommended to set `direction` to `'LR'` or `'RL'` for best results.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='Radial Layout'/>\n","packages/site/docs/manual/layout/DendrogramLayout.zh.md":"---\ntitle: 生态树 Dendrogram\norder: 10\n---\n\n## 概述\n\n生态树布局适用于层次聚类数据的可视化，其特点是所有子节点布局在同一层级，不考虑节点大小，每个节点被当成 1px 处理。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='生态树布局示例'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"生态树配置项图解\" />\n\n| 属性      | 描述                                           | 类型                                       | 默认值 | 必选 |\n| --------- | ---------------------------------------------- | ------------------------------------------ | ------ | ---- |\n| type      | 布局类型                                       | `dendrogram`                               | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                 | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`   |      |\n| nodeSep   | 节点间距，即同一层级节点之间的距离，单位为像素 | number                                     | 20     |      |\n| rankSep   | 层级间距，即不同层级之间的距离，单位为像素     | number                                     | 200    |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)            | boolean                                    | false  |      |\n\n### direction\n\n树布局的方向，有以下选项：\n\n- `TB`：根节点在上，往下布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB方向'/>\n\n- `BT`：根节点在下，往上布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT方向'/>\n\n- `LR`：根节点在左，往右布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR方向'/>\n\n- `RL`：根节点在右，往左布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL方向'/>\n\n- `H`：根节点在中间，水平对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H方向'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V方向'/>\n\n### radial\n\n是否启用辐射状布局模式。启用后，节点将以根节点为中心呈辐射状分布。\n\n若 `radial` 设置为 `true`，建议将 `direction` 设置为 `'LR'` 或 `'RL'` 以获得最佳效果。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='辐射状布局'/>\n","packages/site/docs/manual/layout/Fishbone.en.md":"---\ntitle: Fishbone Layout\norder: 11\n---\n\n## Overview\n\nFishbone layout is a graphical layout specifically designed for representing hierarchical data. By simulating the shape of a fishbone, it arranges data nodes according to their hierarchy, making the hierarchical relationships of the data clearer and more intuitive. Fishbone layout is especially suitable for datasets that need to show causality, hierarchy, or classification information.\n\n## Use Cases\n\n- Displaying hierarchical data, such as organizational structures or classification systems\n- Showing problem analysis processes, such as fault analysis or quality analysis\n- Displaying decision processes, such as decision trees or factor analysis\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## Options\n\n| Property               | Description                                                                                      | Type                                                                                                                                   | Default  | Required |\n| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- |\n| type                   | Layout type                                                                                      | `fishbone`                                                                                                                             | -        | ✓        |\n| direction              | Layout direction, `RL` (right to left, head on right), `LR` (left to right, head on left)        | `RL` \\| `LR`                                                                                                                           | `RL`     |          |\n| hGap                   | Horizontal gap                                                                                   | number                                                                                                                                 | -        |          |\n| vGap                   | Vertical gap                                                                                     | number                                                                                                                                 | -        |          |\n| getRibSep              | Function to get rib gap                                                                          | (node: NodeData) => number                                                                                                             | () => 60 |          |\n| width                  | Layout width                                                                                     | number                                                                                                                                 | -        |          |\n| height                 | Layout height                                                                                    | number                                                                                                                                 | -        |          |\n| nodeSize               | Node size                                                                                        | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (effective when preLayout is true)                 | boolean                                                                                                                                | -        |          |\n| nodeFilter             | Nodes to participate in this layout                                                              | (node: NodeData) => boolean                                                                                                            | -        |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements (not suitable for pipeline layout) | boolean                                                                                                                                | -        |          |\n\n## Code Example\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Real Case\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone Layout](/en/examples/layout/fishbone/#basic)\n","packages/site/docs/manual/layout/Fishbone.zh.md":"---\ntitle: 鱼骨布局 Fishbone\norder: 11\n---\n\n## 概述\n\n鱼骨布局是一种专门用于表示层次结构数据的图形布局方式。它通过模拟鱼骨的形状，将数据节点按照层次结构排列，使得数据的层次关系更加清晰直观。鱼骨布局特别适用于需要展示因果关系、层次结构或分类信息的数据集。\n\n## 使用场景\n\n- 需要展示层次结构数据，如组织结构、分类体系\n- 需要展示问题分析过程，如故障分析、质量分析\n- 需要展示决策过程，如决策树、影响因素分析\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## 配置项\n\n| 属性                   | 描述                                                       | 类型                                                                                                                                   | 默认值   | 必选 |\n| ---------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type                   | 布局类型                                                   | `fishbone`                                                                                                                             | -        | ✓    |\n| direction              | 排布方向，`RL` 从右到左，鱼头在右；`LR` 从左到右，鱼头在左 | `RL` \\| `LR`                                                                                                                           | `RL`     |      |\n| hGap                   | 水平间距                                                   | number                                                                                                                                 | -        |      |\n| vGap                   | 垂直间距                                                   | number                                                                                                                                 | -        |      |\n| getRibSep              | 获取鱼骨间距                                               | (node: NodeData) => number                                                                                                             | () => 60 |      |\n| width                  | 布局宽度                                                   | number                                                                                                                                 | -        |      |\n| height                 | 布局高度                                                   | number                                                                                                                                 | -        |      |\n| nodeSize               | 节点大小                                                   | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局，当 preLayout 为 true 时生效        | boolean                                                                                                                                | -        |      |\n| nodeFilter             | 参与该布局的节点                                           | (node: NodeData) => boolean                                                                                                            | -        |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局，不适用于流水线布局     | boolean                                                                                                                                | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone布局](/examples/layout/fishbone/#basic)\n","packages/site/docs/manual/layout/ForceAtlas2Layout.en.md":"---\ntitle: ForceAtlas2 Force-directed Layout\norder: 12\n---\n\n## Overview\n\nForceAtlas2 is a force-directed layout algorithm that optimizes node positions by simulating forces in a physical system. This layout is especially suitable for visualizing large-scale network data, effectively revealing relationships and cluster structures among nodes.\n\n## Use Cases\n\n- Social network analysis: Display user relationship networks, with node degree reflecting user influence\n- Knowledge graphs: Show associations between concepts, discover knowledge domains through clustering\n- System architecture diagrams: Show dependencies between system components, highlight core components via hub mode\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## Options\n\n| Property       | Description                                                                                                                                                                   | Type                                | Default  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | -------- |\n| type           | Layout type, must be `force-atlas2`                                                                                                                                           | `force-atlas2`                      | -        | ✓        |\n| maxIteration   | Maximum number of iterations                                                                                                                                                  | number                              | 500      |          |\n| minMovement    | Convergence threshold                                                                                                                                                         | number                              | 0.4      |          |\n| barnesHut      | Whether to enable quadtree acceleration. When enabled, improves performance for large graphs but may affect layout quality. By default, enabled if node count > 250.          | boolean                             | -        |          |\n| dissuadeHubs   | Whether to enable hub mode. If true, nodes with higher in-degree are more likely to be placed at the center than those with high out-degree                                   | boolean                             | false    |          |\n| height         | Layout height. Defaults to container height                                                                                                                                   | number                              | -        |          |\n| kg             | Gravity coefficient. The larger the value, the more concentrated the layout is at the center                                                                                  | number                              | 1        |          |\n| kr             | Repulsion coefficient. Adjusts the compactness of the layout. The larger the value, the looser the layout                                                                     | number                              | 5        |          |\n| ks             | Controls the speed of node movement during iteration                                                                                                                          | number                              | 0.1      |          |\n| ksmax          | Maximum node movement speed during iteration                                                                                                                                  | number                              | 10       |          |\n| mode           | Clustering mode. In `linlog` mode, clusters are more compact                                                                                                                  | `normal` \\| `linlog`                | `normal` |          |\n| nodeSize       | Node size (diameter). Used for repulsion calculation when `preventOverlap` is enabled. If not set, uses `data.size` in node data                                              | Size \\| ((node?: Node) => Size)     | -        |          |\n| nodeSpacing    | Spacing between nodes                                                                                                                                                         | number \\| ((node?: Node) => number) | -        |          |\n| onTick         | Callback for each iteration                                                                                                                                                   | (data: LayoutMapping) => void       | -        |          |\n| preventOverlap | Whether to prevent node overlap. When enabled, layout considers node size to avoid overlap. Node size is specified by `nodeSize` or `data.size` in node data                  | boolean                             | false    |          |\n| prune          | Whether to enable auto-pruning. By default, enabled if node count > 100. Pruning speeds up convergence but may reduce layout quality. Set to false to disable auto-activation | boolean                             | -        |          |\n| tao            | Tolerance for stopping oscillation when layout is near convergence                                                                                                            | number                              | 0.1      |          |\n| width          | Layout width. Defaults to container width                                                                                                                                     | number                              | -        |          |\n| center         | Layout center, format [x, y]. Each node is attracted to this point, gravity controlled by `kg`. If not set, uses canvas center                                                | [number, number]                    | -        |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## Real Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2 Layout](/en/examples/layout/force-directed/#atlas2)\n","packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md":"---\ntitle: ForceAtlas2 力导向布局\norder: 12\n---\n\n## 概述\n\nForceAtlas2 是一种基于力导向的布局算法，它通过模拟物理系统中的力来优化节点位置。该布局特别适用于大规模网络数据的可视化，能够有效地展示节点之间的关系和聚类结构。\n\n## 使用场景\n\n- 社交网络分析：展示用户之间的关系网络，通过节点度数反映用户影响力\n- 知识图谱：展示概念之间的关联关系，通过聚类效果发现知识领域\n- 系统架构图：展示系统组件之间的依赖关系，通过 hub 模式突出核心组件\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                 | 类型                                | 默认值   | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | ---- |\n| type           | 布局类型，必须为 `force-atlas2`                                                                                                                                      | `force-atlas2`                      | -        | ✓    |\n| maxIteration   | 最大迭代次数                                                                                                                                                         | number                              | 500      |      |\n| minMovement    | 收敛阈值                                                                                                                                                             | number                              | 0.4      |      |\n| barnesHut      | 是否开启四叉树加速，开启后可以提升大规模图的布局性能，但可能会影响布局质量。默认情况下为 undefined，当节点数量大于 250 时它将会被激活。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| dissuadeHubs   | 是否开启 hub 模式。若为 true，相比与出度大的节点，入度大的节点将会有更高的优先级被放置在中心位置                                                                     | boolean                             | false    |      |\n| height         | 布局高度，默认使用容器高度                                                                                                                                           | number                              | -        |      |\n| kg             | 重力系数，`kg` 越大，布局越聚集在中心                                                                                                                                | number                              | 1        |      |\n| kr             | 斥力系数，可用于调整布局的紧凑程度。kr 越大，布局越松散                                                                                                              | number                              | 5        |      |\n| ks             | 控制迭代过程中，节点移动的速度                                                                                                                                       | number                              | 0.1      |      |\n| ksmax          | 迭代过程中，最大的节点移动的速度上限                                                                                                                                 | number                              | 10       |      |\n| mode           | 聚类模式，`linlog` 模式下，聚类将更加紧凑                                                                                                                            | `normal` \\| `linlog`                | `normal` |      |\n| nodeSize       | 节点大小（直径）。当开启 `preventOverlap` 时，用于计算节点之间的斥力。如果不设置，则使用节点数据中的 size 属性                                                       | Size \\| ((node?: Node) => Size)     | -        |      |\n| nodeSpacing    | 节点间距                                                                                                                                                             | number \\| ((node?: Node) => number) | -        |      |\n| onTick         | 每一次迭代的回调函数                                                                                                                                                 | (data: LayoutMapping) => void       | -        |      |\n| preventOverlap | 是否防止节点重叠。开启后，布局会考虑节点大小，避免节点重叠                                                                                                           | boolean                             | false    |      |\n| prune          | 是否开启自动剪枝模式。默认情况下为 undefined，当节点数量大于 100 时它将会被激活。注意，剪枝能够提高收敛速度，但可能会降低图的布局质量。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| tao            | 迭代接近收敛时停止震荡的容忍度                                                                                                                                       | number                              | 0.1      |      |\n| width          | 布局宽度，默认使用容器宽度                                                                                                                                           | number                              | -        |      |\n| center         | 布局中心点，用于指定重力的中心，格式为 [x, y]。每个节点都会受到一个指向该中心点的重力，重力大小由 `kg` 参数控制。如果不设置，则使用画布中心点                        | [number, number]                    | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2布局](/examples/layout/force-directed/#atlas2)\n","packages/site/docs/manual/layout/ForceLayout.en.md":"---\ntitle: Force-directed Layout\norder: 13\n---\n\n## Overview\n\nForce-directed layout is a graph layout algorithm based on physical simulation that determines node positions by simulating attraction and repulsion forces between nodes. This layout is particularly suitable for displaying complex relationship networks, such as social networks and knowledge graphs.\n\nThe force-directed layout automatically calculates and adjusts node positions to maintain appropriate distances between connected nodes while minimizing edge crossings. During the layout process, it simulates a physical system where nodes repel each other like charged particles, and edges connect nodes like springs.\n\nKey features of force-directed layout include:\n\n1. **Automatic Arrangement**: No need to manually set node positions, the system automatically finds suitable positions\n2. **Real-time Adjustment**: When you drag a node, other nodes will adjust their positions in real-time\n3. **Flexible Configuration**:\n   - Can adjust attraction and repulsion forces between nodes\n   - Can set edge lengths\n   - Can prevent node overlap\n4. **Animation Effects**: Smooth animations during node movement make changes more natural\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='Force-directed Layout Example'/>\n\n## Core Concepts\n\n### Basic Principles of Force-directed Layout\n\nForce-directed layout is a graph layout algorithm based on physical simulation that models nodes and edges as a physical system:\n\n- Nodes are treated as physical particles\n- Edges are treated as springs\n- The entire system reaches its lowest energy state through physical simulation\n\n### Detailed Core Forces\n\n#### Node Repulsion\n\n- **Physical Model**: Coulomb's Law\n- **Function**: Prevents node overlap and ensures more uniform node distribution, where `factor` and `coulombDisScale` control the overall strength and range of repulsion.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='Repulsion Force'/>\n\n  - k: Repulsion coefficient (`factor` / `coulombDisScale²`)\n  - q1,q2: Node strength (`nodeStrength`)\n  - r: Distance between nodes\n\n#### Edge Attraction\n\n- **Physical Model**: Hooke's Law\n- **Function**: Simulates edge tension, moving nodes along edge directions, where `edgeStrength` and `linkDistance` control edge \"stiffness\" and length.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='Edge Attraction'/>\n\n  - ka: Edge attraction strength (`edgeStrength`)\n  - L: Edge length (`linkDistance`)\n  - r: Actual edge length\n\n#### Centripetal Force\n\n- **Physical Model**: Newton's Universal Law of Gravitation\n- **Function**: Attracts nodes toward the canvas center or cluster centers, where `gravity` and `center` control gravity strength and center point position\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Centripetal Force'/>\n\n  - G: Gravitational constant (`gravity`)\n  - xc: Center point coordinates (`center`)\n  - mass: Node mass (`nodeSize`)\n\n#### Interaction of Three Forces\n\n- **Physical Model**: Force interactions, generating acceleration\n- **Function**: Repulsion, edge attraction, and centripetal force work together, affecting node movement through acceleration superposition, ultimately reaching the lowest energy state.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Force Interactions'/>\n\n### Physical System\n\n#### Node Velocity Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='Node Velocity Formula'/>\n\n  - v: Velocity\n  - a: Acceleration\n  - dt: Time step (`interval`)\n  - damping: Damping coefficient (`damping`)\n\n- **Function**:\n  1. Controls node movement stability\n  2. Damping coefficient prevents system oscillation\n  3. Time step affects displacement per iteration\n\n#### Node Position Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='Node Position Formula'/>\n\n  - x: Node position\n  - v: Node velocity\n  - dt: Time step (`interval`)\n\n- **Function**:\n  1. Updates node position based on velocity\n  2. Ensures motion continuity\n  3. Prevents node overlap through `preventOverlap`\n\n#### Cluster Center Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='Cluster Center Calculation'/>\n\n  - n: Number of nodes in cluster\n  - (xi​,yi​): Position of each node\n\n- **Function**:\n  1. Calculates cluster center\n  2. Centripetal force pulls nodes toward their cluster center\n  3. Cluster center can change dynamically\n\n#### Cluster Strength Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='Cluster Strength Calculation'/>\n\n  - s: Cluster strength (`clusterNodeStrength`)\n  - xc​: Cluster center\n\n- **Function**:\n  1. Controls cluster compactness\n  2. Higher cluster strength means tighter clusters\n  3. Can be dynamically adjusted based on node properties\n\n#### Mass Effect on Forces\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='Mass Effect on Forces'/>\n\n  - a: Acceleration\n  - F: Force (repulsion, edge attraction, centripetal force)\n  - mass: Node mass\n\n- **Function**:\n  1. Nodes with larger mass move less\n  2. Nodes with smaller mass move more\n  3. Mass calculation can be customized through `getMass`\n\n#### Energy Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='Energy Calculation'/>\n\n  - m: Node mass\n  - v: Node velocity\n\n- **Function**:\n  1. Monitors layout convergence\n  2. System stabilizes when energy approaches zero\n\n#### System Convergence Condition\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='System Convergence Condition'/>\n\n- **Function**:\n  1. Controls iteration count\n  2. Stops when movement is below threshold\n  3. Can choose between mean, maximum, or minimum through `distanceThresholdMode`\n\n### Force Interaction Diagram\n\n```mermaid\ngraph TD\n    A[Input] --> B[Initialize Parameters];\n    B --> C[Build Layout Calculation];\n    C --> D[Iterative Calculation];\n    D --> E{Converged?};\n    E -->|Yes| F[Output Layout];\n    E -->|No| G[Calculate Repulsion];\n    G --> H[Calculate Edge Attraction];\n    H --> I[Calculate Centripetal Force];\n    I --> J[Update Velocity];\n    J --> K[Update Position];\n    K --> D;\n```\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/BOu7Rbuz4MoAAAAAQjAAAAgADpdRAQFr/original' alt='Force Simulation Diagram'/>\n\n## Configuration Options\n\nBased on the physical characteristics of force-directed layout, the following configuration options are available:\n\n### Basic Configuration\n\n| Property              | Description                                                                                                                                                                                                                                        | Default Value | Required |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type                  | Layout type                                                                                                                                                                                                                                        | `force`       | ✓        |\n| dimensions            | Layout dimensions, 2 for 2D layout, 3 for 3D layout                                                                                                                                                                                                | 2             |          |\n| width                 | Layout width                                                                                                                                                                                                                                       | Canvas width  |          |\n| height                | Layout height                                                                                                                                                                                                                                      | Canvas height |          |\n| center                | Layout center point                                                                                                                                                                                                                                | Graph center  |          |\n| maxIteration          | Maximum iteration count, if 0 will auto-adjust                                                                                                                                                                                                     | 0             |          |\n| minMovement           | Stop iteration when average movement distance is less than 0.4                                                                                                                                                                                     | 0.4           |          |\n| distanceThresholdMode | Movement distance calculation mode: mean: stop when average movement distance is less than `minMovement`; max: stop when maximum movement distance is less than `minMovement`; min: stop when minimum movement distance is less than `minMovement` | `mean`        |          |\n| maxDistance           | Maximum distance                                                                                                                                                                                                                                   |               |          |\n\n### Force-related Configuration\n\n#### Repulsion Configuration\n\n| Property        | Description                                                                                         | Default Value | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| nodeStrength    | Node force, positive values represent attraction between nodes, negative values represent repulsion | 1000          |          |\n| factor          | Repulsion coefficient, larger values mean stronger repulsion                                        | 1             |          |\n| coulombDisScale | Coulomb coefficient, a factor for repulsion, larger values mean stronger repulsion between nodes    | 0.005         |          |\n\n#### Edge Attraction Configuration\n\n| Property     | Description                                                                                                    | Default Value | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| edgeStrength | Edge force (attraction) strength, fixed force or callback function to dynamically return different edge forces | 500           |          |\n| linkDistance | Edge length, fixed length or callback function to dynamically return different edge lengths                    | 200           |          |\n\n#### Centripetal Force Configuration\n\n| Property           | Description                                                                                                                                                                                                                                                          | Default Value | Required |\n| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| gravity            | Center force strength, the force attracting all nodes to the center. Larger values mean more compact layout                                                                                                                                                          | 10            |          |\n| centripetalOptions | Centripetal force configuration, including center and strength for leaf nodes, isolated nodes, and other nodes. leaf: leaf node centripetal force; single: single node centripetal force; others: other node centripetal force; center: custom center point function | [0, 0]        |          |\n\n#### Clustering Configuration\n\n| Property            | Description                                                                                                                                                                                                                                                                                                                                                   | Default Value | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| clustering          | Whether to cluster all nodes. If true, will use the field specified by nodeClusterBy in node data for clustering. centripetalOptions.single, centripetalOptions.leaf, and centripetalOptions.others will use the value returned by getClusterNodeStrength; leaf and centripetalOptions.center will use the average center of all nodes in the current cluster | `false`       |          |\n| nodeClusterBy       | Specifies the field name in node data for clustering. Takes effect when clustering is true. Automatically generates centripetalOptions, can be used with clusterNodeStrength                                                                                                                                                                                  |               |          |\n| clusterNodeStrength | Used with clustering and nodeClusterBy to specify the strength of the cluster centripetal force                                                                                                                                                                                                                                                               |               |          |\n| leafCluster         | Whether to cluster leaf nodes. If true, centripetalOptions.single will be 100; centripetalOptions.leaf will use the value returned by getClusterNodeStrength; getClusterNodeStrength.center will return the average center of all leaf nodes                                                                                                                  | false         |          |\n\n#### Performance and Optimization Configuration\n\n| Property        | Description                                                                                                                                                                                                                                                               | Default Value | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| damping         | Damping coefficient, range [0, 1]. Larger values mean slower speed decrease                                                                                                                                                                                               | 0.9           |          |\n| maxSpeed        | Maximum movement length per iteration                                                                                                                                                                                                                                     | 200           |          |\n| interval        | Controls the movement speed of each node per iteration                                                                                                                                                                                                                    | 0.02          |          |\n| preventOverlap  | Whether to prevent overlap. Must be used with nodeSize or data.size in node data. Only when data.size is set in the data or nodeSize is configured in the layout with the same value as the node size in the graph, collision detection for node overlap can be performed | true          |          |\n| nodeSize        | Node size (diameter). Used for collision detection to prevent node overlap. Fixed size or callback function to dynamically return node size                                                                                                                               |               |          |\n| nodeSpacing     | Takes effect when preventOverlap is true. Minimum spacing between node edges to prevent overlap. Can be a callback to set different spacing for different nodes                                                                                                           |               |          |\n| collideStrength | Strength of anti-overlap force, range [0, 1]                                                                                                                                                                                                                              | 1             |          |\n\n#### Other Configuration\n\n| Property  | Description                                                                                                                                                                              | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| getMass   | Callback for the mass of each node. The parameter is the node's internal data, and the return value is the mass                                                                          |               |          |\n| getCenter | Callback for the x, y, and strength of the centripetal force for each node. If not specified, no extra centripetal force is applied                                                      |               |          |\n| onTick    | Callback for each iteration                                                                                                                                                              |               |          |\n| monitor   | Callback for monitoring each iteration. energy indicates the convergence energy of the layout. May incur extra computation if configured; if not configured, no computation is performed |               |          |\n\n## Code Examples\n\n### Basic Usage\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Layout width\n    width: 800,\n    // Layout height\n    height: 600,\n  },\n});\n```\n\n### Preventing Node Overlap\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n  },\n});\n```\n\n### Force-directed Layout\n\nThis example demonstrates how to create a basic force-directed graph using force-directed layout.\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Centripetal force\n    gravity: 0.9,\n    // Iteration count\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\nKey configuration explanations:\n\n- `preventOverlap`: Enable node overlap detection\n- `nodeSize`: Set node size\n- `gravity`: Set node centripetal force\n- `iterations`: Set layout calculation precision\n\nYou can also refer to [View Examples](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) for more usage examples.\n","packages/site/docs/manual/layout/ForceLayout.zh.md":"---\ntitle: Force 力导向布局\norder: 13\n---\n\n## 概述\n\n力导向布局是一种基于物理模拟的图布局算法，它通过模拟节点间的引力和斥力来确定节点的位置。这种布局方式特别适合展示复杂的关系网络，如社交网络、知识图谱等。\n\n力导向布局会自动计算并调整节点位置，使得相连的节点保持适当的距离，同时尽量减少边的交叉。布局过程中会模拟物理系统，节点会像带电粒子一样相互排斥，边则像弹簧一样连接节点。\n\n力导向布局的主要特点包括：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的长度\n   - 可以防止节点重叠\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='力导向布局示例'/>\n\n## 核心概念\n\n### Force 力导向布局基本原理\n\n力导向布局是一种基于物理模拟的图布局算法，它将图中的节点和边模拟为物理系统：\n\n- 节点被视为物理粒子\n- 边被视为弹簧\n- 整个系统通过物理模拟达到能量最低状态\n\n### 核心力详解\n\n#### 斥力（Node Repulsion）\n\n- **物理模型**：库伦定律（Coulomb's Law）\n- **作用**：防止节点重叠，让节点分布更均匀，其中 `factor` 和 `coulombDisScale` 控制斥力的总体强度和范围。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='斥力'/>\n\n  - k: 斥力系数（`factor` / `coulombDisScale²`）\n  - q1,q2: 节点强度(`nodeStrength`)\n  - r: 节点间距离\n\n#### 边拉力（Edge Attraction）\n\n- **物理模型**：胡克定律（Hooke's Law）\n- **作用**：模拟边的拉力，使节点沿着边的方向移动，其中 `edgeStrength` 和 `linkDistance` 控制边的“硬度”和长度。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='边拉力'/>\n\n  - ka: 边拉力强度（`edgeStrength`）\n  - L: 边的长度（`linkDistance`）\n  - r: 实际边长度\n\n#### 向心力（Gravity）\n\n- **物理模型**：牛顿万有引力定律（Newton's Universal Law of Gravitational）\n- **作用**：使节点向画布中心或者聚类中心聚集，其中 `gravity` 和 `center` 控制重力强度和中心点位置\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='向心力'/>\n\n  - G: 万有引力常数（`gravity`）\n  - xc: 中心点坐标（`center`）\n  - mass: 节点质量（`nodeSize`）\n\n#### 三种力的相互作用\n\n- **物理模型**：力的相互作用，产生加速度\n- **作用**：斥力、边拉力、向心力共同作用，通过加速度叠加影响节点运动，最终达到能量最低状态。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='力的相互作用'/>\n\n### 物理系统\n\n#### 节点运动速度公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='节点运动速度公式'/>\n\n  - v: 速度\n  - a: 加速度\n  - dt: 时间步长（`interval`）\n  - damping: 阻尼系数（`damping`）\n\n- **作用**：\n  1. 控制节点移动的稳定性\n  2. 阻尼系数防止系统震荡\n  3. 时间步长影响每次迭代的位移\n\n#### 节点位置公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='节点位置公式'/>\n\n  - x: 节点位置\n  - v: 节点速度\n  - dt: 时间步长（`interval`）\n\n- **作用**：\n  1. 根据速度更新节点位置\n  2. 确保运动连续性\n  3. 通过 `preventOverlap` 防止节点重叠\n\n#### 聚类中心计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='聚类中心计算'/>\n\n  - n: 聚类内节点数量\n  - (xi​,yi​): 每个节点的位置\n\n- **作用**：\n  1. 计算聚类中心\n  2. 向心力将节点拉向所属聚类中心\n  3. 聚类中心可动态变化\n\n#### 聚类强度计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='聚类强度计算'/>\n\n  - s: 聚类强度（`clusterNodeStrength`）\n  - xc​: 聚类中心\n\n- **作用**：\n  1. 控制聚类的紧密程度\n  2. 聚类强度越大，聚类越紧凑\n  3. 可根据节点属性动态调整\n\n#### 质量对力的影响\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='质量对力的影响'/>\n\n  - a: 加速度\n  - F: 力（斥力、边拉力、向心力）\n  - mass: 节点质量\n\n- **作用**：\n  1. 质量大的节点移动较小\n  2. 质量小的节点移动较大\n  3. 通过 `getMass` 可自定义质量计算\n\n#### 能量计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='能量计算'/>\n\n  - m: 节点质量\n  - v: 节点速度\n\n- **作用**：\n  1. 监控布局收敛情况\n  2. 能量趋近于零时系统趋于稳定\n\n#### 系统收敛条件\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='系统收敛条件'/>\n\n- **作用**：\n  1. 控制迭代次数\n  2. 移动量小于阈值时停止\n  3. 通过 `distanceThresholdMode` 可选择平均值、最大值或最小值\n\n### 力相互作用图\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2lI1RruANXoAAAAAAAAAAAAADpdRAQFr/original' alt='力作用模拟图'/>\n\n## 配置项\n\n根据上述力导向布局的物理特性，有以下配置项：\n\n### 基础配置\n\n| 属性                  | 描述                                                                                                                                                         | 默认值   | 必选 |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ---- |\n| type                  | 布局类型                                                                                                                                                     | `force`  | ✓    |\n| dimensions            | 布局维度，2表示2D布局，3表示3D布局                                                                                                                           | 2        |      |\n| width                 | 布局宽度                                                                                                                                                     | 画布宽度 |      |\n| height                | 布局高度                                                                                                                                                     | 画布高度 |      |\n| center                | 布局的中心点                                                                                                                                                 | 图中心   |      |\n| maxIteration          | 最大迭代次数，若为 0 则将自动调整                                                                                                                            | 0        |      |\n| minMovement           | 当平均移动距离小于0.4时停止迭代                                                                                                                              | 0.4      |      |\n| distanceThresholdMode | 移动距离的计算模式：mean: 平均移动距离小于 `minMovement` 时停止迭代；max: 最大移动距离小于时 `minMovement` 时停止迭代；min: 最小移动距离小于时 `minMovement` | `mean`   |      |\n| maxDistance           | 最大距离                                                                                                                                                     |          |      |\n\n### 力相关配置\n\n#### 斥力配置\n\n| 属性            | 描述                                                               | 默认值 | 必选 |\n| --------------- | ------------------------------------------------------------------ | ------ | ---- |\n| nodeStrength    | 节点作用力，正数代表节点之间的引力作用，负数代表节点之间的斥力作用 | 1000   |      |\n| factor          | 斥力系数，数值越大，斥力越大                                       | 1      |      |\n| coulombDisScale | 库伦系数，斥力的一个系数，数字越大，节点之间的斥力越大             | 0.005  |      |\n\n#### 边拉力配置\n\n| 属性         | 描述                                                               | 默认值 | 必选 |\n| ------------ | ------------------------------------------------------------------ | ------ | ---- |\n| edgeStrength | 边的作用力（引力）大小，固定作用力或回调函数动态返回不同边的作用力 | 500    |      |\n| linkDistance | 边的长度，固定长度或回调函数动态返回不同边的长度                   | 200    |      |\n\n#### 向心力配置\n\n| 属性               | 描述                                                                                                                                                         | 默认值 | 必选 |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ---- |\n| gravity            | 向中心力大小，指所有节点被吸引到 center 的力。数字越大，布局越紧凑                                                                                           | 10     |      |\n| centripetalOptions | 向心力配置，包括叶子节点、离散点、其他节点的向心中心及向心力大小。leaf: 叶子节点向心力；single: 单点向心力；others: 其他节点向心力；center: 自定义中心点函数 | [0, 0] |      |\n\n#### 聚类配置\n\n| 属性                | 描述                                                                                                                                                                                                                                                                                                      | 默认值  | 必选 |\n| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---- |\n| clustering          | 是否需要全部节点聚类，若为 `true`，将使用 `nodeClusterBy` 配置的节点数据中的字段作为聚类依据。 `centripetalOptions.single`、`centripetalOptions.leaf`、`centripetalOptions.others` 将使用 `getClusterNodeStrength` 返回值；`leaf`、`centripetalOptions.center` 将使用当前节点所属聚类中所有节点的平均中心 | `false` |      |\n| nodeClusterBy       | 指定节点数据中的字段名称作为节点聚类的依据，`clustering` 为 true 时生效，自动生成 `centripetalOptions`，可配合 `clusterNodeStrength` 使用                                                                                                                                                                 |         |      |\n| clusterNodeStrength | 配合 `clustering` 和 `nodeClusterBy` 使用，指定聚类向心力的大小                                                                                                                                                                                                                                           |         |      |\n| leafCluster         | 是否需要叶子节点聚类，若为 `true`，则 `centripetalOptions.single` 将为 100；`centripetalOptions.leaf` 将使用 `getClusterNodeStrength` 返回值；`getClusterNodeStrength.center` 将为叶子节点返回当前所有叶子节点的平均中心                                                                                  | false   |      |\n\n#### 性能与优化配置\n\n| 属性            | 描述                                                                                                                                                                                           | 默认值 | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| damping         | 阻尼系数，取值范围 [0, 1]。数字越大，速度降低得越慢                                                                                                                                            | 0.9    |      |\n| maxSpeed        | 一次迭代的最大移动长度                                                                                                                                                                         | 200    |      |\n| interval        | 控制每个迭代节点的移动速度                                                                                                                                                                     | 0.02   |      |\n| preventOverlap  | 是否防止重叠，必须配合下面属性 `nodeSize` 或节点数据中的 `data.size` 属性，只有在数据中设置了 `data.size` 或在该布局中配置了与当前图节点大小相同的 `nodeSize` 值，才能够进行节点重叠的碰撞检测 | true   |      |\n| nodeSize        | 节点大小（直径）。用于防止节点重叠时的碰撞检测，固定大小或者回调函数动态返回节点大小                                                                                                           |        |      |\n| nodeSpacing     | `preventOverlap` 为 `true` 时生效, 防止重叠时节点边缘间距的最小值。可以是回调函数, 为不同节点设置不同的最小间距                                                                                |        |      |\n| collideStrength | 防止重叠的力强度，范围 [0, 1]                                                                                                                                                                  | 1      |      |\n\n#### 其他配置\n\n| 属性      | 描述                                                                                                                                                                                                | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| getMass   | 获取节点质量的回调函数，入参为节点内部流转数据，用于计算节点质量大小                                                                                                                                |        |      |\n| getCenter | 每个节点中心力的 x、y、强度的回调函数，若不指定，则没有额外中心力                                                                                                                                   |        |      |\n| onTick    | 每一次迭代的回调函数                                                                                                                                                                                |        |      |\n| monitor   | 每个迭代的监控信息回调，energy 表示布局的收敛能量。若配置可能带来额外的计算能量性能消耗，不配置则不计算。入参为迭代监控信息 `{ energy: number; nodes: Node[]; edges: Edge[]; iterations: number; }` |        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 布局宽度\n    width: 800,\n    // 布局高度\n    height: 600,\n  },\n});\n```\n\n### 防止节点重叠\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n  },\n});\n```\n\n### 力导向布局\n\n该示例展示了如何使用力导向布局创建一个基础的力导向图。\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 向心力\n    gravity: 0.9,\n    // 迭代次数\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\n主要配置说明：\n\n- `preventOverlap`: 开启节点重叠检测\n- `nodeSize`: 设置节点大小\n- `gravity`: 设置节点向心力\n- `iterations`: 设置布局计算的精确程度\n\n还可以参考 [查看示例](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) 获取更多用法。\n","packages/site/docs/manual/layout/FruchtermanLayout.en.md":"---\ntitle: Fruchterman Force-directed Layout\norder: 14\n---\n\n## Overview\n\nThe Fruchterman layout is a force-directed layout based on the algorithm from [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf). By flexibly configuring parameters to simulate physical forces, the layout automatically reaches a stable equilibrium state with minimal energy. It supports both basic uniform distribution and cluster layouts. See more Fruchterman force-directed layout [examples](/en/examples#layout-fruchterman) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts).\n\n## Use Cases\n\n- Basic uniform distribution: Suitable for displaying network graphs with evenly distributed nodes and clear overall structure, such as network topology and knowledge graphs.\n- Cluster layout: Suitable for visualizing data with internal aggregation or grouping, such as community structure display and association group analysis.\n\n## Options\n\n| Property     | Description                                                                                                                                                                                        | Type                                                                                                       | Default          | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------- | -------- |\n| type         | Layout type                                                                                                                                                                                        | `'fruchterman'`                                                                                            | -                | ✓        |\n| height       | Layout height                                                                                                                                                                                      | `number`                                                                                                   | container height |          |\n| width        | Layout width                                                                                                                                                                                       | `number`                                                                                                   | container width  |          |\n| maxIteration | Maximum number of iterations                                                                                                                                                                       | `number`                                                                                                   | 500              |          |\n| minMovement  | Convergence threshold                                                                                                                                                                              | `number`                                                                                                   | 0.4              |          |\n| gravity      | Central force, i.e., the force attracting all nodes to the [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915). The larger the value, the more compact the layout | `number`                                                                                                   | 10               |          |\n| speed        | Node movement speed per iteration. Too high a speed may cause strong oscillation                                                                                                                   | `number`                                                                                                   | 5                |          |\n| onTick       | Callback for each iteration                                                                                                                                                                        | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -                |          |\n\n### Cluster Layout\n\n| Property       | Description                                                                               | Type      | Default     | Required |\n| -------------- | ----------------------------------------------------------------------------------------- | --------- | ----------- | -------- |\n| clustering     | Whether to use cluster layout                                                             | `boolean` | `false`     |          |\n| nodeClusterBy  | Field name in node data for clustering, effective when `clustering` is true               | `string`  | `'cluster'` |          |\n| clusterGravity | Gravity within clusters, affects cluster compactness, effective when `clustering` is true | `number`  | 10          |          |\n\n## Example Code\n\n### Basic Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### Cluster Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/FruchtermanLayout.zh.md":"---\ntitle: Fruchterman 力导向布局\norder: 14\n---\n\n## 概述\n\nFruchterman 布局是基于 [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf) 算法实现的一种力导向布局，通过灵活的参数配置模拟物理作用，使整个布局自动达到能量最小的稳定平衡状态，支持基础均匀分布和聚类布局。参考更多 Fruchterman 力导向布局[样例](/examples#layout-fruchterman)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts)\n\n## 使用场景\n\n- 基础均匀分布: 适用于展示节点均匀分布，整体结构清晰的网络关系图, 比如网络拓扑、知识图谱。\n- 聚类布局: 适用于具有内部聚合特性或分组的数据可视化展示, 比如社区结构展示、关联组分析。\n\n## 配置项\n\n| 属性         | 描述                                                                                                                                           | 类型                                                                                                       | 默认值   | 必选 |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type         | 布局类型                                                                                                                                       | `'fruchterman'`                                                                                            | -        | ✓    |\n| height       | 布局的高度                                                                                                                                     | `number`                                                                                                   | 容器高度 |      |\n| width        | 布局的宽度                                                                                                                                     | `number`                                                                                                   | 容器宽度 |      |\n| maxIteration | 最大迭代次数                                                                                                                                   | `number`                                                                                                   | 500      |      |\n| minMovement  | 收敛阈值                                                                                                                                       | `number`                                                                                                   | 0.4      |      |\n| gravity      | 中心力大小，指所有节点被吸引到 [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915) 的力。数字越大，布局越紧凑 | `number`                                                                                                   | 10       |      |\n| speed        | 每次迭代节点移动的速度。速度太快可能会导致强烈震荡                                                                                             | `number`                                                                                                   | 5        |      |\n| onTick       | 每一次迭代的回调函数                                                                                                                           | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -        |      |\n\n### 聚类布局\n\n| 属性           | 描述                                                                       | 类型      | 默认值      | 必选 |\n| -------------- | -------------------------------------------------------------------------- | --------- | ----------- | ---- |\n| clustering     | 是否按照聚类布局                                                           | `boolean` | `false`     |      |\n| nodeClusterBy  | 聚类布局依据的节点数据 `data` 中的字段名，在 `clustering` 为 `true` 时生效 | `string`  | `'cluster'` |      |\n| clusterGravity | 聚类内部的重力大小，影响聚类的紧凑程度，在 `clustering` 为 `true` 时生效   | `number`  | 10          |      |\n\n## 示例代码\n\n### 基本布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### 聚类布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","packages/site/docs/manual/layout/GridLayout.en.md":"---\ntitle: Grid Layout\norder: 15\n---\n\n## Overview\n\nThe grid layout arranges nodes in a grid pattern, suitable for scenarios where nodes need to be arranged neatly. This layout supports automatic calculation of the number of rows and columns, or you can specify them manually. It also supports preventing node overlap.\n\n## Use Cases\n\n- Visualizing data in a matrix or table format\n\n## Online Demo\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## Options\n\n| Property              | Description                                                                                                                     | Type                                             | Default   | Required |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | -------- |\n| type                  | Layout type                                                                                                                     | `grid`                                           | -         | ✓        |\n| begin                 | Grid start position (top-left corner), default is `[0, 0]`                                                                      | [number, number]                                 | [0, 0]    |          |\n| cols                  | Number of columns. If undefined, the algorithm calculates it automatically based on node count, layout space, and rows (if set) | number                                           | undefined |          |\n| rows                  | Number of rows. If undefined, the algorithm calculates it automatically based on node count, layout space, and cols (if set)    | number                                           | 10        |          |\n| width                 | Layout area width. In G6, the container width is used as the default value                                                      | number                                           | 300       |          |\n| height                | Layout area height. In G6, the container height is used as the default value                                                    | number                                           | 300       |          |\n| condense              | If false, uses all available canvas space; if true, uses the minimum canvas space                                               | boolean                                          | false     |          |\n| nodeSize              | Node size (diameter), used for collision detection when preventing overlap                                                      | Size \\| ((nodeData: Node) => Size)               | -         |          |\n| nodeSpacing           | Node spacing, used to adjust the gap between nodes                                                                              | ((node?: Node) => number) \\| number              | -         |          |\n| position              | Specify the row and column for each node                                                                                        | (node?: Node) => { row?: number; col?: number; } | undefined |          |\n| preventOverlap        | Whether to prevent node overlap. Requires nodeSize or size property in node data                                                | boolean                                          | false     |          |\n| preventOverlapPadding | Padding when preventing overlap. Effective when preventOverlap is true                                                          | number                                           | 10        |          |\n| sortBy                | Sort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting              | string                                           | undefined |          |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\nWhether to prevent overlap\n\nMust be used with nodeSize or the size property in node data. Only when data has data.size or nodeSize is set in the layout, collision detection for node overlap can be performed.\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\nPadding when preventing overlap. Effective when preventOverlap is true.\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\nSort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting. In G6, the container width is used as the default value for grid layout width. When used alone, the default is 300.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Custom Configuration\n\nYou can customize the grid layout in various ways:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // Start layout from [50, 50]\n    cols: 4, // 4 columns\n    rows: 6, // 6 rows\n    width: 400, // Layout area width\n    height: 600, // Layout area height\n    preventOverlap: true, // Prevent node overlap\n    nodeSize: 30, // Node size\n    condense: true, // Use minimum space\n    sortBy: 'value', // Sort by value property\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // Property for sorting\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Specify Node Position\n\nYou can specify the position for specific nodes using the `position` property:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // Specify position for specific nodes\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // Top-left\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // Top-right\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // Bottom-left\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // Bottom-right\n      return undefined; // Other nodes are auto-arranged\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Real Cases\n\n- [Grid Layout](/en/examples/layout/grid/#basic)\n","packages/site/docs/manual/layout/GridLayout.zh.md":"---\ntitle: 网格布局 Grid\norder: 15\n---\n\n## 概述\n\n网格布局将节点按照网格形式排列，适用于需要整齐排列节点的场景。该布局支持自动计算行列数，也可以手动指定行列数，并支持防止节点重叠。\n\n## 使用场景\n\n- 在数据可视化中需要展示矩阵或表格形式的数据关系\n\n## 在线体验\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## 配置项\n\n| 属性                  | 描述                                                                                                                             | 类型                                             | 默认值    | 必选 |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | ---- |\n| type                  | 布局类型                                                                                                                         | `grid`                                           | -         | ✓    |\n| begin                 | 网格开始位置（左上角），默认为 `[0, 0]`                                                                                          | [number, number]                                 | [0, 0]    |      |\n| cols                  | 网格的列数，为 undefined 时算法根据节点数量、布局空间、rows（若指定）自动计算                                                    | number                                           | undefined |      |\n| rows                  | 网格的行数，为 undefined 时算法根据节点数量、布局空间、cols（若指定）自动计算                                                    | number                                           | 10        |      |\n| width                 | 布局区域宽度，在 G6 中使用当前容器的宽度作为默认值                                                                               | number                                           | 300       |      |\n| height                | 布局区域高度，在 G6 中使用当前容器的高度作为默认值                                                                               | number                                           | 300       |      |\n| condense              | 为 false 时表示利用所有可用画布空间，为 true 时表示利用最小的画布空间                                                            | boolean                                          | false     |      |\n| nodeSize              | 节点大小（直径），用于防止节点重叠时的碰撞检测                                                                                   | Size \\| ((nodeData: Node) => Size)               | -         |      |\n| nodeSpacing           | 节点间距，用于调整节点之间的间隔                                                                                                 | ((node?: Node) => number) \\| number              | -         |      |\n| position              | 指定每个节点所在的行和列                                                                                                         | (node?: Node) => { row?: number; col?: number; } | undefined |      |\n| preventOverlap        | 是否防止节点重叠，需要配合 nodeSize 或节点数据中的 size 属性使用                                                                 | boolean                                          | false     |      |\n| preventOverlapPadding | 避免重叠时节点的间距 padding，preventOverlap 为 true 时生效                                                                      | number                                           | 10        |      |\n| sortBy                | 指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心 | string                                           | undefined |      |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\n是否防止重叠\n\n必须配合下面属性 nodeSize 或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\n避免重叠时节点的间距 padding，preventOverlap 为 true 时生效\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\n指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心\n\n在 G6 中使用当前容器的宽度作为 grid 布局 width 的默认值。单独使用此布局时默认值为 300\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 自定义配置\n\n可以通过多种方式自定义网格布局：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // 从坐标 [50, 50] 开始布局\n    cols: 4, // 指定 4 列\n    rows: 6, // 指定 6 行\n    width: 400, // 布局区域宽度\n    height: 600, // 布局区域高度\n    preventOverlap: true, // 防止节点重叠\n    nodeSize: 30, // 节点大小\n    condense: true, // 使用最小空间\n    sortBy: 'value', // 按 value 属性排序\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // 用于排序的属性\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 指定节点位置\n\n可以通过 `position` 属性为特定节点指定位置：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // 为特定节点指定位置\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // 左上角\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // 右上角\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // 左下角\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // 右下角\n      return undefined; // 其他节点自动布局\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [Grid布局](/examples/layout/grid/#basic)\n","packages/site/docs/manual/layout/IndentedLayout.en.md":"---\ntitle: Indented Tree\norder: 16\n---\n\n# Indented Tree Layout\n\n## Overview\n\nIndented tree layout represents the hierarchy of tree nodes through indentation in the horizontal direction. Each element occupies a row or column, commonly used in file directory structures, organizational charts, and other scenarios. This layout provides a clear structure for displaying hierarchical relationships.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented Tree Layout'/>\n\n## Use Cases\n\n- File directory structure visualization\n- Organizational charts\n- Classification system display\n- Tree-like data where hierarchical relationships need to be emphasized\n\n## Configuration Items\n\n> IndentedLayout supports common layout configuration items and specific configuration items, as shown below.\n\n| Property               | Description                                                         | Type                            | Default    | Required |\n| ---------------------- | ------------------------------------------------------------------- | ------------------------------- | ---------- | -------- |\n| type                   | Layout type, must be 'indented'                                     | 'indented'                      | -          | ✓        |\n| direction              | Layout direction, see details below                                 | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |          |\n| indent                 | Column spacing, fixed value or function                             | number \\| (d?: Node) => number  | 20         |          |\n| getWidth               | Get each node's width, effective when direction='H'                 | (d?: Node) => number            | -          |          |\n| getHeight              | Get each node's height                                              | (d?: Node) => number            | -          |          |\n| getSide                | Node placement on left/right side of root, overrides direction='H'  | (d?: Node) => 'left' \\| 'right' | -          |          |\n| dropCap                | Whether the first child of each node starts on the next line        | boolean                         | true       |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (when preLayout=true) | boolean                         | false      |          |\n| nodeFilter             | Nodes participating in this layout                                  | (node: NodeData) => boolean     | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements       | boolean                         | false      |          |\n| enableWorker           | Whether to run layout in WebWorker                                  | boolean                         | -          |          |\n| iterations             | Number of iterations for iterative layout                           | number                          | -          |          |\n\n### Complex Type Explanations\n\n- **direction**\n\n  - `'LR'`: Root node on the left, layout to the right\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`: Root node on the right, layout to the left\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`: Root node in the middle, horizontal symmetric layout\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - Fixed value: Consistent indentation for all levels\n  - Function: (d?: Node) => number, customize indentation based on node\n  - Example:\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - Used to customize each node's width/height, often for content adaptation\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - Specifies which side of the root node a node should be placed, only effective when direction='H'\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## Example Code\n\n> For more examples, see [Online Demo](https://g6.antv.antgroup.com/en/examples/layout/indented)\n\n### Automatic Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### Right Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'LR'\n```\n\n### Left Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'RL'\n```\n\n### Custom Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### No Line Break for First Child Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","packages/site/docs/manual/layout/IndentedLayout.zh.md":"---\ntitle: 缩进树 Indented\norder: 16\n---\n\n## 概述\n\nIndented（缩进树）布局是一种通过水平方向的缩进量来表示树节点层级的布局方式。每个元素占据一行或一列，常用于文件目录结构、组织架构等场景。该布局结构清晰，便于展示层级关系。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented 缩进树布局示意图'/>\n\n## 使用场景\n\n- 文件目录结构可视化\n- 组织架构树\n- 分类体系展示\n- 需要突出层级关系的树状数据\n\n## 配置项\n\n> IndentedLayout 支持通用布局配置项和专有配置项，详见下表。\n\n| 属性                   | 描述                                                 | 类型                            | 默认值     | 必选 |\n| ---------------------- | ---------------------------------------------------- | ------------------------------- | ---------- | ---- |\n| type                   | 布局类型，需为 'indented'                            | 'indented'                      | -          | ✓    |\n| direction              | 布局方向，根节点在左/右/中间，详见下方说明           | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |      |\n| indent                 | 列间间距，支持固定值或函数                           | number \\| (d?: Node) => number  | 20         |      |\n| getWidth               | 获取每个节点宽度，仅 direction='H' 时生效            | (d?: Node) => number            | -          |      |\n| getHeight              | 获取每个节点高度                                     | (d?: Node) => number            | -          |      |\n| getSide                | 节点排布在根节点的左/右侧，设置后 direction='H' 失效 | (d?: Node) => 'left' \\| 'right' | -          |      |\n| dropCap                | 每个节点的第一个子节点是否换行                       | boolean                         | true       |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（preLayout=true 时生效）      | boolean                         | false      |      |\n| nodeFilter             | 参与该布局的节点                                     | (node: NodeData) => boolean     | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                   | boolean                         | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                          | boolean                         | -          |      |\n| iterations             | 迭代布局的迭代次数                                   | number                          | -          |      |\n\n### 复杂类型说明\n\n- **direction**\n\n  - `'LR'`：根节点在左，向右布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`：根节点在右，向左布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`：根节点在中间，水平对称布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - 固定数值：所有层级缩进一致\n  - 函数：(d?: Node) => number，可根据节点自定义缩进\n  - 示例：\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - 用于自定义每个节点的宽度/高度，常用于自适应内容\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - 指定节点在根节点的哪一侧，仅 direction='H' 时生效\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## 示例代码\n\n> 更多示例可参考 [在线 Demo](https://g6.antv.antgroup.com/examples/layout/indented)\n\n### 子节点自动分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### 子节点右侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'LR'\n```\n\n### 子节点左侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'RL'\n```\n\n### 自定义子节点分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### 首子节点不换行\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","packages/site/docs/manual/layout/MdsLayout.en.md":"---\ntitle: MDS High-dimensional Data Dimensionality Reduction Layout\norder: 17\n---\n\n# MDS High-dimensional Data Dimensionality Reduction Layout\n\n## Overview\n\nMDS (Multidimensional Scaling) is a classic dimensionality reduction algorithm. In G6, the MDS layout constructs a distance matrix between nodes and restores their relative distances in high-dimensional space as much as possible in 2D space. It is suitable for graph visualization scenarios that show similarity, distance, or structural relationships between nodes.\n\n## Use Cases\n\n- Data dimensionality reduction visualization\n- Displaying distance relationships between nodes\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## Options\n\n| Option           | Description                           | Type              | Default       | Required |\n| :--------------- | :------------------------------------ | :---------------- | :------------ | :------- |\n| **type**         | Layout type                           | `mds`             | -             | Yes      |\n| **center**       | Center position of the layout         | `[number,number]` | canvas center | No       |\n| **linkDistance** | Ideal length of edges (spring length) | `number`          | 200           | No       |\n\n**center**\n\nThe center coordinates of the layout. All nodes will be symmetrically distributed around this point.\n\n**linkDistance**\n\n> number Default: 50\n\nThe ideal distance between nodes. The larger the value, the more dispersed the nodes.\n\n## Code Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/MdsLayout.zh.md":"---\ntitle: 高维数据降维布局 MDS\norder: 17\n---\n\n## 概述\n\nMDS（多维尺度分析，Multidimensional Scaling）是一种经典的降维算法。在 G6 中，MDS 布局通过构造节点间的距离矩阵，在二维空间中尽可能还原它们在高维空间中的相对距离。适用于展示节点之间相似度、距离或结构关系的图可视化场景。\n\n## 使用场景\n\n- 数据降维可视化\n- 展示节点之间的距离关系\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## 配置项\n\n| 配置项           | 描述                               | 类型              | 默认值   | 必选 |\n| :--------------- | :--------------------------------- | :---------------- | :------- | :--- |\n| **type**         | 布局类型                           | `mds`             | -        | 是   |\n| **center**       | 布局的中心位置                     | `[number,number]` | 画布中心 | 否   |\n| **linkDistance** | 边的理想长度（弹簧未受力时的长度） | `number`          | 200      | 否   |\n\n**center**\n\n布局的中心点坐标，所有节点会围绕该点对称分布。\n\n**linkDistance**\n\n> number Default: 50\n\n节点之间的理想距离，越大则节点间距离越分散。\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/MindmapLayout.en.md":"---\ntitle: Mindmap Tree\norder: 18\n---\n\n## Overview\n\nThe mindmap tree layout is suitable for hierarchical layouts of tree structures, supporting expansion on both left and right sides. Nodes at the same depth will be placed on the same layer. Note: the layout **does** take node size into account. See more mindmap layout [examples](/en/examples#layout-mindmap) or [source code](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"Mindmap tree options diagram\" />\n\n| Property  | Description                                                                                             | Type                                | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------- | -------- |\n| type      | Layout type                                                                                             | `mindmap`                           | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                 | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`    |          |\n| getHeight | Function to calculate the height of each node                                                           | (d?: Node) => number                |         | ✓        |\n| getWidth  | Function to calculate the width of each node                                                            | (d?: Node) => number                |         | ✓        |\n| getVGap   | Vertical gap for each node. Note: the actual vertical gap between two nodes is twice the vgap           | (d?: Node) => number                |         |          |\n| getHGap   | Horizontal gap for each node. Note: the actual horizontal gap between two nodes is twice the hgap       | (d?: Node) => number                |         |          |\n| getSide   | Set whether the node is placed on the left or right of the root. Only effective when `direction` is `H` | (d?: Node) => string                |         |          |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\nTree layout direction\n\n- `'H'`: horizontal — The children of the root node are divided into two parts and placed on the left and right sides of the root node. You can pass the `getSide` method to specify the left/right distribution logic for each node. If not provided, the first half will be placed on the right, and the second half on the left by default.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='Horizontal layout'/>\n\n- `'LR' | 'TB'`: Children are placed on the right side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `'RL'`: Children are placed on the left side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `BT`: Children are placed on the right side of the root node, then the entire graph is rotated 180° along the X axis.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='Vertical layout'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\nWidth of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\nHeight of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\nHorizontal gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\nVertical gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\nSet whether the node is placed on the left or right of the root. Note: only effective when `direction` is `H`. If not set, the first half of the children will be placed on the right, and the second half on the left by default. See [getSide auto calculation logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### Suitable Scenarios\n\n- Data lineage graph: `direction='H'` is suitable for rendering upstream and downstream lineage of a specified node, with upstream on the left and downstream on the right of the central node.\n- Mind map: Build custom mind map components.\n","packages/site/docs/manual/layout/MindmapLayout.zh.md":"---\ntitle: 脑图树 Mindmap\norder: 18\n---\n\n## 概述\n\n脑图树布局适用于树状结构的层次化布局，支持左右两侧展开，深度相同的节点将会被放置在同一层。需要注意：布局**会**考虑节点的大小。参考更多脑图布局[样例](/examples#layout-mindmap)或[源码](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"脑图树配置项图解\" />\n\n| 属性      | 描述                                                                                                  | 类型                                | 默认值 | 必选 |\n| --------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                              | `mindmap`                           | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                        | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`   |      |\n| getHeight | 计算每个节点的高度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getWidth  | 计算每个节点的宽度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getVGap   | 每个节点的垂直间隙，注意实际两个节点间的垂直间隙是2倍的vgap                                           | (d?: Node) => number                |        |      |\n| getHGap   | 每个节点的水平间隙，注意实际两个节点间的水平间隙是2倍的hgap                                           | (d?: Node) => number                |        |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在`H`布局方向上生效 | (d?: Node) => string                |        |      |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\n树布局的方向\n\n- `'H'`：horizontal（水平）—— 根节点的子节点分成两部分横向放置在根节点左右两侧。可传入`getSide`方法指定每个节点的左右分布逻辑，不传则默认将前半部分放置在右侧，后半部分放置在左侧。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='水平布局'/>\n\n- `'LR' | 'TB'`：将子节点排布在根节点的右侧；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='竖直布局'/>\n\n- `'RL'`：将子节点排布在根节点的左侧；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='竖直布局'/>\n\n- `BT`：将子节点排布在根节点右侧，然后将整个图沿X轴旋转180°；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='竖直布局'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在`direction`为`H`时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考[getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### 布局适用场景\n\n- 数据血缘图：`direction='H'`很适合渲染血缘图中查看指定节点的上下游血缘的场景，上游分布在中心节点的左侧，下游分布在右侧；\n- 思维导图：构建自定义的思维导图组件。\n","packages/site/docs/manual/layout/RadialLayout.en.md":"---\ntitle: Radial Layout\norder: 19\n---\n\n## Overview\n\nRadial layout is a graph layout algorithm that arranges nodes in concentric circles by layers. It is commonly used to display hierarchical relationships, community structures, and more. This layout supports advanced features such as node overlap prevention and group sorting, making it suitable for visualizing various network structures.\n\n## Use Cases\n\n- Displaying hierarchical structures (e.g., organizational charts, family trees)\n- Community structure analysis\n- Scenarios that need to highlight the central node and its radiating relationships\n- Complex networks requiring node grouping and sorting\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // other configurations...\n});\n```\n\n## Options\n\n| Property                   | Description                                                     | Type                                             | Default  | Required |\n| -------------------------- | --------------------------------------------------------------- | ------------------------------------------------ | -------- | -------- |\n| type                       | Layout type                                                     | string                                           | `radial` | ✓        |\n| center                     | Center coordinates                                              | [number, number]                                 | -        |          |\n| focusNode                  | Radiating center node                                           | string \\| Node \\| null                           | null     |          |\n| height                     | Canvas height                                                   | number                                           | -        |          |\n| width                      | Canvas width                                                    | number                                           | -        |          |\n| nodeSize                   | Node size (diameter)                                            | number \\| number[] \\| ((nodeData: Node) => Size) | -        |          |\n| nodeSpacing                | Minimum node spacing (effective when preventing overlap)        | number \\| (nodeData: Node) => number             | 10       |          |\n| linkDistance               | Edge length                                                     | number                                           | 50       |          |\n| unitRadius                 | Radius per circle; when null, automatically computed from space | number \\| null                                   | 100      |          |\n| maxIteration               | Maximum number of iterations                                    | number                                           | 1000     |          |\n| maxPreventOverlapIteration | Max iterations for overlap prevention                           | number                                           | 200      |          |\n| preventOverlap             | Whether to prevent node overlap                                 | boolean                                          | false    |          |\n| sortBy                     | Field or sorting function for nodes in the same layer           | string \\| ((nodeData: Node) => number \\| string) | -        |          |\n| sortStrength               | Sorting strength for nodes in the same layer                    | number                                           | 10       |          |\n| strictRadial               | Strictly place nodes in the same layer on the same ring         | boolean                                          | true     |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\nResult:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"Basic Radial Layout\" style=\"max-width: 600px;\" />\n\n## Real Cases\n\n- [Basic Radial Layout](/en/examples/layout/radial/#basic)\n- [Strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#strict-prevent-overlap)\n- [Non-strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#non-strict-prevent-overlap)\n- [Cluster Sorting](/en/examples/layout/radial/#cluster-sort)\n","packages/site/docs/manual/layout/RadialLayout.zh.md":"---\ntitle: 径向布局 Radial\norder: 19\n---\n\n## 概述\n\n径向（Radial）布局是一种将节点以同心圆方式分层排列的图布局算法，常用于展示层级关系、社群结构等。该布局支持节点防重叠、分组排序等高级特性，适用于多种网络结构的可视化。\n\n## 使用场景\n\n- 展示层级结构（如组织架构、家谱等）\n- 社群结构分析\n- 需要突出中心节点及其辐射关系的场景\n- 需要节点分组、排序的复杂网络\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // 其他配置...\n});\n```\n\n## 配置项\n\n| 属性                       | 描述                                         | 类型                                             | 默认值   | 必选 |\n| -------------------------- | -------------------------------------------- | ------------------------------------------------ | -------- | ---- |\n| type                       | 布局类型                                     | string                                           | `radial` | ✓    |\n| center                     | 圆心坐标                                     | [number, number]                                 | -        |      |\n| focusNode                  | 辐射中心节点                                 | string \\| Node \\| null                           | null     |      |\n| height                     | 画布高度                                     | number                                           | -        |      |\n| width                      | 画布宽度                                     | number                                           | -        |      |\n| nodeSize                   | 节点大小（直径）                             | number \\| number[] \\| ((nodeData: Node) => Size) | -        |      |\n| nodeSpacing                | 节点最小间距（防重叠时生效）                 | number \\| (nodeData: Node) => number             | 10       |      |\n| linkDistance               | 边长度                                       | number                                           | 50       |      |\n| unitRadius                 | 每圈半径；为 null 时按布局空间自动计算       | number \\| null                                   | 100      |      |\n| maxIteration               | 最大迭代次数                                 | number                                           | 1000     |      |\n| maxPreventOverlapIteration | 防重叠最大迭代次数                           | number                                           | 200      |      |\n| preventOverlap             | 是否防止节点重叠                             | boolean                                          | false    |      |\n| sortBy                     | 同层节点排序字段或排序函数                   | string \\| ((nodeData: Node) => number \\| string) | -        |      |\n| sortStrength               | 同层节点排序强度                             | number                                           | 10       |      |\n| strictRadial               | 是否严格每层节点在同一圆环上（防重叠时生效） | boolean                                          | true     |      |\n\n## 代码示例\n\n### 基本用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\n效果如下：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"基本 Radial 辐射布局\" style=\"max-width: 600px;\" />\n\n## 实际案例\n\n- [基本 Radial 辐射布局](/examples/layout/radial/#basic)\n- [防止节点重叠的严格辐射布局](/examples/layout/radial/#strict-prevent-overlap)\n- [防止节点重叠的非严格辐射布局](/examples/layout/radial/#non-strict-prevent-overlap)\n- [排序聚类](/examples/layout/radial/#cluster-sort)\n","packages/site/docs/manual/layout/RandomLayout.en.md":"---\ntitle: Random Layout\norder: 20\n---\n\n## Overview\n\n**Random Layout** is a layout method based on simple rules. Its core logic is to generate random coordinates for each node within a specified layout area (defined by the layout center, width, and height). The coordinates are completely random, and there is no node collision prevention.\n\n## Use Cases\n\nThe use cases for random layout are very limited. It is only recommended for the following scenarios:\n\n- **Initial Data Display**:\n\n  During early development, when debugging data loading logic or quickly verifying data structure, random layout can be used for preliminary validation.\n\nFor final business delivery, it is recommended to use layouts that better reflect business value, such as [AntVDagreLayout](/en/manual/layout/antv-dagre-layout), [ForceLayout](/en/manual/layout/force-layout), or [custom layouts](/en/manual/layout/custom-layout).\n\n## Basic Usage\n\nAll other configurations use defaults (the layout width and height default to the entire canvas container).\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## Options\n\n| Property | Description   | Type                                         | Default                                   | Required |\n| -------- | ------------- | -------------------------------------------- | ----------------------------------------- | -------- |\n| type     | Layout type   | random                                       | -                                         | ✓        |\n| center   | Layout center | [number, number] \\| [number, number, number] | [`layout width` / 2, `layout height` / 2] |          |\n| height   | Layout height | number                                       | canvas height                             |          |\n| width    | Layout width  | number                                       | canvas width                              |          |\n\n## Example\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/RandomLayout.zh.md":"---\ntitle: 随机布局 Random\norder: 20\n---\n\n## 概述\n\n**随机布局（Random Layout）** 是一种基于简单规则的布局方式，其核心逻辑是为每个节点在指定布局区域（由布局中心点、宽度和高度定义）内生成随机坐标（完全随机，无节点防碰撞）。\n\n## 使用场景\n\n随机布局的使用场景非常局限，只推荐以下场景使用：\n\n- **数据初步展示**:\n\n  在开发初期调试数据加载逻辑或需要快速验证数据结构的情况下，可使用随机布局先行验证\n\n业务最终交付推荐使用更能体现业务价值的布局方式，比如 [AntVDagreLayout](/manual/layout/antv-dagre-layout) 、[ForceLayout](/manual/layout/force-layout) 或者[自定义布局](/manual/layout/custom-layout)等。\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## 配置项\n\n| 属性   | 描述       | 类型                                         | 默认值                           | 必选 |\n| ------ | ---------- | -------------------------------------------- | -------------------------------- | ---- |\n| type   | 布局类型   | random                                       | -                                | ✓    |\n| center | 布局的中心 | [number, number] \\| [number, number, number] | [`布局宽度` / 2, `布局高度` / 2] |      |\n| height | 布局的高度 | number                                       | 画布高度                         |      |\n| width  | 布局的宽度 | number                                       | 画布宽度                         |      |\n\n## 示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/Snake.en.md":"---\ntitle: Snake Layout\norder: 21\n---\n\n## Overview\n\nSnake Layout is a special type of graph layout that can more efficiently display long chain structures in a limited space. Note that the graph data must ensure that nodes are linearly arranged from the source node to the sink node, forming a clear path.\n\nNodes are arranged in an S-shape: the first node is at the start of the first row, subsequent nodes are arranged to the right in the first row until the end. At the end of the row, the next row's nodes are arranged from right to left. This process repeats until all nodes are placed.\n\n## Use Cases\n\nSuitable for scenarios that require compact presentation of linear relationships:\n\n- **Long process visualization**\n\n  Perfect for scenarios with many process steps, such as approval flows, production line procedures, logistics routes, etc.\n\n- **Hierarchical structures in limited space**\n\n  When the hierarchy is too long but the canvas is limited, rows can be folded to save space. For example, API call dependencies (client → gateway → serviceA → serviceB → database, snake layout compresses 5 layers into 2 rows), or file directory trees (deeply nested folder structures, e.g., src/components/utils/helpers/..., using snake layout to fold subdirectories horizontally).\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## Options\n\n> If the layout has specific properties, they are listed below. For common layout options, see [Base Layout Options](/en/manual/layout/base-layout)\n\n| Property                | Description                                                 | Type                                               | Default                                                    | Required |\n| ----------------------- | ----------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- | -------- |\n| type                    | Layout type                                                 | snake                                              | -                                                          | ✓        |\n| [clockwise](#clockwise) | Whether nodes are arranged clockwise                        | boolean                                            | true                                                       |          |\n| colGap                  | Gap size between columns                                    | number                                             | Automatically calculated by canvas width and total columns |          |\n| cols                    | Number of columns                                           | number                                             | 5                                                          |          |\n| nodeSize                | Node size                                                   | Size \\| ((node: NodeData) => Size)                 | -                                                          |          |\n| padding                 | Padding, i.e., distance from layout area to canvas boundary | number \\| number[]                                 | 0                                                          |          |\n| rowGap                  | Gap size between rows                                       | number                                             | Automatically calculated by canvas height and total rows   |          |\n| sortBy                  | Node sorting method                                         | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | Default is the path order in the graph                     |          |\n\n### clockwise\n\n- When arranged clockwise, nodes start from the top left, the first row is arranged left to right, the second row right to left, and so on, forming an S-shaped path.\n- When arranged counterclockwise, nodes start from the top right, the first row is arranged right to left, the second row left to right, and so on, forming a reversed S-shaped path.\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/Snake.zh.md":"---\ntitle: 蛇形布局 Snake\norder: 21\n---\n\n## 概览\n\n蛇形布局（Snake Layout）是一种特殊的图形布局方式，能够在较小的空间内更有效地展示长链结构。需要注意的是，其图数据需要确保节点按照从源节点到汇节点的顺序进行线性排列，形成一条明确的路径。\n\n节点按 S 字型排列，第一个节点位于第一行的起始位置，接下来的节点在第一行向右排列，直到行末尾。到达行末尾后，下一行的节点从右向左反向排列。这个过程重复进行，直到所有节点排列完毕。\n\n## 使用场景\n\n适合需要紧凑呈现线性关系的场景：\n\n- **长流程可视化**\n\n  完美适配流程步骤过多的场景，如审批流程、生产线工序、物流运输路径等。\n\n- **有限空间内的层级结构**\n\n  层级结构过长但画布受限，需通过折叠行节省空间，比如 API 调用依赖（客户端 → 网关 → 服务A → 服务B → 数据库，蛇形布局将 5 层压缩为 2 行）、文件目录树（深度嵌套的文件夹结构，如 src/components/utils/helpers/... ，用蛇形布局横向折叠子目录）。\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## 配置项\n\n> 如果布局有其特定的属性，我们将在下面列出。对于所有布局的通用属性，见[布局通用配置项](/manual/layout/base-layout)\n\n| 属性                    | 描述                               | 类型                                               | 默认值                                 | 必选 |\n| ----------------------- | ---------------------------------- | -------------------------------------------------- | -------------------------------------- | ---- |\n| type                    | 布局类型                           | snake                                              | -                                      | ✓    |\n| [clockwise](#clockwise) | 节点排布方向是否顺时针             | boolean                                            | true                                   |      |\n| colGap                  | 节点列之间的间隙大小               | number                                             | 默认将根据画布宽度和节点总列数自动计算 |      |\n| cols                    | 节点列数                           | number                                             | 5                                      |      |\n| nodeSize                | 节点尺寸                           | Size \\| ((node: NodeData) => Size)                 | -                                      |      |\n| padding                 | 内边距，即布局区域与画布边界的距离 | number \\| number[]                                 | 0                                      |      |\n| rowGap                  | 节点行之间的间隙大小               | number                                             | 默认将根据画布高度和节点总行数自动计算 |      |\n| sortBy                  | 节点排序方法                       | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | 默认按照在图中的路径顺序进行展示       |      |\n\n### clockwise\n\n- 在顺时针排布时，节点从左上角开始，第一行从左到右排列，第二行从右到左排列，依次类推，形成 S 型路径。\n\n- 在逆时针排布时，节点从右上角开始，第一行从右到左排列，第二行从左到右排列，依次类推，形成反向 S 型路径。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/layout/custom-layout.en.md":"---\ntitle: Custom Layout\norder: 22\n---\n\n## Overview\n\nIn G6, layouts are divided into two types: 'iterative layout' and 'non-iterative layout'. An iterative layout refers to a layout algorithm that iterates multiple times until convergence, while a non-iterative layout refers to a layout algorithm that executes only once.\n\n## Implement Layout\n\n### Non-Iterative Layout\n\nImplementing a non-iterative layout is relatively straightforward; you only need to implement the `execute` method in `BaseLayout`. Below is a simple implementation of a custom layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\nIn the code above, we implemented a simple layout algorithm that arranges nodes along a diagonal line starting from the top-left corner.\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=info}\n\nThe `execute` method returns a GraphData object, which only needs to contain the basic information of the elements (such as id, source, target) and the properties added by the layout (such as x, y, control points of edges, etc.), and does not need to contain other unnecessary information.\nIf you only need to layout the nodes, you can return only the node information and do not need to return the edge information.\n:::\n\n### Iterative Layout\n\nThe implementation of an iterative layout also requires inheriting from `BaseLayout`, but in addition to `execute`, you also need to implement the `tick` and `stop` methods. The `tick` method is used to iterate the layout to a specified number of rounds, and the `stop` method is used to stop the layout iteration.\n\nIn addition, in iterative layouts, you need to call `options.onTick` each time the layout iterates to trigger the graph update.\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\nBelow is a simple implementation of an iterative layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\nIn this example, we have implemented a simple iterative layout algorithm that toggles the x-coordinate of the nodes between 50 and 150 every 200 milliseconds and arranges them in order along the y-axis according to the sequence of the nodes.\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## Register Layout\n\nYou can register through the `register` method provided by G6. For more details, please refer to [Register Layout](/en/manual/core-concept/layout#register-layout)\n\n## Configure Layout\n\nThe type and parameters of the layout can be configured in `options.layout`. For more details, please refer to [Configure Layout](/en/manual/core-concept/layout#configure-layout)\n","packages/site/docs/manual/layout/custom-layout.zh.md":"---\ntitle: 自定义布局\norder: 22\n---\n\n## 概述\n\nG6 中布局分为`迭代布局`和`非迭代布局`两种，迭代布局是指布局算法会迭代多次直到收敛，非迭代布局是指布局算法只执行一次。\n\n## 实现布局\n\n### 非迭代布局\n\n实现一个非迭代布局相对简单，只需要实现 `BaseLayout` 中的 `execute` 方法即可，下面是一个简单的自定义布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\n在上面的代码中，我们实现了一个简单的布局算法，将节点从左上角沿对角线排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=提示}\n`execute` 方法返回的是一个 GraphData 对象，里面仅需要包含元素的基本信息（如 id、source、target）以及布局新增的属性（如 x、y、边的控制点等），不需要包含其他无用的信息。\n如果仅需要对节点进行布局，可以只返回节点信息，不需要返回边的信息。\n:::\n\n### 迭代布局\n\n迭代布局的实现同样需要继承 `BaseLayout`，但是除 `execute` 外还需要实现 `tick` 和 `stop` 方法，`tick` 方法用于将布局迭代到指定轮次，`stop` 方法用于停止布局迭代。\n\n此外，迭代布局中需要在每次迭代调用 `options.onTick` 以触发图的更新。\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\n下面是一个简单的迭代布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\n在这个例子中，我们实现了一个简单的迭代布局算法，每 200ms 将节点的 x 坐标在 50 和 150 之间切换，并按照节点顺序在 y 方向上排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## 注册布局\n\n通过 G6 提供的 register 方法注册即可，详见[注册布局](/manual/layout/overview#注册布局)\n\n## 配置布局\n\n可在 `options.layout` 中配置布局的类型和参数，详见[配置布局](/manual/layout/overview#配置布局)\n","packages/site/docs/manual/layout/overview.en.md":"---\ntitle: Layout Overview\norder: 0\n---\n\n## Overview\n\nGraph layout refers to the process of arranging elements in a graph according to certain rules, such as force-directed layout based on charge elasticity models, grid layout with sequential arrangement, and tree layout based on hierarchical structures.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Layout Types\n\nG6 provides a variety of layout algorithms, allowing users to choose the appropriate one based on their needs:\n\n- [AntVDagreLayout](/en/manual/layout/antv-dagre-layout): Custom layout based on dagre\n- [CircularLayout](/en/manual/layout/circular-layout): Circular layout\n- [ComboCombinedLayout](/en/manual/layout/combo-combined-layout): Layout suitable for combinations\n- [ConcentricLayout](/en/manual/layout/concentric-layout): Concentric layout\n- [D3Force3DLayout](/en/manual/layout/d3-force3-d-layout): [3D Force-directed](https://github.com/vasturiano/d3-force-3d) layout\n- [D3ForceLayout](/en/manual/layout/d3-force-layout): Force-directed layout based on [D3](https://d3js.org/d3-force)\n- [DagreLayout](/en/manual/layout/dagre-layout): [dagre](https://github.com/dagrejs/dagre) layout\n- [FishboneLayout](/en/manual/layout/fishbone): Fishbone layout\n- [ForceAtlas2Layout](/en/manual/layout/force-atlas2-layout): [ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) layout\n- [ForceLayout](/en/manual/layout/force-layout): Force-directed layout\n- [FruchtermanLayout](/en/manual/layout/fruchterman-layout): [Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) layout\n- [GridLayout](/en/manual/layout/grid-layout): Grid layout\n- [MDSLayout](/en/manual/layout/mds-layout): High-dimensional data dimensionality reduction layout\n- [RadialLayout](/en/manual/layout/radial-layout): Radial layout\n- [RandomLayout](/en/manual/layout/random-layout): Random layout\n- [SnakeLayout](/en/manual/layout/snake): Snake layout\n- [CompactBoxLayout](/en/manual/layout/compact-box-layout): Compact tree layout\n- [DendrogramLayout](/en/manual/layout/dendrogram-layout): Dendrogram layout\n- [MindmapLayout](/en/manual/layout/mindmap-layout): Mindmap layout\n- [IndentedLayout](/en/manual/layout/indented-layout): Indented tree layout\n\nAmong them, `CompactBox Layout`, `Dendrogram Layout`, `Mindmap Layout`, and `Indented Layout` are types of tree layouts suitable for tree-structured graphs.\n\n## Register Layout\n\nYou can directly use built-in layouts, but if you want to use other layouts, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## Configure Layout\n\nThe `layout` configuration item can specify the graph's layout algorithm, for example:\n\n```typescript\n{\n  layout: {\n    // Specify the layout algorithm to use\n    type: 'force',\n    // Configuration items for the layout algorithm\n    gravity: 10\n    // ...\n  }\n}\n```\n\nYou can also use `graph.setLayout` to update the layout configuration after the graph is instantiated.\n\nStarting from `5.1`, layout docs align their shared fields with `@antv/layout`. Besides each layout's own algorithm parameters, you should also pay attention to common options such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`.\n\n## Layout Acceleration\n\nG6 provides accelerated versions for some layout algorithms, including executing layout algorithms in Web Workers, providing [WASM](https://webassembly.org/) versions of layout algorithms, and GPU-accelerated layout algorithms. They can be used as follows:\n\n### Execute Layout Algorithms in Web Workers\n\nExcept for tree layouts, all built-in layout algorithms in G6 support execution in Web Workers. Simply set `enableWorker` to `true`:\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### Use WASM Version Layout Algorithms\n\nCurrently supported WASM version layout algorithms include: `Fruchterman Layout`, `ForceAtlas Layout`, `Force Layout`, `Dagre Layout`.\n\nFirst, install `@antv/layout-wasm`:\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\nInitialize threads:\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... other configurations\n  },\n});\n```\n\n### Use GPU-Accelerated Layout\n\nCurrently supported GPU-accelerated layout algorithms include: `Fruchterman Layout`, `GForce Layout`.\n\nFirst, install `@antv/layout-gpu`:\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... other configurations\n  },\n});\n```\n\n## Execute Layout\n\nUsually, after calling `graph.render()`, G6 will automatically execute the layout algorithm.\n\nIf you need to manually execute the layout algorithm, G6 provides the following APIs:\n\n- [layout](/api/layout#graphlayoutlayoutoptions): Execute layout algorithm\n- [setLayout](/api/layout#graphsetlayoutlayout): Set layout algorithm\n- [stopLayout](/api/layout#graphstoplayout): Stop layout algorithm\n\n## Custom Layout\n\nIf the built-in layout algorithms cannot meet your needs, you can customize layout algorithms. For details, please refer to [Custom Layout](/manual/layout/custom-layout).\n\nIf you are migrating layout configuration from G6 `5.0` to `5.1`, see [Upgrade from 5.0 to 5.1 (Layout)](/en/manual/whats-new/upgrade-to-5-1).\n","packages/site/docs/manual/layout/overview.zh.md":"---\ntitle: 布局总览\norder: 0\n---\n\n## 概述\n\n图布局是指将图中的元素按照一定的规则进行排列的过程，例如基于电荷弹性模型的力导向布局、逐次排布的网格布局、基于层次结构的树布局等。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 布局类型\n\nG6 提供了多种布局算法，用户可以根据自己的需求选择合适的布局算法：\n\n- [AntVDagreLayout](/manual/layout/antv-dagre-layout)：基于 dagre 定制的布局\n- [CircularLayout](/manual/layout/circular-layout)：环形布局\n- [ComboCombinedLayout](/manual/layout/combo-combined-layout)：适用于存在组合的布局\n- [ConcentricLayout](/manual/layout/concentric-layout)：同心圆布局\n- [D3Force3DLayout](/manual/layout/d3-force3-d-layout)：[3D 力导向](https://github.com/vasturiano/d3-force-3d)布局\n- [D3ForceLayout](/manual/layout/d3-force-layout)：基于 [D3](https://d3js.org/d3-force) 的力导向布局\n- [DagreLayout](/manual/layout/dagre-layout)：[dagre](https://github.com/dagrejs/dagre) 布局\n- [FishboneLayout](/manual/layout/fishbone)：鱼骨布局\n- [ForceAtlas2Layout](/manual/layout/force-atlas2-layout)：[ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) 布局\n- [ForceLayout](/manual/layout/force-layout)：力导向布局\n- [FruchtermanLayout](/manual/layout/fruchterman-layout)：[Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) 布局\n- [GridLayout](/manual/layout/grid-layout)：网格布局\n- [MDSLayout](/manual/layout/mds-layout)：高维数据降维算法布局\n- [RadialLayout](/manual/layout/radial-layout)：径向布局\n- [RandomLayout](/manual/layout/random-layout)：随机布局\n- [SnakeLayout](/manual/layout/snake)：蛇形布局\n- [CompactBoxLayout](/manual/layout/compact-box-layout): 紧凑树布局\n- [DendrogramLayout](/manual/layout/dendrogram-layout): 树状布局\n- [MindmapLayout](/manual/layout/mindmap-layout): 思维导图布局\n- [IndentedLayout](/manual/layout/indented-layout): 缩进树布局\n\n其中 `CompactBox Layout`、`Dendrogram Layout`、`Mindmap Layout`、`Indented Layout` 是树布局的一种，适用于树状结构的图。\n\n## 注册布局\n\n你可以直接使用内置布局，如果想要使用其他布局，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## 配置布局\n\n通过 `layout` 配置项可以指定图的布局算法，例如：\n\n```typescript\n{\n  layout: {\n    // 指定要使用的布局算法\n    type: 'force',\n    // 布局算法的配置项\n    gravity: 10\n    // ...\n  }\n}\n```\n\n也可在图实例化之后使用 `graph.setLayout` 来更新布局配置。\n\n5.1 开始，布局文档中的通用字段已与 `@antvis/layout` 对齐。除了各布局自己的算法参数外，也建议同时关注 `width`、`height`、`center`、`enableWorker`、`node`、`edge` 等公共配置。\n\n## 布局加速\n\nG6 对一些布局算法提供了加速版本，包括：在 Web Worker 中执行布局算法、提供 [WASM](https://webassembly.org/) 版本的布局算法、GPU 加速的布局算法等。可按照下列方式使用：\n\n### 在 Web Worker 中执行布局算法\n\n除树布局外，G6 的所有内置布局算法都支持在 Web Worker 中执行。只需将 `enableWorker` 设置为 `true` 即可：\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### 使用 WASM 版本布局算法\n\n目前支持 WASM 版本的布局算法有：`Fruchterman Layout` `ForceAtlas Layout` `Force Layout` `Dagre Layout`。\n\n首先安装 `@antv/layout-wasm`：\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\n初始化线程：\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... 其他配置\n  },\n});\n```\n\n### 使用 GPU 加速布局\n\n目前支持 GPU 加速的布局算法有：`Fruchterman Layout` `GForce Layout`。\n\n首先安装 `@antv/layout-gpu`：\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他配置\n  },\n});\n```\n\n## 执行布局\n\n通常，在调用 `graph.render()` 后，G6 会自动执行布局算法。\n\n如果需要手动执行布局算法，G6 提供了以下 API：\n\n- [layout](/api/layout#graphlayoutlayoutoptions)：执行布局算法\n- [setLayout](/api/layout#graphsetlayoutlayout)：设置布局算法\n- [stopLayout](/api/layout#graphstoplayout)：停止布局算法\n\n## 自定义布局\n\n如果内置布局算法无法满足需求，可以自定义布局算法，具体请参考[自定义布局](/manual/layout/custom-layout)。\n\n如果你正在从 G6 `5.0` 的布局配置迁移到 `5.1`，可继续阅读 [从 5.0 升级到 5.1（布局）](/manual/whats-new/upgrade-to-5-1)。\n","packages/site/docs/manual/plugin/Background.en.md":"---\ntitle: Background\norder: 1\n---\n\n## Overview\n\nSupport setting a background image for the canvas to make the canvas more hierarchical and narrative.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Setting a unified brand background color or image for charts\n- Distinguishing different functional areas through the background\n- Enhancing the visual hierarchy and aesthetics of charts\n\n## Basic Usage\n\nBelow is a simple example of initializing the Background plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // Specify an identifier for the plugin for dynamic updates\n      backgroundColor: '#f0f2f5', // Set background color\n      backgroundImage: 'url(https://example.com/bg.png)', // Set background image\n    },\n  ],\n});\n```\n\n## Configuration Options\n\nThe configuration options for the Background plugin inherit all CSS style properties ([CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)), so you can use any valid CSS property to configure the background. Here are some common configurations:\n\n| Property           | Description                   | Type   | Default Value     | Required |\n| ------------------ | ----------------------------- | ------ | ----------------- | -------- |\n| type               | Plugin type                   | string | `background`      | ✓        |\n| key                | Unique identifier for updates | string | -                 |          |\n| width              | Background width              | string | `100%`            |          |\n| height             | Background height             | string | `100%`            |          |\n| backgroundColor    | Background color              | string | -                 |          |\n| backgroundImage    | Background image              | string | -                 |          |\n| backgroundSize     | Background size               | string | `cover`           |          |\n| backgroundPosition | Background position           | string | -                 |          |\n| backgroundRepeat   | Background repeat             | string | -                 |          |\n| opacity            | Background opacity            | string | -                 |          |\n| transition         | Transition animation          | string | `background 0.5s` |          |\n| zIndex             | Stacking order                | string | -1                |          |\n\n> Note: The `zIndex` is set to -1 by default to prevent the background from covering other plugin DOM elements, such as grid lines.\n\n## Code Examples\n\n### Basic Background Color\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Using a Background Image\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Gradient Background\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Updating the Background\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// Subsequent updates\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## FAQs\n\n### 1. Background conflicts with other plugins?\n\nBy default, the `zIndex` of the background plugin is set to `-1` to ensure it is below other elements. If there are still conflicts, you can adjust the `zIndex` value:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // Lower z-index to avoid conflicts\n    },\n  ],\n});\n```\n","packages/site/docs/manual/plugin/Background.zh.md":"---\ntitle: 背景 Background\norder: 1\n---\n\n## 概述\n\n支持为图画布设置一个背景图片，让画布更有层次感、叙事性。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 为图表设置统一的品牌背景色或图片\n- 通过背景区分不同的功能区域\n- 增强图表的视觉层次感和美观度\n\n## 基本用法\n\n以下是一个简单的 Background 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // 为插件指定标识符，方便动态更新\n      backgroundColor: '#f0f2f5', // 设置背景色\n      backgroundImage: 'url(https://example.com/bg.png)', // 设置背景图\n    },\n  ],\n});\n```\n\n## 配置项\n\nBackground 插件的配置项继承了所有 CSS 样式属性（[CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration)），因此你可以使用任何合法的 CSS 属性来配置背景。以下是一些常用配置：\n\n| 属性               | 描述                         | 类型   | 默认值            | 必选 |\n| ------------------ | ---------------------------- | ------ | ----------------- | ---- |\n| type               | 插件类型                     | string | `background`      | ✓    |\n| key                | 插件唯一标识符，用于后续更新 | string | -                 |      |\n| width              | 背景宽度                     | string | `100%`            |      |\n| height             | 背景高度                     | string | `100%`            |      |\n| backgroundColor    | 背景颜色                     | string | -                 |      |\n| backgroundImage    | 背景图片                     | string | -                 |      |\n| backgroundSize     | 背景尺寸                     | string | `cover`           |      |\n| backgroundPosition | 背景位置                     | string | -                 |      |\n| backgroundRepeat   | 背景重复方式                 | string | -                 |      |\n| opacity            | 背景透明度                   | string | -                 |      |\n| transition         | 过渡动画                     | string | `background 0.5s` |      |\n| zIndex             | 层叠顺序                     | string | -1                |      |\n\n> 注意：`zIndex` 默认为 -1，这是为了避免背景覆盖其他插件的 DOM 元素，如网格线。\n\n## 代码示例\n\n### 基础背景色\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 使用背景图片\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 渐变背景\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新背景\n\n```js\n// 初始化时配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// 后续更新\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## 常见问题\n\n### 1. 背景与其他插件冲突？\n\n默认情况下，背景插件的 `zIndex` 设为 `-1`，以确保它位于其他元素之下。如果仍有冲突，可以调整 `zIndex` 值：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // 降低 z-index 避免冲突\n    },\n  ],\n});\n```\n","packages/site/docs/manual/plugin/BubbleSets.en.md":"---\ntitle: BubbleSets\norder: 2\n---\n\n## Overview\n\nThe BubbleSets plugin represents sets and their relationships by creating bubble shapes, helping users intuitively understand logical relationships such as intersections and unions between sets. It is a tool to enhance data visualization effects, especially suitable for displaying complex data set relationships.\n\n## Use Cases\n\nThe BubbleSets plugin is mainly suitable for the following scenarios:\n\n- Displaying relationships between sets (e.g., intersections, unions)\n- Enhancing the expressive ability of data visualization\n- Identifying specific sets of nodes or edges in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the BubbleSets plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // List of node IDs to be enclosed\n      label: true, // Whether to display labels\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## Configuration Options\n\n| Property                 | Description                                                                              | Type                                                           | Default Value | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| type                     | Plugin type                                                                              | string                                                         | `bubble-sets` | ✓        |\n| key                      | Unique identifier for the plugin for subsequent updates                                  | string                                                         | -             |          |\n| members                  | Member elements, including nodes and edges, [example](#members)                          | string[]                                                       | -             | ✓        |\n| avoidMembers             | Elements to avoid, not included when drawing contours (currently supports setting nodes) | string[]                                                       | -             |          |\n| label                    | Whether to display labels                                                                | boolean                                                        | true          |          |\n| labelPlacement           | Label position                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |          |\n| labelBackground          | Whether to display background                                                            | boolean                                                        | false         |          |\n| labelPadding             | Label padding                                                                            | number \\| number[]                                             | 0             |          |\n| labelCloseToPath         | Whether the label is close to the contour, [example](#labelclosetopath)                  | boolean                                                        | true          |          |\n| labelAutoRotate          | Whether the label rotates with the contour, [example](#labelautorotate)                  | boolean                                                        | true          |          |\n| labelOffsetX             | Label x-axis offset                                                                      | number                                                         | 0             |          |\n| labelOffsetY             | Label y-axis offset                                                                      | number                                                         | 0             |          |\n| labelMaxWidth            | Maximum width of the text, automatically ellipsized if exceeded                          | number                                                         | -             |          |\n| maxRoutingIterations     | Maximum number of iterations for calculating paths between members                       | number                                                         | 100           |          |\n| maxMarchingIterations    | Maximum number of iterations for calculating contours                                    | number                                                         | 20            |          |\n| pixelGroup               | Number of pixels per potential area group, used to improve speed                         | number                                                         | 4             |          |\n| edgeR0                   | Edge radius parameter R0                                                                 | number                                                         | -             |          |\n| edgeR1                   | Edge radius parameter R1                                                                 | number                                                         | -             |          |\n| nodeR0                   | Node radius parameter R0                                                                 | number                                                         | -             |          |\n| nodeR1                   | Node radius parameter R1                                                                 | number                                                         | -             |          |\n| morphBuffer              | Morph buffer size                                                                        | number                                                         |               |          |\n| threshold                | Threshold                                                                                | number                                                         | -             |          |\n| memberInfluenceFactor    | Member influence factor                                                                  | number                                                         | -             |          |\n| edgeInfluenceFactor      | Edge influence factor                                                                    | number                                                         | -             |          |\n| nonMemberInfluenceFactor | Non-member influence factor                                                              | number                                                         | -             |          |\n| virtualEdges             | Whether to use virtual edges                                                             | boolean                                                        | -             |          |\n\n### members\n\nMember elements, including nodes and edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\nExample: Do not let the label stick to the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\nExample: Do not let the label rotate with the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Usage Examples\n\n### Basic BubbleSets\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom BubbleSets Style\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visualization effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/BubbleSets.zh.md":"---\ntitle: 气泡集 BubbleSets\norder: 2\n---\n\n## 概述\n\nBubbleSets 插件通过创建气泡形状来表示集合及其关系，帮助用户直观地理解集合间的交集、并集等逻辑关系。它是一种增强数据可视化效果的工具，特别适用于展示复杂的数据集合关系。\n\n## 使用场景\n\nBubbleSets 插件主要适用于以下场景：\n\n- 展示集合间的关系（如交集、并集）\n- 增强数据可视化的表达能力\n- 在复杂网络图中标识特定节点或边的集合\n\n## 基本用法\n\n以下是一个简单的 BubbleSets 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // 需要包裹的节点 ID 列表\n      label: true, // 是否显示标签\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## 配置项\n\n| 属性                     | 描述                                                             | 类型                                                           | 默认值        | 必选 |\n| ------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | ---- |\n| type                     | 插件类型                                                         | string                                                         | `bubble-sets` | ✓    |\n| key                      | 插件唯一标识符，用于后续更新                                     | string                                                         | -             |      |\n| members                  | 成员元素，包括节点和边，[示例](#members)                         | string[]                                                       | -             | ✓    |\n| avoidMembers             | 需要避开的元素，在绘制轮廓时不会包含这些元素（目前支持设置节点） | string[]                                                       | -             |      |\n| label                    | 是否显示标签                                                     | boolean                                                        | true          |      |\n| labelPlacement           | 标签位置                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |      |\n| labelBackground          | 是否显示背景                                                     | boolean                                                        | false         |      |\n| labelPadding             | 标签内边距                                                       | number \\| number[]                                             | 0             |      |\n| labelCloseToPath         | 标签是否贴合轮廓，[示例](#labelclosetopath)                      | boolean                                                        | true          |      |\n| labelAutoRotate          | 标签是否跟随轮廓旋转，[示例](#labelautorotate)                   | boolean                                                        | true          |      |\n| labelOffsetX             | 标签 x 轴偏移量                                                  | number                                                         | 0             |      |\n| labelOffsetY             | 标签 y 轴偏移量                                                  | number                                                         | 0             |      |\n| labelMaxWidth            | 文本的最大宽度，超出会自动省略                                   | number                                                         | -             |      |\n| maxRoutingIterations     | 计算成员之间路径的最大迭代次数                                   | number                                                         | 100           |      |\n| maxMarchingIterations    | 计算轮廓的最大迭代次数                                           | number                                                         | 20            |      |\n| pixelGroup               | 每个潜在区域组的像素数，用于提高速度                             | number                                                         | 4             |      |\n| edgeR0                   | 边的半径参数 R0                                                  | number                                                         | -             |      |\n| edgeR1                   | 边的半径参数 R1                                                  | number                                                         | -             |      |\n| nodeR0                   | 节点的半径参数 R0                                                | number                                                         | -             |      |\n| nodeR1                   | 节点的半径参数 R1                                                | number                                                         | -             |      |\n| morphBuffer              | 形态缓冲区大小                                                   | number                                                         |               |      |\n| threshold                | 阈值                                                             | number                                                         | -             |      |\n| memberInfluenceFactor    | 成员影响因子                                                     | number                                                         | -             |      |\n| edgeInfluenceFactor      | 边影响因子                                                       | number                                                         | -             |      |\n| nonMemberInfluenceFactor | 非成员影响因子                                                   | number                                                         | -             |      |\n| virtualEdges             | 是否使用虚拟边                                                   | boolean                                                        | -             |      |\n\n### members\n\n成员元素，包括节点和边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\n示例：不让 label 贴合轮廓\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\n示例：不让label标签跟随轮廓旋转\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 使用示例\n\n### 基础 BubbleSets\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义 BubbleSets 样式\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Contextmenu.en.md":"---\ntitle: Contextmenu\norder: 3\n---\n\n## Overview\n\nThe context menu, also known as the right-click menu, is a menu that appears when a user clicks on a specific area. It supports triggering custom events before and after clicking. Through the context menu, specific element operations can be integrated, making it convenient to control a particular item when needed.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Various interactions with elements: viewing nodes, viewing edges, deleting nodes, etc.\n\n## Basic Usage\n\nBelow is a simple example of initializing the Contextmenu plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // Enable right-click menu only on nodes, by default all elements are enabled\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: 'View Details', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('Display node details');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property       | Description                                                                                                               | Type                                                                              | Default Value    | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | -------- |\n| className      | Additional class name for the menu DOM                                                                                    | string                                                                            | `g6-contextmenu` |          |\n| trigger        | How to trigger the right-click menu: `contextmenu` for right-click, `click` for click                                     | `click` \\| `contextmenu`                                                          | `contextmenu`    |          |\n| offset         | Offset of the menu display in X and Y directions                                                                          | [number, number]                                                                  | [4, 4]           |          |\n| onClick        | Callback method triggered after the menu is clicked, [example](#onclick)                                                  | (value: string, target: HTMLElement, current: Element) => void                    | -                |          |\n| getItems       | Returns the list of menu items, supports `Promise` type return value. It is a shortcut configuration for `getContent`     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |          |\n| getContent     | Returns the content of the menu, supports `Promise` type return value, can also use `getItems` for shortcut configuration | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |          |\n| loadingContent | Menu content used when `getContent` returns a `Promise`                                                                   | HTMLElement \\| string                                                             | -                |          |\n| enable         | Whether it is available, determines whether the right-click menu is supported by parameters, by default all are available | boolean \\| (event: IElementEvent) => boolean                                      | true             |          |\n\n### Item\n\nEach menu item (Item) contains the following properties:\n\n| Property | Description                          | Type     | Required |\n| -------- | ------------------------------------ | -------- | -------- |\n| name     | Name displayed for the menu item     | `string` | ✓        |\n| value    | Value corresponding to the menu item | `string` | ✓        |\n\n### onClick\n\nThis function is triggered after clicking a menu item, and the function has three parameters:\n\n- value: Corresponds to the value of the menu item\n- target: The DOM node of the menu item container\n- current: The element that triggered the menu item, for example, if it is a node, you can use `current` to get the node information (id), or to modify the element\n\n## Code Examples\n\n### Basic Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + value + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: 'View Details', value: 'detail' },\n          { name: 'Delete', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### Edge Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: 'Change Start Point', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('Execute change start point operation here');\n      },\n      // Enable right-click menu only on edges\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### Asynchronous Loading of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // Enable right-click menu only on nodes\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Dynamic Control of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: 'Delete Node',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: 'Move Edge',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Contextmenu.zh.md":"---\ntitle: 上下文菜单 Contextmenu\norder: 3\n---\n\n## 概述\n\n上下文菜单（Contextmenu），也被称为右键菜单，是当用户在某个特定区域上点击后出现的一个菜单。支持在点击前后，触发自定义事件。通过上下文菜单，可以将一些具体元素的操作集成在其中，方便对某一项来进行需要时的单独控制。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 元素的各种交互：查看节点、查看边、删除节点等等交互操作\n\n## 基本用法\n\n以下是一个简单的 Contextmenu 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // 只在节点上开启右键菜单，默认全部元素都开启\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: '查看详情', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('展示节点详情');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                            | 类型                                                                              | 默认值           | 必选 |\n| -------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | ---- |\n| className      | 给菜单的 DOM 追加的类名                                                         | string                                                                            | `g6-contextmenu` |      |\n| trigger        | 如何触发右键菜单：`contextmenu` 表示右键触发，`click` 表示点击触发              | `click` \\| `contextmenu`                                                          | `contextmenu`    |      |\n| offset         | 菜单显式 X、Y 方向的偏移量                                                      | [number, number]                                                                  | [4, 4]           |      |\n| onClick        | 当菜单被点击后，触发的回调方法，[示例](#onclick)                                | (value: string, target: HTMLElement, current: Element) => void                    | -                |      |\n| getItems       | 返回菜单的项目列表，支持 `Promise` 类型的返回值。是 `getContent` 的快捷配置     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |      |\n| getContent     | 返回菜单的内容，支持 `Promise` 类型的返回值，也可以使用 `getItems` 进行快捷配置 | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |      |\n| loadingContent | 当 `getContent` 返回一个 `Promise` 时，使用的菜单内容                           | HTMLElement \\| string                                                             | -                |      |\n| enable         | 是否可用，通过参数判断是否支持右键菜单，默认是全部可用                          | boolean \\| (event: IElementEvent) => boolean                                      | true             |      |\n\n### Item\n\n每个菜单项目 (Item) 包含以下属性：\n\n| 属性  | 描述             | 类型     | 必选 |\n| ----- | ---------------- | -------- | ---- |\n| name  | 菜单项显示的名字 | `string` | ✓    |\n| value | 菜单项对应的值   | `string` | ✓    |\n\n### onClick\n\n点击菜单项后会触发该函数，函数有三个参数：\n\n- value: 对应菜单项的 value\n- target: 对应菜单项容器的 dom 节点\n- current: 对应触发菜单项的元素，例如是节点则可以通过 `current` 来获取到节点的信息(id)等，或者来对元素进行修改\n\n## 代码示例\n\n### 基础右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '查看详情', value: 'detail' },\n          { name: '删除', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### 边的右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: '变更起点', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('这里执行变更起点操作');\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### 异步加载菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 动态控制菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: '删除节点',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: '移动边',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/EdgeBundling.en.md":"---\ntitle: EdgeBundling\norder: 4\n---\n\n## Overview\n\nEdge bundling is a graph visualization technique used to reduce visual clutter in complex network graphs and to reveal high-level patterns and structures in the graph. Its purpose is to bundle adjacent edges together.\n\nThe edge bundling plugin provided in G6 is based on the implementation of the [FEDB (Force-Directed Edge Bundling for Graph Visualization)](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf) paper: modeling edges as flexible springs that can attract each other and bundling them through a self-organizing process.\n\n## Use Cases\n\nThe edge bundling plugin is mainly suitable for the following scenarios:\n\n- Reducing visual clutter in complex network graphs\n- Revealing high-level patterns and structures in the graph\n- Improving the readability and aesthetics of large-scale graph data\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeBundling plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property        | Description                                                                                                                                                                                            | Type   | Default Value   | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | --------------- | -------- |\n| type            | Plugin type, used to identify the plugin as an edge bundling plugin                                                                                                                                    | string | `edge-bundling` | ✓        |\n| key             | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                      | string | -               |          |\n| bundleThreshold | Edge compatibility threshold, determines which edges should be bundled together, the larger the value, the fewer edges are bundled, [example](#bundlethreshold)                                        | number | 0.6             |          |\n| cycles          | Number of simulation cycles, controls the number of execution rounds of the edge bundling simulation                                                                                                   | number | 6               |          |\n| divisions       | Initial number of cut points, in subsequent cycles, the number of cut points will gradually increase according to divRate, affecting the degree of edge subdivision                                    | number | 1               |          |\n| divRate         | Growth rate of cut points, determines the growth rate of cut points in each cycle                                                                                                                      | number | 2               |          |\n| iterations      | Specifies the number of iterations executed in the first cycle, in subsequent cycles, the number of iterations will gradually decrease according to iterRate, affecting the accuracy of the simulation | number | 90              |          |\n| iterRate        | Iteration decrement rate, controls the reduction ratio of iterations in each cycle                                                                                                                     | number | 2/3             |          |\n| K               | Edge strength, affects the attraction and repulsion between edges, [example](#k)                                                                                                                       | number | 0.1             |          |\n| lambda          | Initial step size, in subsequent cycles, the step size will double increment, affecting the magnitude of node movement during edge bundling                                                            | number | 0.1             |          |\n\n### bundleThreshold\n\nEdge compatibility threshold, determines which edges should be bundled together. The larger the value, the fewer edges are bundled, and vice versa.\n\n- A lower bundleThreshold value (e.g., 0.4) will cause more edges to be bundled together, forming a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // Lower edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge compatibility threshold\">\n\n- A higher bundleThreshold value (e.g., 0.8) will cause fewer edges to be bundled together, maintaining more independent edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge compatibility threshold\">\n\n### K\n\nEdge strength, affects the attraction and repulsion between edges. A higher K value will make the attraction between edges stronger, resulting in a tighter bundling effect.\n\n- A lower K value (e.g., 0.05) will make the attraction between edges weaker, resulting in a weaker bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // Lower edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge strength\">\n\n- A higher K value (e.g., 0.2) will make the attraction between edges stronger, resulting in a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // Higher edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge strength\">\n\n## Code Examples\n\n### Basic Edge Bundling\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['edge-bundling'],\n});\n```\n\n### Custom Styles\n\nYou can customize the parameters of edge bundling as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n      cycles: 8, // More simulation cycles\n      K: 0.2, // Stronger edge strength\n    },\n  ],\n});\n```\n\n### Dynamic Update of Edge Bundling\n\nUse the key identifier to dynamically update edge bundling properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// Subsequent dynamic update\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // Update edge compatibility threshold\n  cycles: 10, // Update number of simulation cycles\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/EdgeBundling.zh.md":"---\ntitle: 边绑定 EdgeBundling\norder: 4\n---\n\n## 概述\n\n边绑定（Edge Bundling）是一种图可视化技术，用于减少复杂网络图中的视觉混乱，并展示图中的高级别模式和结构。其目的是将相邻的边捆绑在一起。\n\nG6 中提供的边绑定插件是基于 [FEDB（Force-Directed Edge Bundling for Graph Visualization）](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf)论文的实现：将边建模为可以相互吸引的柔性弹簧，通过自组织的方式进行捆绑。\n\n## 使用场景\n\n边绑定插件主要适用于以下场景：\n\n- 减少复杂网络图中的视觉混乱\n- 揭示图中的高级别模式和结构\n- 提高大规模图数据的可读性和美观性\n\n## 基本用法\n\n以下是一个简单的 EdgeBundling 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性            | 描述                                                                                               | 类型   | 默认值          | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------- | ------ | --------------- | ---- |\n| type            | 插件类型，用于标识该插件为边捆绑插件                                                               | string | `edge-bundling` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                   | string | -               |      |\n| bundleThreshold | 边兼容性阈值，该值决定了哪些边应该被绑定在一起，值越大，绑定的边越少，[示例](#bundlethreshold)     | number | 0.6             |      |\n| cycles          | 模拟周期数，控制边捆绑模拟的执行轮数                                                               | number | 6               |      |\n| divisions       | 初始切割点数，在后续的周期中，切割点数将根据 divRate 逐步递增，影响边的细分程度                    | number | 1               |      |\n| divRate         | 切割点数增长率，决定了每一轮周期中切割点数的增长幅度                                               | number | 2               |      |\n| iterations      | 指定在第一个周期中执行的迭代次数，在后续的周期中，迭代次数将根据 iterRate 逐步递减，影响模拟的精度 | number | 90              |      |\n| iterRate        | 迭代次数递减率，控制每一轮周期中迭代次数的减少比例                                                 | number | 2\\/3            |      |\n| K               | 边的强度，影响边之间的吸引力和排斥力，[示例](#k)                                                   | number | 0.1             |      |\n| lambda          | 初始步长，在后续的周期中，步长将双倍递增，影响边捆绑过程中节点移动的幅度                           | number | 0.1             |      |\n\n### bundleThreshold\n\n边兼容性阈值，该值决定了哪些边应该被绑定在一起。值越大，绑定的边越少，反之则绑定的边越多。\n\n- 较低的 bundleThreshold 值（如 0.4）会使更多的边被绑定在一起，形成更明显的捆绑效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // 较低的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边兼容性阈值\">\n\n- 较高的 bundleThreshold 值（如 0.8）会使较少的边被绑定在一起，保持更多的独立边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 较高的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边兼容性阈值\">\n\n### K\n\n边的强度，影响边之间的吸引力和排斥力。较高的 K 值会使边之间的吸引力更强，从而形成更紧密的捆绑效果。\n\n- 较低的 K 值（如 0.05）会使边之间的吸引力较弱，边的捆绑效果较弱。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // 较低的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边强度\">\n\n- 较高的 K 值（如 0.2）会使边之间的吸引力较强，边的捆绑效果更明显。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // 较高的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边强度\">\n\n## 代码示例\n\n### 基础边绑定\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['edge-bundling'],\n});\n```\n\n### 自定义样式\n\n您可以根据需要自定义边绑定的参数：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 更高的边兼容性阈值\n      cycles: 8, // 更多模拟周期\n      K: 0.2, // 更强的边强度\n    },\n  ],\n});\n```\n\n### 动态更新边绑定\n\n使用 key 标识符可以在运行时动态更新边绑定属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // 更新边兼容性阈值\n  cycles: 10, // 更新模拟周期数\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/EdgeFilterLens.en.md":"---\ntitle: EdgeFilterLens\norder: 5\n---\n\n## Overview\n\nThe Edge Filter Lens plugin allows you to keep the edges of interest within the lens range, while other edges will not be displayed in that range. This is an important visualization exploration tool that can help users focus on edge relationships in specific areas.\n\n## Use Cases\n\n- Need to focus on viewing edge relationships in local areas\n- Highlight connections between specific nodes in complex networks\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeFilterLens plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // Follow mouse movement\n      r: 60, // Set lens radius\n      nodeType: 'both', // Edge display condition\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                                                                                                                                                                                 | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                  | `edge-filter-lens`                          | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                                                                                                                                                                                           | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the lens:<br/>- `pointermove`: The lens always follows the mouse movement <br/>- `click`: Move the lens to the click position when clicking on the canvas <br/>- `drag`: Move the lens by dragging                                                                                                                                                                           | `pointermove` \\| `click` \\| `drag`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the lens                                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                  | 60                                          |          |\n| maxR           | Maximum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to scale the lens radius: `wheel`: Scale the lens radius by the wheel                                                                                                                                                                                                                                                                                                                | `wheel`                                                                                                                                                                 | -                                           |          |\n| nodeType       | Edge display condition:<br/> - `both`: The edge is displayed only when both the source and target nodes are in the lens <br/> - `source`: The edge is displayed only when the source node is in the lens<br/> - `target`: The edge is displayed only when the target node is in the lens <br/> - `either`: The edge is displayed as long as either the source or target node is in the lens | `both` \\| `source` \\| `target` \\| `either`                                                                                                                              | `both`                                      |          |\n| filter         | Filter out elements that are never displayed in the lens                                                                                                                                                                                                                                                                                                                                    | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                       | () => true                                  |          |\n| style          | Style of the lens, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                          | object                                                                                                                                                                  |                                             |          |\n| nodeStyle      | Style of nodes in the lens                                                                                                                                                                                                                                                                                                                                                                  | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: false }`                          |          |\n| edgeStyle      | Style of edges in the lens                                                                                                                                                                                                                                                                                                                                                                  | [EdgeStyle](/en/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/en/manual/data#边数据edgedata)) => [EdgeStyle](/en/manual/element/edge/base-edge#style))   | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                                                                                                                                                                                           | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nStyle properties of the circular lens.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#fff`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | 1             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.8           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the lens:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Edge Filter Lens](/en/examples/plugin/edge-filter-lens/#basic)\n","packages/site/docs/manual/plugin/EdgeFilterLens.zh.md":"---\ntitle: 边过滤镜 EdgeFilterLens\norder: 5\n---\n\n## 概述\n\n边过滤镜插件可以将关注的边保留在过滤镜范围内，其他边将在该范围内不显示。这是一个重要的可视化探索工具，可以帮助用户聚焦于特定区域的边关系。\n\n## 使用场景\n\n- 需要聚焦查看局部区域的边关系\n- 在复杂网络中突出显示特定节点之间的连接\n\n## 基本用法\n\n以下是一个简单的 EdgeFilterLens 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // 跟随鼠标移动\n      r: 60, // 设置透镜半径\n      nodeType: 'both', // 边的显示条件\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                                                                       | 类型                                                                                                                                                           | 默认值               | 必选 |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                                                                                   | string                                                                                                                                                         | `edge-filter-lens`   | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                                                                                           | string                                                                                                                                                         | -                    |      |\n| trigger        | 移动透镜的方式：<br/>- `pointermove`：透镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动透镜到点击位置 <br/>- `drag`：通过拖拽方式移动透镜                                                                                                                | `pointermove` \\| `click` \\| `drag`                                                                                                                             | `pointermove`        |      |\n| r              | 透镜的半径                                                                                                                                                                                                                                                 | number                                                                                                                                                         | 60                   |      |\n| maxR           | 透镜的最大半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 画布宽高最小值的一半 |      |\n| minR           | 透镜的最小半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 0                    |      |\n| scaleRBy       | 缩放透镜半径的方式：`wheel`：通过滚轮缩放透镜的半径                                                                                                                                                                                                        | `wheel`                                                                                                                                                        | -                    |      |\n| nodeType       | 边显示的条件：<br/> - `both`：只有起始节点和目标节点都在透镜中时，边才会显示 <br/> - `source`：只有起始节点在透镜中时，边才会显示<br/> - `target`：只有目标节点在透镜中时，边才会显示 <br/> - `either`：只要起始节点或目标节点有一个在透镜中时，边就会显示 | `both` \\| `source` \\| `target` \\| `either`                                                                                                                     | `both`               |      |\n| filter         | 过滤出始终不在透镜中显示的元素                                                                                                                                                                                                                             | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                              | () => true           |      |\n| style          | 透镜的样式，[配置项](#style)                                                                                                                                                                                                                               | object                                                                                                                                                         |                      |      |\n| nodeStyle      | 在透镜中节点的样式                                                                                                                                                                                                                                         | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: false }`   |      |\n| edgeStyle      | 在透镜中边的样式                                                                                                                                                                                                                                           | [EdgeStyle](/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/manual/data#边数据edgedata)) => [EdgeStyle](/manual/element/edge/base-edge#style))   | `{ label: true }`    |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                                                                                           | boolean                                                                                                                                                        | true                 |      |\n\n### style\n\n圆形透镜的样式属性。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#fff` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | 1      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.8    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义透镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [边过滤镜](/examples/plugin/edge-filter-lens/#basic)\n","packages/site/docs/manual/plugin/Fisheye.en.md":"---\ntitle: Fisheye\norder: 6\n---\n\n## Overview\n\nThe Fisheye plugin is designed for focus+context exploration scenarios. It can magnify the area of interest while ensuring that the context and the relationship between the context and the focus center are not lost. It is an important visualization exploration tool.\n\n## Use Cases\n\n- Highlight certain areas during presentations\n- Magnify details locally without losing the overall view\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fisheye plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // Move fisheye by dragging\n      d: 1.5, // Set distortion factor\n      r: 120, // Set fisheye radius\n      showDPercent: true, // Show distortion degree\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                   | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                   | string                                                                                                                                                                  | `fisheye`                                   | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                             | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the fisheye:<br/>- `pointermove`: The fisheye always follows the mouse movement <br/>- `click`: Move the fisheye to the click position when clicking on the canvas <br/>- `drag`: Move the fisheye by dragging | `pointermove` \\| `drag` \\| `click`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the fisheye                                                                                                                                                                                                         | number                                                                                                                                                                  | 120                                         |          |\n| maxR           | Maximum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | 0                                           |          |\n| d              | Distortion factor                                                                                                                                                                                                             | number                                                                                                                                                                  | 1.5                                         |          |\n| maxD           | Maximum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 5                                           |          |\n| minD           | Minimum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to adjust the fisheye radius:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                                     | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| scaleDBy       | Method to adjust the fisheye distortion factor:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                          | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| showDPercent   | Whether to show the distortion factor value in the fisheye                                                                                                                                                                    | boolean                                                                                                                                                                 | true                                        |          |\n| style          | Style of the fisheye, [configuration options](#style)                                                                                                                                                                         | object                                                                                                                                                                  | -                                           |          |\n| nodeStyle      | Style of nodes in the fisheye                                                                                                                                                                                                 | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                             | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nCircular style properties for configuring the appearance of the fisheye.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#ccc`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | -             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.1           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n### Zoom Control\n\n`scaleRBy` and `scaleDBy` can be used to control the adjustment method of the fisheye's radius and distortion factor respectively:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // Adjust radius by wheel\n      scaleRBy: 'wheel',\n      // Adjust distortion factor by dragging\n      scaleDBy: 'drag',\n      // Set range for radius and distortion factor\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\nNote: When `trigger`, `scaleRBy`, and `scaleDBy` are all set to `'drag'`, the priority order is `trigger` > `scaleRBy` > `scaleDBy`, and only the highest priority configuration item will bind the drag event. Similarly, if `scaleRBy` and `scaleDBy` are both set to `'wheel'`, only `scaleRBy` will bind the wheel event.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the fisheye:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Fisheye.zh.md":"---\ntitle: 鱼眼放大镜 Fisheye\norder: 6\n---\n\n## 概述\n\n鱼眼放大镜插件是为 focus+context 的探索场景设计的，它能够在放大关注区域的同时，保证上下文以及上下文与关注中心的关系不丢失，是一个重要的可视化探索工具。\n\n## 使用场景\n\n- 在演示过程中需要突出展示某些区域内容\n- 需要局部放大查看细节时，同时又不想失去整体视图\n\n## 基本用法\n\n以下是一个简单的 Fisheye 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // 通过拖拽移动鱼眼\n      d: 1.5, // 设置畸变因子\n      r: 120, // 设置鱼眼半径\n      showDPercent: true, // 显示畸变程度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                          | 类型                                                                                                                                                           | 默认值                 | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                      | string                                                                                                                                                         | `fisheye`              | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                              | string                                                                                                                                                         | -                      |      |\n| trigger        | 用于控制鱼眼放大镜的移动方式，支持以下三种配置：<br/>- `pointermove`：鱼眼放大镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动鱼眼放大镜到点击位置 <br/>- `drag`：通过拖拽方式移动鱼眼放大镜 | `pointermove` \\| `drag` \\| `click`                                                                                                                             | `pointermove`          |      |\n| r              | 鱼眼放大镜半径                                                                                                                                                                                | number                                                                                                                                                         | 120                    |      |\n| maxR           | 鱼眼放大镜可调整的最大半径                                                                                                                                                                    | number                                                                                                                                                         | 画布宽高的最小值的一半 |      |\n| minR           | 鱼眼放大镜可调整的最小半径                                                                                                                                                                    | number                                                                                                                                                         | 0                      |      |\n| d              | 畸变因子                                                                                                                                                                                      | number                                                                                                                                                         | 1.5                    |      |\n| maxD           | 鱼眼放大镜可调整的最大畸变因子                                                                                                                                                                | number                                                                                                                                                         | 5                      |      |\n| minD           | 鱼眼放大镜可调整的最小畸变因子                                                                                                                                                                | number                                                                                                                                                         | 0                      |      |\n| scaleRBy       | 调整鱼眼放大镜范围半径的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| scaleDBy       | 调整鱼眼放大镜畸变因子的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| showDPercent   | 是否在鱼眼放大镜中显示畸变因子数值                                                                                                                                                            | boolean                                                                                                                                                        | true                   |      |\n| style          | 鱼眼放大镜样式，[配置项](#style)                                                                                                                                                              | object                                                                                                                                                         | -                      |      |\n| nodeStyle      | 在鱼眼放大镜中的节点样式                                                                                                                                                                      | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: true }`      |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                              | boolean                                                                                                                                                        | true                   |      |\n\n### style\n\n圆形样式属性，用于配置鱼眼放大镜的外观。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#ccc` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | -      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.1    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n### 缩放控制\n\n通过 `scaleRBy` 和 `scaleDBy` 可以分别控制鱼眼放大镜的半径和畸变因子的调整方式：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // 通过滚轮调整半径\n      scaleRBy: 'wheel',\n      // 通过拖拽调整畸变因子\n      scaleDBy: 'drag',\n      // 设置半径和畸变因子的范围\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\n注意：当 `trigger`、`scaleRBy` 和 `scaleDBy` 同时设置为 `'drag'` 时，优先级顺序为 `trigger` > `scaleRBy` > `scaleDBy`，只会为优先级最高的配置项绑定拖拽事件。同理，如果 `scaleRBy` 和 `scaleDBy` 同时设置为 `'wheel'`，只会为 `scaleRBy` 绑定滚轮事件。\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### 自定义样式\n\n可以自定义鱼眼放大镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Fullscreen.en.md":"---\ntitle: Fullscreen\norder: 7\n---\n\n## Overview\n\nThe Fullscreen plugin allows users to expand the graph visualization content to the entire screen, providing a broader view and a better immersive experience.\n\n## Use Cases\n\nThe Fullscreen plugin is mainly suitable for the following scenarios:\n\n- Provide a broader view for viewing complex graph data\n- Enhance immersive experience, focusing on graph visualization content\n- Display graph data in presentations or reports\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fullscreen plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n      onEnter: () => {\n        console.log('Entered fullscreen mode');\n      },\n      onExit: () => {\n        console.log('Exited fullscreen mode');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property | Description                                                                                                      | Type                                 | Default Value | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ------------- | -------- |\n| type     | Plugin type                                                                                                      | string                               | `fullscreen`  | ✓        |\n| key      | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                | string                               | -             |          |\n| autoFit  | Whether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen | boolean                              | true          |          |\n| trigger  | Method to trigger fullscreen, [example](#trigger)                                                                | { request?: string; exit?: string; } | -             |          |\n| onEnter  | Callback after entering fullscreen                                                                               | () => void                           | -             |          |\n| onExit   | Callback after exiting fullscreen                                                                                | () => void                           | -             |          |\n\n### trigger\n\nThe trigger property is used to control the method of triggering fullscreen. It supports two configuration methods:\n\n#### Shortcut Key Configuration\n\nUse keyboard shortcuts to trigger fullscreen and exit fullscreen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n    },\n  ],\n});\n```\n\n#### Custom Trigger\n\nControl fullscreen by calling the request and exit methods.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\nWhether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen.\n\n- When set to true, the canvas will automatically resize to fit the entire screen.\n- When set to false, the canvas size remains unchanged.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\nThis method is used to enter fullscreen mode programmatically. It can be called on the plugin instance to expand the graph visualization to the entire screen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\nThis method is used to exit fullscreen mode programmatically. It can be called on the plugin instance to revert the graph visualization back to its original size.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Fullscreen.zh.md":"---\ntitle: 全屏展示 Fullscreen\norder: 7\n---\n\n## 概述\n\n全屏展示插件允许用户将图可视化内容扩展到整个屏幕，提供更广阔的视图和更好的沉浸式体验。\n\n## 使用场景\n\n全屏展示插件主要适用于以下场景：\n\n- 提供更广阔的视图，便于查看复杂图数据\n- 增强沉浸式体验，专注于图可视化内容\n- 在演示或报告中展示图数据\n\n## 基本用法\n\n以下是一个简单的 Fullscreen 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n      onEnter: () => {\n        console.log('进入全屏模式');\n      },\n      onExit: () => {\n        console.log('退出全屏模式');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性    | 描述                                                 | 类型                                 | 默认值       | 必选 |\n| ------- | ---------------------------------------------------- | ------------------------------------ | ------------ | ---- |\n| type    | 插件类型                                             | string                               | `fullscreen` | ✓    |\n| key     | 插件的唯一标识，可用于获取插件实例或更新插件选项     | string                               | -            |      |\n| autoFit | 是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸 | boolean                              | true         |      |\n| trigger | 触发全屏的方式，[示例](#trigger)                     | { request?: string; exit?: string; } | -            |      |\n| onEnter | 进入全屏后的回调                                     | () => void                           | -            |      |\n| onExit  | 退出全屏后的回调                                     | () => void                           | -            |      |\n\n### trigger\n\ntrigger 属性用于控制触发全屏的方式。它支持两种配置方式：\n\n#### 快捷键配置\n\n使用键盘快捷键来触发全屏和退出全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n    },\n  ],\n});\n```\n\n#### 自定义触发\n\n通过调用 request 和 exit 方法来控制全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\n是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸。\n\n- 设置为 true 时，画布会自动调整大小以适应整个屏幕。\n- 设置为 false 时，画布大小保持不变。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\n这个方法可以让你通过代码进入全屏模式。调用插件实例上的这个方法，就能把图形内容扩展到整个屏幕。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\n这个方法可以让你通过代码退出全屏模式。调用插件实例上的这个方法，就能把图形内容恢复到原来的大小。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/GridLine.en.md":"---\ntitle: GridLine\norder: 8\n---\n\n## Overview\n\nThe GridLine plugin provides visual auxiliary lines for the canvas, helping users precisely position and align graphic elements. It is an indispensable tool in graphic drawing.\n\n## Use Cases\n\nThe GridLine plugin is mainly suitable for the following scenarios:\n\n- Assisting users in precise drawing and element alignment\n- Providing visual references to enhance spatial awareness\n- Building a structured reference system when designing and editing graphics\n\n## Basic Usage\n\nBelow is a simple example of initializing the GridLine plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // Specify a unique identifier for dynamic updates\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## Configuration Options\n\n| Property        | Description                                                                                         | Type                                              | Default     | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------- | -------- |\n| type            | Plugin type                                                                                         | string                                            | `grid-line` | ✓        |\n| key             | Unique identifier for the plugin, used to get the plugin instance or update plugin options          | string                                            | -           |          |\n| border          | Whether to display the border                                                                       | boolean                                           | true        |          |\n| borderLineWidth | Border line width                                                                                   | number                                            | 1           |          |\n| borderStroke    | Border color, see [CSS border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color) | string                                            | `#eee`      |          |\n| borderStyle     | Border style, see [CSS border-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style) | string                                            | `solid`     |          |\n| follow          | Whether to follow canvas movements                                                                  | boolean \\| {translate ?: boolean, zoom?: boolean} | false       |          |\n| lineWidth       | Grid line width                                                                                     | number \\| string                                  | 1           |          |\n| size            | Grid unit size in pixels                                                                            | number                                            | 20          |          |\n| stroke          | Grid line color                                                                                     | string                                            | `#eee`      |          |\n\n### follow\n\nThe `follow` property controls whether the grid lines follow the canvas transformations. It supports two configuration methods:\n\n1. **Boolean Configuration**: When set to `true`, the grid lines follow both canvas translation and zoom; when set to `false`, they remain static.\n\n```js\n// Enable both translation and zoom following\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **Object Configuration**: Allows more precise control over the grid line following behavior.\n\n```js\n// Follow translation only, not zoom\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // Follow translation\n        zoom: false, // Do not follow zoom\n      },\n    },\n  ],\n});\n\n// Follow zoom only, not translation\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // Do not follow translation\n        zoom: true, // Follow zoom\n      },\n    },\n  ],\n});\n```\n\nWhen grid lines follow zoom, they maintain a relative position to the canvas content, making alignment references more precise. Following translation allows the grid to move with the canvas content, enhancing the visual experience of spatial continuity.\n\n## Code Examples\n\n### Basic Grid Line\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid-line'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### Custom Style\n\nYou can customize the grid line style as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid unit\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Follow Movement\n\nEnabling the follow option allows the grid to move with the canvas, enhancing user experience:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n```\n\nTry dragging/zooming the canvas to observe the grid following effect:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamic Grid Update\n\nUse the key identifier to dynamically update grid properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// Subsequent dynamic updates\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // Update grid size\n  stroke: '#ff4d4f', // Update grid color\n});\n```\n\n## Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","packages/site/docs/manual/plugin/GridLine.zh.md":"---\ntitle: 网格线 GridLine\norder: 8\n---\n\n## 概述\n\n网格线插件为画布提供可视化辅助线，帮助用户精确定位和对齐图形元素，是图形绘制中不可或缺的辅助工具。\n\n## 使用场景\n\n网格线插件主要适用于以下场景：\n\n- 辅助用户精确绘图和元素对齐\n- 提供视觉参考，增强空间感知\n- 在设计和编辑图形时构建结构化的参考系统\n\n## 基本用法\n\n以下是一个简单的 GridLine 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // 指定唯一标识符，便于后续动态更新\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## 配置项\n\n| 属性            | 描述                                                                                                     | 类型                                               | 默认值      | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------- | ---- |\n| type            | 插件类型                                                                                                 | string                                             | `grid-line` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                         | string                                             | -           |      |\n| border          | 是否显示边框                                                                                             | boolean                                            | true        |      |\n| borderLineWidth | 边框线宽                                                                                                 | number                                             | 1           |      |\n| borderStroke    | 边框颜色，详细属性参考 [CSS border-color](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-color) | string                                             | `#eee`      |      |\n| borderStyle     | 边框样式，详细属性参考 [CSS border-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-style) | string                                             | `solid`     |      |\n| follow          | 是否跟随画布移动                                                                                         | boolean \\｜ {translate ?: boolean, zoom?: boolean} | false       |      |\n| lineWidth       | 网格线宽度                                                                                               | number \\| string                                   | 1           |      |\n| size            | 网格单元大小，单位为像素                                                                                 | number                                             | 20          |      |\n| stroke          | 网格线颜色                                                                                               | string                                             | `#eee`      |      |\n\n### follow\n\n`follow` 属性用于控制网格线是否跟随画布的变换操作。它支持两种配置方式：\n\n1. **布尔值配置**：当设置为 `true` 时，网格线会同时跟随画布的平移和缩放；设置为 `false` 时则保持静态。\n\n```js\n// 同时启用跟随平移和缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **对象配置**：可以更精细地控制网格线的跟随行为。\n\n```js\n// 仅跟随平移，不跟随缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // 跟随平移\n        zoom: false, // 不跟随缩放\n      },\n    },\n  ],\n});\n\n// 仅跟随缩放，不跟随平移\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // 不跟随平移\n        zoom: true, // 跟随缩放\n      },\n    },\n  ],\n});\n```\n\n当网格线跟随缩放时，它会保持与画布内容的相对位置关系，使得对齐参考更加精准。跟随平移则让网格随着画布内容一起移动，增强空间连续性的视觉体验。\n\n## 代码示例\n\n### 基础网格线\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid-line'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义网格线的样式：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格单元\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 跟随移动\n\n启用 follow 选项可以让网格跟随画布移动，增强用户体验：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n```\n\n试着拖拽/缩放画布，观察网格的跟随效果：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新网格\n\n使用 key 标识符可以在运行时动态更新网格属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // 更新网格大小\n  stroke: '#ff4d4f', // 更新网格颜色\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","packages/site/docs/manual/plugin/History.en.md":"---\ntitle: History\norder: 9\n---\n\n## Overview\n\nThis plugin is used to implement the **Undo** and **Redo** functions in graph editing. By recording the historical state stack of user operations, it supports backtracking or restoring operations during graph interactions. The plugin provides users with comprehensive configuration options and APIs.\n\n## Usage Scenarios\n\nThe history plugin is suitable for all scenarios involving graph editing.\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## Basic Usage\n\nAdd this plugin in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['history'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property         | Description                                                                                                                                                                                                   | Type                                                           | Default Value | Required |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| afterAddCommand  | Called after a command is added to the `Undo/Redo` queue. `revert` is `true` for undo operations and `false` for redo operations                                                                              | (cmd: [Command](#command), revert: boolean) => void            | -             |          |\n| beforeAddCommand | Called before a command is added to the `Undo/Redo` queue. If this method returns `false`, the command will not be added to the queue. `revert` is `true` for undo operations and `false` for redo operations | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -             |          |\n| executeCommand   | Callback function when executing a command                                                                                                                                                                    | (cmd: [Command](#command)) => void                             | -             |          |\n| stackSize        | Maximum length of history records to be recorded                                                                                                                                                              | number                                                         | 0 (unlimited) |          |\n\n### Parameter Type Description\n\n#### `Command`\n\n```typescript\n// Single history command\ninterface Command {\n  current: CommandData; // Current data\n  original: CommandData; // Original data\n  animation: boolean; // Whether to enable animation\n}\n// Single history command data\ninterface CommandData {\n  add: GraphData; // Added data\n  update: GraphData; // Updated data\n  remove: GraphData; // Removed data\n}\n// Graph data\ninterface GraphData {\n  nodes?: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data\n  combos?: ComboData[]; // Combo data\n}\n```\n\n## API\n\nThe history plugin provides the following APIs for users to use as needed. For how to call plugin methods, please refer to the [Plugin Overview Document](/en/manual/plugin/overview#calling-plugin-methods)\n\n### History.canRedo()\n\nDetermines whether a **redo** operation can be performed. If there are records in the redo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanRedo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('Redo operation can be performed');\n} else {\n  console.log('Redo stack is empty, cannot redo');\n}\n```\n\n### History.canUndo()\n\nDetermines whether an **undo** operation can be performed. If there are records in the undo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanUndo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('Undo operation can be performed');\n} else {\n  console.log('Undo stack is empty, cannot undo');\n}\n```\n\n### History.clear()\n\nClears the history records, including the undo and redo stacks.\n\n```typescript\nclear(): void;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('History records cleared');\n```\n\n### History.on()\n\nListens to history events, allowing users to execute custom logic when specific events occur.\n\n```typescript\non(event: Loosen<HistoryEvent>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\nParameter Type Description:\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // When a command is undone\n    REDO = 'redo', // When a command is redone\n    CANCEL = 'cancel', // When a command is canceled\n    ADD = 'add', // When a command is added to the queue\n    CLEAR = 'clear', // When the history queue is cleared\n    CHANGE = 'change', // When the history queue changes\n  }\n  ```\n\n- Command\n\n  Please refer to the previous [Command](#parameter-type-description) type description\n\nExample:\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('Undo operation executed');\n});\n```\n\n### History.redo()\n\nPerforms a **redo** operation and returns the plugin instance. If the redo stack is empty, no operation is performed.\n\n```typescript\nredo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('Redo operation executed');\n```\n\n### History.undo()\n\nPerforms an **undo** operation and returns the plugin instance. If the undo stack is empty, no operation is performed.\n\n```typescript\nundo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('Undo operation executed');\n```\n\n### History.undoAndCancel()\n\nPerforms an undo operation without recording it in the history and returns the plugin instance. Note that this operation will clear the **redo** stack.\n\n```typescript\nundoAndCancel(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('Undo and cancel operation executed');\n```\n\n## History Modes\n\nThis plugin supports two history modes:\n\n### Default Mode\n\nIn default mode, every time a **render** is triggered (for example, after updating element data, the user actively executes the `graph.draw()` method to trigger rendering), the plugin records the data **before** and **after** rendering and stacks it as an operation record.\n\n### Custom Mode\n\n#### Scenario Description\n\nIn actual needs, a user's graph editing operation may involve **multiple renders**. For example, in one editing operation, first display nodes A and B, then display the connection from A to B. This involves two renders (i.e., the user needs to perform `graph.draw()` twice). In this scenario, the default mode will stack two history records, which are:\n\n- Display nodes A and B\n- Display the connection from A to B\n\nObviously, in actual business, one operation should only require one undo.\n\nBut here, when undoing this operation, the user needs to call the `undo` method twice, which means two undos are required.\n\n#### Scenario Support\n\nTo support such scenarios, G6 provides a batch controller (`BatchController`, [refer to the source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)), which is provided in the graph instance context.\n\nThe history plugin implements custom operation records based on this batch controller. The code example is as follows:\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // Start batch operation\ngraph.addNodeData(...); // Display nodes A and B\ngraph.draw(); // First render trigger\ngraph.addEdgeData(...); // Display the connection from A to B\ngraph.draw(); // Second render trigger\ngraph.context.batch.endBatch(); // End batch operation\n```\n\nIn the example:\n\n- By calling the `startBatch` method of the batch controller instance, the history plugin is informed that batch operations are now being performed. Before the batch operation ends, no matter how many renders are triggered, no history records should be stacked (the history plugin will record the change data for each render trigger).\n- After completing the last data change, call the `endBatch()` method. The history plugin listens for the completion of the batch operation and stacks this batch operation as a history record.\n\nFinally, the user only needs to perform one `undo` to undo.\n\n## Code Examples\n\nBelow are some common cases with corresponding code references.\n\n### Undo and Redo Button States\n\nIn actual business scenarios, you may need to customize the toolbar of the canvas, which involves the enable and disable states of the undo and redo buttons.\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\nIn the example, by listening to the `HistoryEvent.CHANGE` event, which is triggered when the history queue changes, it is determined in real-time whether undo and redo operations can be performed.\n\n### Determine Whether a Command is Allowed to Enter the Queue\n\nHere is a simple scenario: only the operation of removing elements is allowed to enter the history queue.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\nIn the example, the configuration option [beforeAddCommand](#beforeAddCommand) is used to determine whether there are elements removed in `cmd.current.remove`.\n","packages/site/docs/manual/plugin/History.zh.md":"---\ntitle: 历史记录 History\norder: 9\n---\n\n## 概述\n\n该插件用于实现图编辑的 **撤销（Undo）** 和 **重做（Redo）** 功能，通过记录用户操作的历史状态堆栈，支持在图交互过程中进行回溯或恢复操作。该插件为用户提供了完善的配置项和 API 。\n\n## 使用场景\n\n历史记录插件适用于所有涉及到图编辑的场景。\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一插件：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['history'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性             | 描述                                                                                                                                                                | 类型                                                           | 默认值      | 必选 |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------- | ---- |\n| afterAddCommand  | 当一个命令被添加到 `Undo/Redo` 队列后被调用。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作                                                           | (cmd: [Command](#command), revert: boolean) => void            | -           |      |\n| beforeAddCommand | 当一个命令被添加到 `Undo/Redo` 队列前被调用，如果该方法返回 `false`，那么这个命令将不会被添加到队列中。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作 | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -           |      |\n| executeCommand   | 执行命令时的回调函数                                                                                                                                                | (cmd: [Command](#command)) => void                             | -           |      |\n| stackSize        | 最多记录该数据长度的历史记录                                                                                                                                        | number                                                         | 0（不限制） |      |\n\n### 参数类型说明\n\n#### `Command`\n\n```typescript\n// 单条历史记录命令\ninterface Command {\n  current: CommandData; // 当前数据\n  original: CommandData; // 原始数据\n  animation: boolean; // 是否开启动画\n}\n// 单条历史记录命令数据\ninterface CommandData {\n  add: GraphData; // 新增的数据\n  update: GraphData; // 更新的数据\n  remove: GraphData; // 移除的数据\n}\n// 图数据\ninterface GraphData {\n  nodes?: NodeData[]; // 节点数据\n  edges?: EdgeData[]; // 边数据\n  combos?: ComboData[]; // Combo 数据\n}\n```\n\n## API\n\nhistory 插件提供了以下 API 供用户按需使用，调用插件方法的方式请参考 [插件总览文档](/manual/plugin/overview#调用插件方法)\n\n### History.canRedo()\n\n判断是否可以进行**重做**操作。如果重做堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanRedo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('可以进行重做操作');\n} else {\n  console.log('重做堆栈为空，无法重做');\n}\n```\n\n### History.canUndo()\n\n判断是否可以进行**撤销**操作。如果撤销堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanUndo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('可以进行撤销操作');\n} else {\n  console.log('撤销堆栈为空，无法撤销');\n}\n```\n\n### History.clear()\n\n清空历史记录，包括撤销和重做堆栈。\n\n```typescript\nclear(): void;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('历史记录已清空');\n```\n\n### History.on()\n\n监听历史记录事件，允许用户在特定事件发生时执行自定义逻辑。\n\n```typescript\non(event: Loosen/<HistoryEvent/>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\n参数类型说明：\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // 当命令被撤销时\n    REDO = 'redo', // 当命令被重做时\n    CANCEL = 'cancel', // 当命令被取消时\n    ADD = 'add', // 当命令被添加到队列时\n    CLEAR = 'clear', // 当历史队列被清空时\n    CHANGE = 'change', // 当历史队列发生变化时\n  }\n  ```\n\n- Command\n\n  请参考前面的 [Command](#参数类型说明) 类型说明\n\n示例：\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('执行了撤销操作');\n});\n```\n\n### History.redo()\n\n执行**重做**操作，并返回插件实例。如果重做堆栈为空，则不执行任何操作。\n\n```typescript\nredo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('执行了重做操作');\n```\n\n### History.undo()\n\n执行**撤销**操作，并返回插件实例。如果撤销堆栈为空，则不执行任何操作。\n\n```typescript\nundo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('执行了撤销操作');\n```\n\n### History.undoAndCancel()\n\n执行撤销操作且不计入历史记录，并返回插件实例。注意，执行该操作会清空**重做**栈。\n\n```typescript\nundoAndCancel(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('执行了撤销并取消操作');\n```\n\n## 历史记录模式\n\n该插件支持两种历史记录模式：\n\n### 默认模式\n\n默认模式下，每一次触发**渲染后**（比如更新元素数据后，用户主动执行 `graph.draw()` 方法触发渲染），插件会把**渲染前**和**渲染后**的数据记录下来并作为一次操作记录入栈。\n\n### 自定义模式\n\n#### 场景描述\n\n实际需求中，用户的一次图编辑操作可能涉及到**多次渲染**，比如，一次编辑操作中，首先把节点 A、B 展示出来，然后展示 A->B 的连线，这里就涉及到两次渲染（即用户需要进行两次 `graph.draw()` ），这种场景下，默认模式会入栈两次历史记录，分别是：\n\n- 展示节点 A 和 B\n- 展示 A->B 的连线\n\n显然，实际业务中，一次操作，也应该只需一次撤销。\n\n但这里在撤销本次操作时，用户需要调用两次 `undo` 方法，也就是需要进行两次撤销。\n\n#### 场景支持\n\n为了支持这样的场景，G6 提供了一个批量控制器（ `BatchController`，[可参考源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)），在图实例上下文中提供了这个批量控制器实例。\n\n历史记录插件则基于这个批量控制器，来实现自定义操作记录，代码示例如下：\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // 开始批量操作\ngraph.addNodeData(...); // 把节点 A、B 展示出来\ngraph.draw(); // 第一次触发渲染\ngraph.addEdgeData(...); // 把 A->B 连线展示出来\ngraph.draw(); // 第二次触发渲染\ngraph.context.batch.endBatch(); // 结束批量操作\n```\n\n示例中：\n\n- 通过调用批量控制器实例的 `startBatch` 方法，告诉历史记录插件，现在开始进行批量操作，在批量操作没有结束前，不管触发多少次渲染，都不能进行历史记录入栈（历史记录插件会把每次触发渲染的变更数据记录下来）\n- 在完成最后一次数据变更后，调用 `endBatch()` 方法，历史记录插件监听到批量操作完成，则把本次批量操作作为一次历史记录入栈\n\n最终，用户只需要进行一次 `undo` 即可撤销。\n\n## 代码示例\n\n下面列举一些常见的案例，并给出相应的代码参考\n\n### 撤销、重做按钮状态\n\n实际业务场景中，可能需要自定义画布的工具栏，也就涉及到撤销和重做按钮的启禁用状态\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\n示例中通过监听 `HistoryEvent.CHANGE` 事件，这个事件在历史队列发生变化时会触发，每次发生变化后，实时判断当前是否可以进行撤销和重做操作\n\n### 判断是否允许命令进入队列\n\n这里实现一个简单的场景：只有移除元素的操作才允许进入历史记录队列\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\n示例中通过配置项 [beforeAddCommand](#beforeAddCommand) 来实现，判断 `cmd.current.remove` 里面是否存在被移除的元素\n","packages/site/docs/manual/plugin/Hull.en.md":"---\ntitle: Hull\norder: 10\n---\n\n## Overview\n\nHull is used to process and represent the convex or concave polygon bounding box of a set of points. It can wrap a set of nodes in a minimal geometric shape, helping users better understand and analyze datasets.\n\n- **Convex Hull**: This is a convex polygon that contains all the points and has no indentations.\n- **Concave Hull**: This is a concave polygon that also contains all the points but may have indentations. The degree of indentation is controlled by the concavity parameter.\n\n## Usage Scenarios\n\nThe hull plugin is mainly applicable to the following scenarios:\n\n- Wrapping node collections in data visualization\n- Providing visual references to enhance spatial awareness\n- Identifying the collection relationship of specific nodes in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the Hull plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // Specify a unique identifier for subsequent dynamic updates\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n      concavity: Infinity, // Default to convex hull\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## Configuration Options\n\n| Property         | Description                                                                                              | Type                                               | Default Value | Required |\n| ---------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type             | Plugin type                                                                                              | string                                             | `hull`        | ✓        |\n| key              | Unique identifier for the plugin, used for subsequent updates                                            | string                                             | -             |          |\n| members          | Elements within the Hull, including nodes and edges                                                      | string[]                                           | -             | ✓        |\n| concavity        | Concavity, the larger the value, the smaller the concavity; default is Infinity representing Convex Hull | number                                             | Infinity      |          |\n| corner           | Corner type, options are `rounded` \\| `smooth` \\| `sharp`                                                | string                                             | `rounded`     |          |\n| padding          | Padding                                                                                                  | number                                             | `10`          |          |\n| label            | Whether to display the label                                                                             | boolean                                            | true          |          |\n| labelPlacement   | Label position                                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`      |          |\n| labelBackground  | Whether to display the background                                                                        | boolean                                            | false         |          |\n| labelPadding     | Label padding                                                                                            | number \\| number[]                                 | 0             |          |\n| labelCloseToPath | Whether the label is close to the hull                                                                   | boolean                                            | true          |          |\n| labelAutoRotate  | Whether the label rotates with the hull, effective only when closeToPath is true                         | boolean                                            | true          |          |\n| labelOffsetX     | X-axis offset                                                                                            | number                                             | 0             |          |\n| labelOffsetY     | Y-axis offset                                                                                            | number                                             | 0             |          |\n| labelMaxWidth    | Maximum width of the text, exceeding will automatically ellipsis                                         | number                                             | 0             |          |\n\nFor complete label styles, see [this link](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nThe concavity attribute is used to control the concavity of the Hull. When set to Infinity, a convex hull is generated; otherwise, a concave hull is generated.\n\n```js\n// Convex hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // Convex hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// Concave hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // Concave hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hull\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style of the Hull as needed, such as adjusting color, transparency, and other properties.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visual effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","packages/site/docs/manual/plugin/Hull.zh.md":"---\ntitle: 轮廓包围 Hull\norder: 10\n---\n\n## 概述\n\n轮廓包围（Hull）用于处理和表示一组点的凸多边形或凹多边形包围盒。它可以将一组节点包裹在一个最小的几何形状中，帮助用户更好地理解和分析数据集。\n\n- **凸包（Convex Hull）**：这是一个凸多边形，它包含所有的点，并且没有任何凹陷。\n- **凹包（Concave Hull）**：这是一个凹多边形，它同样包含所有的点，但是可能会有凹陷。凹包的凹陷程度由 concavity 参数控制。\n\n## 使用场景\n\n轮廓包围插件主要适用于以下场景：\n\n- 数据可视化中的节点集合包裹\n- 提供视觉参考，增强空间感知\n- 在复杂网络图中标识特定节点的集合关系\n\n## 基本用法\n\n以下是一个简单的 Hull 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // 指定唯一标识符，便于后续动态更新\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n      concavity: Infinity, // 默认为凸包\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## 配置项\n\n| 属性             | 描述                                                       | 类型                                               | 默认值    | 必选 |\n| ---------------- | ---------------------------------------------------------- | -------------------------------------------------- | --------- | ---- |\n| type             | 插件类型                                                   | string                                             | `hull`    | ✓    |\n| key              | 插件唯一标识符，用于后续更新                               | string                                             | -         |      |\n| members          | Hull 内的元素，包括节点和边                                | string[]                                           | -         | ✓    |\n| concavity        | 凹度，数值越大凹度越小；默认为 Infinity 代表为 Convex Hull | number                                             | Infinity  |      |\n| corner           | 拐角类型，可选值为 `rounded` \\| `smooth` \\| `sharp`        | string                                             | `rounded` |      |\n| padding          | 内边距                                                     | number                                             | `10`      |      |\n| label            | 是否显示标签                                               | boolean                                            | true      |      |\n| labelPlacement   | 标签位置                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`  |      |\n| labelBackground  | 是否显示背景                                               | boolean                                            | false     |      |\n| labelPadding     | 标签内边距                                                 | number \\| number[]                                 | 0         |      |\n| labelCloseToPath | 标签是否贴合轮廓                                           | boolean                                            | true      |      |\n| labelAutoRotate  | 标签是否跟随轮廓旋转，仅在 closeToPath 为 true 时生效      | boolean                                            | true      |      |\n| labelOffsetX     | x 轴偏移量                                                 | number                                             | 0         |      |\n| labelOffsetY     | y 轴偏移量                                                 | number                                             | 0         |      |\n| labelMaxWidth    | 文本的最大宽度，超出会自动省略                             | number                                             | 0         |      |\n\n完整的标签样式见[此链接](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nconcavity 属性用于控制 Hull 的凹度。当设置为 Infinity 时，生成的是凸包；否则会生成凹包。\n\n```js\n// 凸包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // 凸包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// 凹包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // 凹包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础 Hull\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义 Hull 的样式，例如调整颜色、透明度等属性。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n```\n\n```\n","packages/site/docs/manual/plugin/Legend.en.md":"---\ntitle: Legend\norder: 11\n---\n\n## Overview\n\nThe Legend plugin is used to display classification information of elements in the graph, supporting the display of classification information for nodes, edges, and combos. Through the legend, users can quickly perceive the classification information of related elements in the graph and quickly locate elements by clicking on the corresponding legend items, improving user browsing efficiency.\n\n## Usage Scenarios\n\nThis plugin is mainly used for:\n\n- Quickly classifying elements through the legend\n- Quickly highlighting and locating corresponding elements through the legend\n\n## Basic Usage\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property          | Description                                                                                                                                                                                    | Type                                                                                        | Default Value | Required |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type              | Plugin type                                                                                                                                                                                    | string                                                                                      | `legend`      | ✓        |\n| key               | Unique identifier for the plugin, used for subsequent updates                                                                                                                                  | string                                                                                      | -             |          |\n| trigger           | How the legend item triggers the corresponding item highlight: <br/>- `hover`: Triggered when the mouse enters the legend item <br/>- `click`: Triggered when the mouse clicks the legend item | `hover` \\| `click`                                                                          | `hover`       |          |\n| position          | Relative position of the legend on the canvas, [optional values](#cardinalplacement)                                                                                                           | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`      |          |\n| container         | Container to which the legend is mounted, if not provided, it is mounted to the container where the Graph is located                                                                           | HTMLElement \\| string                                                                       | -             |          |\n| className         | Legend canvas class name, not effective when an external container is passed                                                                                                                   | string                                                                                      | -             |          |\n| containerStyle    | Style of the legend container, not effective when an external container is passed                                                                                                              | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| nodeField         | Node classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| edgeField         | Edge classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| comboField        | Combo classification identifier                                                                                                                                                                | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| orientation       | Layout direction of legend items: <br/>- `horizontal`: Horizontal direction <br/>- `vertical`: Vertical direction                                                                              | `horizontal` \\| `vertical`                                                                  | 'horizontal'  |          |\n| layout            | Layout method: <br/>- `flex`: Flexible layout <br/>- `grid`: Grid layout                                                                                                                       | `flex` \\| `grid`                                                                            | `flex`        |          |\n| showTitle         | Whether to display the title                                                                                                                                                                   | boolean                                                                                     | false         |\n| titleText         | Title content                                                                                                                                                                                  | string                                                                                      | \"\"            |\n| x                 | Relative horizontal position of the legend on the canvas, higher priority than position                                                                                                        | number                                                                                      | -             |          |\n| y                 | Relative vertical position of the legend on the canvas, higher priority than position                                                                                                          | number                                                                                      | -             |          |\n| width             | Width of the legend                                                                                                                                                                            | number                                                                                      | 240           |          |\n| height            | Height of the legend                                                                                                                                                                           | number                                                                                      | 160           |          |\n| itemSpacing       | Spacing between the text of the legend item and the corresponding marker                                                                                                                       | number                                                                                      | 4             |          |\n| rowPadding        | Spacing between each row in the legend                                                                                                                                                         | number                                                                                      | 10            |          |\n| colPadding        | Spacing between each column in the legend                                                                                                                                                      | number                                                                                      | 10            |          |\n| itemMarkerSize    | Size of the legend item marker                                                                                                                                                                 | number                                                                                      | 16            |          |\n| itemLabelFontSize | Font size of the legend item text                                                                                                                                                              | number                                                                                      | 16            |          |\n| gridCol           | Maximum number of columns allowed for legend items when width permits                                                                                                                          | number                                                                                      | -             |          |\n| gridRow           | Maximum number of rows allowed for legend items when height permits                                                                                                                            | number                                                                                      | -             |          |\n\n### CardinalPlacement\n\nThe `position` property supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side near the top\n- `'left-bottom'`: Left side near the bottom\n- `'right-top'`: Right side near the top\n- `'right-bottom'`: Right side near the bottom\n\n## Code Examples\n\n### Basic Legend\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n### Custom Legend Position\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // You can quickly specify the position through position\n      // position: \"top-left\",\n      // Or you can more flexibly control the position of the legend through x, y\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### Custom Legend Item Layout\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // Control to display only one row\n      gridRow: 1,\n      // Control to display 10 columns in one row, a page button will be displayed when the column width is insufficient\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Setting orientation is ineffective?\n\n`orientation` mainly controls the direction of the layout, and the specific display of **multiple columns in one row** or **multiple rows in one column** is mainly controlled by `gridRow` and `gridCol`. For example, if you want it to look like a vertical legend item, you can configure it like this:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // Control to display 1 column in one row\n      gridCol:1,\n      // Control to display up to 20 rows\n      gridRow: 20,\n    },\n  ],\n```\n\nThis way, it becomes a legend with only one column, conforming to the visual vertical arrangement.\n\n### 2. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// Update legend position\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Legend.zh.md":"---\ntitle: 图例 Legend\norder: 11\n---\n\n## 概述\n\n图例（Legend）插件用于展示图中元素的分类信息，支持节点、边、组合的分类信息展示。通过图例，用户可以快速感知到图中相关元素的分类信息，也可以通过点击对应图例项来快速定位到元素，提高用户的浏览效率。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 通过图例快速对元素进行分类\n- 通过图例快速高亮定位到对应元素\n\n## 基本用法\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性              | 描述                                                                                                  | 类型                                                                                        | 默认值       | 必选 |\n| ----------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type              | 插件类型                                                                                              | string                                                                                      | `legend`     | ✓    |\n| key               | 插件唯一标识符，用于后续更新                                                                          | string                                                                                      | -            |      |\n| trigger           | 图例项触发对应项高亮的方式：<br/>- `hover`：鼠标移入图例项时触发 <br/>- `click`：鼠标点击图例项时触发 | `hover` \\| `click`                                                                          | `hover`      |      |\n| position          | 图例在画布中的相对位置，[可选值](#cardinalplacement)                                                  | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`     |      |\n| container         | 图例挂载的容器，无则挂载到 Graph 所在容器                                                             | HTMLElement \\| string                                                                       | -            |      |\n| className         | 图例画布类名，传入外置容器时不生效                                                                    | string                                                                                      | -            |      |\n| containerStyle    | 图例的容器样式，传入外置容器时不生效                                                                  | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| nodeField         | 节点分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| edgeField         | 边分类标识                                                                                            | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| comboField        | 组合分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| orientation       | 图例项的布局方向：<br/>- `horizontal`：水平方向 <br/>- `vertical`：垂直方向                           | `horizontal` \\| `vertical`                                                                  | 'horizontal' |      |\n| layout            | 布局方式：<br/>- `flex`：弹性布局 <br/>- `grid`：网格布局                                             | `flex` \\| `grid`                                                                            | `flex`       |      |\n| showTitle         | 是否显示标题                                                                                          | boolean                                                                                     | false        |\n| titleText         | 标题内容                                                                                              | string                                                                                      | \"\"           |\n| x                 | 图例在画布中的相对的横向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| y                 | 图例在画布中的相对的纵向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| width             | 图例的宽度                                                                                            | number                                                                                      | 240          |      |\n| height            | 图例的高度                                                                                            | number                                                                                      | 160          |      |\n| itemSpacing       | 图例项的文本和对应标记之间的间距                                                                      | number                                                                                      | 4            |      |\n| rowPadding        | 图例中每行之间的间距                                                                                  | number                                                                                      | 10           |      |\n| colPadding        | 图例中每列之间的间距                                                                                  | number                                                                                      | 10           |      |\n| itemMarkerSize    | 图例项标记的大小                                                                                      | number                                                                                      | 16           |      |\n| itemLabelFontSize | 图例项文本的字体大小                                                                                  | number                                                                                      | 16           |      |\n| gridCol           | 图例项在宽度允许情况下的最大列数                                                                      | number                                                                                      | -            |      |\n| gridRow           | 图例项在高度允许情况下的最大行数                                                                      | number                                                                                      | -            |      |\n\n### CardinalPlacement\n\n`position` 属性支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n## 代码示例\n\n### 基础图例\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n### 自定义图例位置\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // 可以通过 position 快捷的来指定位置\n      // position: \"top-left\",\n      // 也可以通过x,y来更加灵活的控制图例的位置\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### 自定义图例项布局\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // 控制只显示一行\n      gridRow: 1,\n      // 控制一行显示10列，当列宽不足时会显示翻页按钮\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 设置了 orientation 无效？\n\n`orientation`主要控制布局的方向，具体展示**一行多列**还是**一列多行**，主要通过 `gridRow` 以及`gridCol`来控制，例如想要看起来像是竖向的图例项，则可以通过这样配置:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // 控制一行显示1列\n      gridCol:1,\n      // 控制显示最多20行\n      gridRow: 20,\n    },\n  ],\n```\n\n这样就变成了只有一列的图例，符合视觉上的竖向排列。\n\n### 2. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// 更新图例位置\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Minimap.en.md":"---\ntitle: Minimap\norder: 12\n---\n\n## Overview\n\nThe main function of the Minimap is to provide users with an overall layout of the current graph content in the form of a thumbnail, allowing quick positioning of graph operation locations.\n\n**⚠️ Note**, The Minimap plugin is currently incompatible with React Node rendering mechanism. When using Minimap functionality, it is recommended to implement node rendering through [built-in nodes](/en/manual/element/node/overview) or [custom nodes](/en/manual/element/node/custom-node).\n\n## Usage Scenarios\n\nThe Minimap plugin is mainly applicable to the following scenarios:\n\n- Providing a global view for quick area positioning\n- Navigation and interaction assistance, allowing quick positioning to the target location through the minimap\n\n## Basic Usage\n\nBelow is a simple example of initializing the Minimap plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                             | Type                                                                                                                                                                                                   | Default Value  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- |\n| type           | Plugin type                                                                                                             | string                                                                                                                                                                                                 | `minimap`      | ✓        |\n| key            | Unique identifier for the plugin, used for subsequent updates                                                           | string                                                                                                                                                                                                 | -              |          |\n| className      | Class name of the thumbnail canvas, not effective when an external container is passed                                  | string                                                                                                                                                                                                 |                |          |\n| container      | Container to which the thumbnail is mounted, if not provided, it is mounted to the container where the Graph is located | HTMLElement \\| string                                                                                                                                                                                  |                |          |\n| containerStyle | Style of the thumbnail container, not effective when an external container is passed                                    | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| delay          | Delay update time (milliseconds) for performance optimization                                                           | number                                                                                                                                                                                                 | 128            |          |\n| filter         | Filter for filtering out elements that do not need to be displayed                                                      | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |          |\n| maskStyle      | Style of the mask                                                                                                       | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| padding        | Padding                                                                                                                 | number \\| number[]                                                                                                                                                                                     | 10             |          |\n| position       | Position of the thumbnail relative to the canvas                                                                        | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |          |\n| renderer       | Renderer, default is Canvas renderer                                                                                    | IRenderer                                                                                                                                                                                              |                |          |\n| shape          | Method for generating element thumbnails                                                                                | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |          |\n| size           | Width and height                                                                                                        | [number, number]                                                                                                                                                                                       | [240, 160]     |          |\n\n### containerStyle\n\nSet the style of the thumbnail container, not effective when an external container is passed. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value    | Required |\n| ------------ | -------------------------- | ------ | ---------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd` | ✓        |\n| background   | Container background color | string | `#fff`           | ✓        |\n| borderRadius | Container border radius    | string | -                |          |\n| boxShadow    | Container shadow effect    | string | -                |          |\n| padding      | Container padding          | string | -                |          |\n| margin       | Container margin           | string | -                |          |\n| opacity      | Opacity                    | string | -                |          |\n\n### maskStyle\n\nSpecify the style of the mask. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value        | Required |\n| ------------ | -------------------------- | ------ | -------------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd`     | ✓        |\n| background   | Container background color | string | `rgba(0, 0, 0, 0.1)` | ✓        |\n| borderRadius | Container border radius    | string | -                    | -        |\n| boxShadow    | Container shadow effect    | string | -                    | -        |\n| padding      | Container padding          | string | -                    | -        |\n| margin       | Container margin           | string | -                    | -        |\n| opacity      | Opacity                    | string | -                    | -        |\n\n### position\n\nPosition of the thumbnail relative to the canvas, the thumbnail position configuration supports array form and preset value form.\n\n- Array form [number, number] represents relative position, with a value range of 0~1. For example: [0, 0] represents the top left corner of the canvas, [1, 1] represents the bottom right corner of the canvas.\n- Preset value form is used to set the fixed position of the thumbnail on the canvas, optional values are: `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // Modify the position of the minimap here\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\nSet the width and height of the minimap, default value is [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // Set the width and height of the minimap\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Minimap.zh.md":"---\ntitle: 小地图 Minimap\norder: 12\n---\n\n## 概述\n\nMinimap（小地图）的主要作用是为用户提供以缩略图形式展示当前图内容的整体布局，可以快速定位图操作位置。\n\n**⚠️ 需要注意**，Minimap 插件当前不兼容 React Node 渲染机制，在需要使用 Minimap 功能的场景中，建议通过 [内置节点](/manual/element/node/overview) 或者[自定义节点](/manual/element/node/custom-node) 实现节点渲染。\n\n## 使用场景\n\nMinimap（小地图）插件主要适用于以下场景：\n\n- 提供全局视野，快速定位区域\n- 导航与交互辅助，通过操作小地图可以快速定位到目标位置\n\n## 基本用法\n\n以下是一个简单的 Minimap 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                        | 类型                                                                                                                                                                                                   | 默认值         | 必选 |\n| -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ---- |\n| type           | 插件类型                                    | string                                                                                                                                                                                                 | `minimap`      | ✓    |\n| key            | 插件唯一标识符，用于后续更新                | string                                                                                                                                                                                                 | -              |      |\n| className      | 缩略图画布类名，传入外置容器时不生效        | string                                                                                                                                                                                                 |                |      |\n| container      | 缩略图挂载的容器，无则挂载到 Graph 所在容器 | HTMLElement \\| string                                                                                                                                                                                  |                |      |\n| containerStyle | 缩略图的容器样式，传入外置容器时不生效      | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| delay          | 延迟更新时间(毫秒)，用于性能优化            | number                                                                                                                                                                                                 | 128            |      |\n| filter         | 过滤器，用于过滤不必显示的元素              | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |      |\n| maskStyle      | 遮罩的样式                                  | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| padding        | 内边距                                      | number \\| number[]                                                                                                                                                                                     | 10             |      |\n| position       | 缩略图相对于画布的位置                      | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |      |\n| renderer       | 渲染器，默认使用 Canvas 渲染器              | IRenderer                                                                                                                                                                                              |                |      |\n| shape          | 元素缩略图形的生成方法                      | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |      |\n| size           | 宽度和高度                                  | [number, number]                                                                                                                                                                                       | [240, 160]     |      |\n\n### containerStyle\n\n设置缩略图的容器样式，传入外置容器时不生效。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值           | 必选 |\n| ------------ | ------------ | ------ | ---------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd` | ✓    |\n| background   | 容器背景颜色 | string | `#fff`           | ✓    |\n| borderRadius | 容器圆角大小 | string | -                |      |\n| boxShadow    | 容器阴影效果 | string | -                |      |\n| padding      | 容器内边距   | string | -                |      |\n| margin       | 容器外边距   | string | -                |      |\n| opacity      | 透明度       | string | -                |      |\n\n### maskStyle\n\n指定遮罩的样式。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值               | 必选 |\n| ------------ | ------------ | ------ | -------------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd`     | ✓    |\n| background   | 容器背景颜色 | string | `rgba(0, 0, 0, 0.1)` | ✓    |\n| borderRadius | 容器圆角大小 | string | -                    | -    |\n| boxShadow    | 容器阴影效果 | string | -                    | -    |\n| padding      | 容器内边距   | string | -                    | -    |\n| margin       | 容器外边距   | string | -                    | -    |\n| opacity      | 透明度       | string | -                    | -    |\n\n### position\n\n缩略图相对于画布的位置，缩略图位置配置支持数组形式和预设值形式。\n\n- 数组形式 [number, number] 表示相对位置，取值范围为 0~1。举例：[0, 0] 代表画布左上角，[1, 1] 代表画布右下角。\n- 预设值形式用于设定缩略图所在画布固定方位，可选值有：`left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // 这里进行修改minimap所在位置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\n设置小地图的宽度和高度，默认值为 [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // minimap的宽度和高度的设置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Snapline.en.md":"---\ntitle: Snapline\norder: 13\n---\n\n## Overview\n\nThe Snapline plugin provides intelligent alignment guidelines for the canvas, automatically displaying guide lines when moving nodes and supporting automatic snapping. It helps users achieve precise alignment and is an important tool for improving efficiency and accuracy in graphic editing.\n\n## Use Cases\n\nThe Snapline plugin is mainly suitable for the following scenarios:\n\n- When manually adjusting node positions and precise alignment with other nodes is needed\n- When dragging multiple nodes while maintaining their alignment relationships\n- When creating standardized graphic layouts to ensure consistency in node spacing and positioning\n- When improving node layout efficiency through automatic snapping functionality\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // Specify unique identifier\n      tolerance: 5, // Alignment snap threshold\n      offset: 20, // Guide line extension distance\n      autoSnap: true, // Enable automatic snapping\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## Options\n\n| Property            | Description                                                                                                                                                                                            | Type                                      | Default                 | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ----------------------- | -------- |\n| type                | Plugin type                                                                                                                                                                                            | string                                    | `'snapline'`            | ✓        |\n| key                 | Plugin unique identifier                                                                                                                                                                               | string                                    | -                       |          |\n| tolerance           | The alignment accuracy, that is, when the distance between the moved node and the target position is less than tolerance, the alignment line is displayed                                              | number                                    | 5                       |          |\n| offset              | The extension distance of the snapline                                                                                                                                                                 | number                                    | 20                      |          |\n| autoSnap            | Whether to enable automatic snapping                                                                                                                                                                   | boolean                                   | true                    |          |\n| shape               | Specifies which shape on the element to use as the reference shape:<br/>- `'key'`: uses the key shape of the element as the reference shape<br/>- `Function`: receives the element and returns a shape | string \\| ((node: Node) => DisplayObject) | `'key'`                 |          |\n| verticalLineStyle   | Vertical snapline style                                                                                                                                                                                | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| horizontalLineStyle | Horizontal snapline style                                                                                                                                                                              | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| filter              | Filter nodes that do not need to participate in alignment                                                                                                                                              | (node: Node) => boolean                   | `() => true`            |          |\n\n### shape\n\nThe `shape` property specifies the reference shape for elements and supports the following configurations:\n\n```js\n// Use the key shape as reference\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// Use custom function to return reference shape\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### Snapline Style Configuration\n\n| Property       | Description             | Type                                     | Default     |\n| -------------- | ----------------------- | ---------------------------------------- | ----------- |\n| stroke         | Line color              | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | Overall opacity         | number \\| string                         | 1           |\n| strokeOpacity  | Stroke opacity          | number \\| string                         | 1           |\n| lineWidth      | Line width              | number \\| string                         | 1           |\n| lineCap        | Line end style          | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | Line join style         | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | Dash line configuration | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | Dash line offset        | number                                   | 0           |\n| shadowBlur     | Shadow blur             | number                                   | 0           |\n| shadowColor    | Shadow color            | string                                   | -           |\n| shadowOffsetX  | Shadow X offset         | number                                   | 0           |\n| shadowOffsetY  | Shadow Y offset         | number                                   | 0           |\n| cursor         | Mouse cursor style      | string                                   | `'default'` |\n| zIndex         | Rendering level         | number                                   | 0           |\n\nExample configuration:\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## Code Examples\n\n### Basic Snapline\n\nThe simplest usage:\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### Custom Configuration\n\nYou can customize the snapline behavior according to your needs:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // Larger snap range\n      offset: 30, // Longer extension lines\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // Filter nodes by id, exclude from alignment\n    },\n  ],\n});\n```\n\n## Live Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Snapline.zh.md":"---\ntitle: 对齐线 Snapline\norder: 13\n---\n\n## 概述\n\n对齐线插件为画布提供智能对齐参考线，在移动节点时自动显示辅助线并支持自动吸附，帮助用户实现精确对齐，是图形编辑中提升效率和精确度的重要工具。\n\n## 使用场景\n\n对齐线插件主要适用于以下场景：\n\n- 手动调整节点位置时,需要与其他节点精确对齐\n- 拖拽移动多个节点时,保持它们之间的对齐关系\n- 制作规范的图形布局时,确保节点间距和位置的一致性\n- 通过自动吸附功能提高节点排版效率\n\n## 基本用法\n\n以下是一个简单的 Snapline 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // 指定唯一标识符\n      tolerance: 5, // 对齐吸附阈值\n      offset: 20, // 对齐线延伸距离\n      autoSnap: true, // 启用自动吸附\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## 配置项\n\n| 属性                | 描述                                                                                                                    | 类型                                                                                                                            | 默认值                  | 必选 |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type                | 插件类型                                                                                                                | string                                                                                                                          | `'snapline'`            | ✓    |\n| key                 | 插件唯一标识符                                                                                                          | string                                                                                                                          | -                       |      |\n| tolerance           | 对齐精度，即触发对齐的距离阈值                                                                                          | number                                                                                                                          | 5                       |      |\n| offset              | 对齐线头尾的延伸距离                                                                                                    | number                                                                                                                          | 20                      |      |\n| autoSnap            | 是否启用自动吸附                                                                                                        | boolean                                                                                                                         | true                    |      |\n| shape               | 指定元素的参照图形：<br/>- `'key'`: 使用元素的主图形作为参照图形<br/>- `Function`: 传入函数时接收元素对象，返回一个图形 | string \\| ((node: Node) => DisplayObject)                                                                                       | `'key'`                 |      |\n| verticalLineStyle   | 垂直对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| horizontalLineStyle | 水平对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| filter              | 过滤不需要参与对齐的节点                                                                                                | (node: Node) => boolean                                                                                                         | `() => true`            |      |\n\n### shape\n\n`shape` 属性用于指定元素的参照图形，支持以下配置方式：\n\n```js\n// 使用主图形作为参照\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// 使用自定义函数返回参照图形\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### 对齐线样式配置\n\n| 配置项         | 说明            | 类型                                     | 默认值      |\n| -------------- | --------------- | ---------------------------------------- | ----------- |\n| stroke         | 线条颜色        | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | 整体透明度      | number \\| string                         | 1           |\n| strokeOpacity  | 描边透明度      | number \\| string                         | 1           |\n| lineWidth      | 线宽度          | number \\| string                         | 1           |\n| lineCap        | 线段端点样式    | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | 线段连接处样式  | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | 虚线配置        | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | 虚线偏移量      | number                                   | 0           |\n| shadowBlur     | 阴影模糊程度    | number                                   | 0           |\n| shadowColor    | 阴影颜色        | string                                   | -           |\n| shadowOffsetX  | 阴影 X 方向偏移 | number                                   | 0           |\n| shadowOffsetY  | 阴影 Y 方向偏移 | number                                   | 0           |\n| cursor         | 鼠标样式        | string                                   | `'default'` |\n| zIndex         | 渲染层级        | number                                   | 0           |\n\n示例配置\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## 代码示例\n\n### 基础对齐线\n\n最简单的使用方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### 自定义配置\n\n可以根据需要自定义对齐线的行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // 更大的吸附范围\n      offset: 30, // 更长的延伸线\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // 根据id过滤节点，不参与对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Timebar.en.md":"---\ntitle: Timebar\norder: 14\n---\n\n## Overview\n\nThe Timebar plugin is an important tool for exploring time-series data. It can display the time distribution of data in the form of a timeline or trend chart, and supports interactions such as time interval filtering and dynamic playback, helping users better understand the changes in data over time.\n\n## Use Cases\n\n- Need to display and analyze the time distribution of time-series data\n- Need to filter and explore graph data through the time dimension\n- Need to dynamically display the process of data changing over time\n\n## Basic Usage\n\nBelow is a simple example of initializing the Timebar plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // Time data\n      width: 450, // Timebar width\n      height: 60, // Timebar height\n      position: 'bottom', // Position\n      loop: false, // Whether to loop playback\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                              | Type                                               | Default Value | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type           | Plugin type                                                                                                                                                                              | string                                             | `timebar`     | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                        | string                                             | -             |          |\n| className      | Additional class name for the toolbar DOM                                                                                                                                                | string                                             | `g6-timebar`  |          |\n| x              | X position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| y              | Y position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| width          | Timebar width                                                                                                                                                                            | number                                             | 450           |          |\n| height         | Timebar height                                                                                                                                                                           | number                                             | 60            |          |\n| position       | Timebar position                                                                                                                                                                         | `bottom` \\| `top`                                  | `bottom`      |          |\n| padding        | Padding                                                                                                                                                                                  | number \\| number[]                                 | 10            |          |\n| data           | Time data                                                                                                                                                                                | number[] \\| { time: number; value: number }[]      | -             | ✓        |\n| timebarType    | Timebar display type                                                                                                                                                                     | `time` \\| `chart`                                  | `time`        |          |\n| elementTypes   | Filter element types                                                                                                                                                                     | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]      |          |\n| mode           | Control element filtering method, supports the following two configurations: <br/>- `modify`: filter by modifying graph data <br/>- `visibility`: filter by modifying element visibility | `modify` \\| `visibility`                           | `modify`      |          |\n| values         | Current time value                                                                                                                                                                       | number \\| [number, number] \\| Date \\| [Date, Date] | -             |          |\n| loop           | Whether to loop playback                                                                                                                                                                 | boolean                                            | false         |          |\n| getTime        | Method to get element time                                                                                                                                                               | (datum: ElementDatum) => number                    | -             |          |\n| labelFormatter | Custom time formatting in chart mode                                                                                                                                                     | (time: number \\| Date) => string                   | -             |          |\n| onChange       | Callback when the time interval changes                                                                                                                                                  | (values: number \\| [number, number]) => void       | -             |          |\n| onReset        | Callback when reset                                                                                                                                                                      | () => void                                         | -             |          |\n| onSpeedChange  | Callback when playback speed changes                                                                                                                                                     | (speed: number) => void                            | -             |          |\n| onPlay         | Callback when playback starts                                                                                                                                                            | () => void                                         | -             |          |\n| onPause        | Callback when paused                                                                                                                                                                     | () => void                                         | -             |          |\n| onBackward     | Callback when moving backward                                                                                                                                                            | () => void                                         | -             |          |\n| onForward      | Callback when moving forward                                                                                                                                                             | () => void                                         | -             |          |\n\n### timebarType\n\nThe `timebarType` property is used to control the display type of the timebar, supporting the following two configurations:\n\n- `time`: Displayed as a timeline, refer to [Time Mode Example](/examples/plugin/timebar/#timer)\n- `chart`: Displayed as a trend chart, at this time the `data` configuration item under `timebar` needs to pass an additional `value` field as chart data, refer to [Chart Mode Example](/examples/plugin/timebar/#chart)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        // By default, elementTypes=['node'], so nodes need to set data.timestamp to display sequentially according to the timeline\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // Scenario 1: By default, elementTypes = ['node']\n        // - Edges do not need to set data.timestamp, the display/hide of edges depends entirely on whether the two connected nodes are visible\n\n        // Scenario 2: If elementTypes includes 'edge', for example, elementTypes = ['node', 'edge']\n        // - At this time, edges must set data.timestamp, and the display of edges is controlled by it\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\n`width`, `height`, `padding`, `className` can customize the display effect of the timebar, but note that `className` only acts on the outer DOM container and cannot affect the internal Canvas rendering content of the timebar (timeline, chart, play button, etc.).\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // Note: Since the content is Canvas rendered, CSS styles cannot affect the internal content of the timebar\n      width: 400, // Set timebar width\n      height: 80, // Set timebar height\n      padding: [20, 20, 10, 20], // Set padding [top, right, bottom, left]\n      position: 'bottom', // Keep position at the bottom\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\nCSS can only set the style of the timebar container:\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## Real Cases\n\n- [Time Mode](/examples/plugin/timebar/#timer)\n- [Chart Mode](/examples/plugin/timebar/#chart)\n","packages/site/docs/manual/plugin/Timebar.zh.md":"---\ntitle: 时间条 Timebar\norder: 14\n---\n\n## 概述\n\n时间条插件是一个用于时序数据探索的重要工具，它能够通过时间轴或趋势图的形式展示数据的时间分布，并支持时间区间筛选、动态播放等交互方式，帮助用户更好地理解数据随时间的变化。\n\n## 使用场景\n\n- 需要展示和分析时序数据的时间分布\n- 需要通过时间维度筛选和探索图数据\n- 需要动态展示数据随时间变化的过程\n\n## 基本用法\n\n以下是一个简单的 Timebar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // 时间数据\n      width: 450, // 时间条宽度\n      height: 60, // 时间条高度\n      position: 'bottom', // 位置\n      loop: false, // 是否循环播放\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                           | 类型                                               | 默认值       | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------------ | ---- |\n| type           | 插件类型                                                                                                                       | string                                             | `timebar`    | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                               | string                                             | -            |      |\n| className      | 给工具栏的 DOM 追加的类名                                                                                                      | string                                             | `g6-timebar` |      |\n| x              | X 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| y              | Y 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| width          | 时间条宽度                                                                                                                     | number                                             | 450          |      |\n| height         | 时间条高度                                                                                                                     | number                                             | 60           |      |\n| position       | 时间条位置                                                                                                                     | `bottom` \\| `top`                                  | `bottom`     |      |\n| padding        | 边距                                                                                                                           | number \\| number[]                                 | 10           |      |\n| data           | 时间数据                                                                                                                       | number[] \\| { time: number; value: number }[]      | -            | ✓    |\n| timebarType    | 时间条展示类型                                                                                                                 | `time` \\| `chart`                                  | `time`       |      |\n| elementTypes   | 筛选元素类型                                                                                                                   | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]     |      |\n| mode           | 控制元素的筛选方式，支持以下两种配置： <br/>- `modify`：通过修改图数据进行筛选 <br/>- `visibility`：通过修改元素可见性进行筛选 | `modify` \\| `visibility`                           | `modify`     |      |\n| values         | 当前时间值                                                                                                                     | number \\| [number, number] \\| Date \\| [Date, Date] | -            |      |\n| loop           | 是否循环播放                                                                                                                   | boolean                                            | false        |      |\n| getTime        | 获取元素时间的方法                                                                                                             | (datum: ElementDatum) => number                    | -            |      |\n| labelFormatter | 图表模式下自定义时间格式化                                                                                                     | (time: number \\| Date) => string                   | -            |      |\n| onChange       | 时间区间变化时的回调                                                                                                           | (values: number \\| [number, number]) => void       | -            |      |\n| onReset        | 重置时的回调                                                                                                                   | () => void                                         | -            |      |\n| onSpeedChange  | 播放速度变化时的回调                                                                                                           | (speed: number) => void                            | -            |      |\n| onPlay         | 开始播放时的回调                                                                                                               | () => void                                         | -            |      |\n| onPause        | 暂停时的回调                                                                                                                   | () => void                                         | -            |      |\n| onBackward     | 后退时的回调                                                                                                                   | () => void                                         | -            |      |\n| onForward      | 前进时的回调                                                                                                                   | () => void                                         | -            |      |\n\n### timebarType\n\n`timebarType` 属性用于控制时间条的展示类型，支持以下两种配置：\n\n- `time`：显示为时间轴形式，参考 [时间模式示例](/examples/plugin/timebar/#timer)\n- `chart`：显示为趋势图形式，此时`timebar`下的`data`配置项，每个数组项需要额外传入 `value` 字段作为图表数据，参考 [图表模式示例](/examples/plugin/timebar/#chart)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        // 默认情况下 elementTypes=['node']，所以节点需要设置 data.timestamp，才能按照时间轴内的时间依次展示\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // 场景一：默认情况 elementTypes = ['node']\n        // - 边不需要设置 data.timestamp，边的显示/隐藏完全取决于其连接的两个节点是否可见\n\n        // 场景二：如果elementTypes包含了'edge'，比如 elementTypes = ['node', 'edge']\n        // - 此时必须为边设置 data.timestamp，边的显示受其控制\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n`width`、`height`、`padding`、`className` 可自定义时间条的展示效果，但需要注意 `className` 仅作用于外层 DOM 容器，无法影响时间条内部的 Canvas 渲染内容（时间轴、图表、播放按钮等）。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // 注意：由于内容是 Canvas 渲染，CSS 样式无法影响到时间条的内部内容\n      width: 400, // 设置时间条宽度\n      height: 80, // 设置时间条高度\n      padding: [20, 20, 10, 20], // 设置内边距 [上, 右, 下, 左]\n      position: 'bottom', // 位置保持在底部\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\n通过 CSS 只能设置时间条容器的样式：\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\n效果如下：\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## 实际案例\n\n- [时间模式](/examples/plugin/timebar/#timer)\n- [图表模式](/examples/plugin/timebar/#chart)\n","packages/site/docs/manual/plugin/Title.en.md":"---\ntitle: Title\norder: 15\n---\n\n## Overview\n\nTitle indicates the name of the image and conveys the brief content of the image.\n\n## Basic Usage\n\nThe following is a simple example of initializing the Title plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: 'This is a title',\n      subTitle: 'This is a subtitle',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                   | Type                          | Default      | Required |\n| --------- | ------------------------------------------------------------- | ----------------------------- | ------------ | -------- |\n| type      | Plugin type                                                   | string                        | `title`      | ✓        |\n| key       | Unique identifier for the plugin, used for subsequent updates | string                        | -            |          |\n| title     | title content [style config](#title)                          | `TitleStyle`                  | -            | ✓        |\n| subtitle  | subtitle content [style config](#subtitle)                    | `SubTitleStyle`               | -            |          |\n| spacing   | Vertical spacing between main title and subtitle              | number                        | 8            |          |\n| className | Class name of the title canvas                                | string                        | -            |          |\n| align     | Graph title alignment                                         | `left` \\| `center` \\| `right` | `left`       |          |\n| size      | Height of the title plugin                                    | number                        | 44           |          |\n| padding   | Padding                                                       | number \\| number[]            | [16,24,0,24] |          |\n\n### size\n\n<description> _number_ **optional** </description>\n\nUsed to configure the space height of the title plugin. Default is `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\nUsed to configure the horizontal alignment of the title plugin. Default is `left`. You can choose `left`, `center`, or `right`, representing left-aligned, center-aligned, and right-aligned respectively.\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: 'Ciallo' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: 'This is a title This is a title',\n        subtitle: 'This is a sub-',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\nUsed to configure the spacing between the chart main title and subtitle. Default is `8`. Appropriate spacing can make the chart look more harmonious overall.\n\n### title\n\nThe title, specifically the main title, can be customized with the following configurations for various title styles.\n\n| Attr               | Desc                                               | Type       | Default               |\n| ------------------ | -------------------------------------------------- | ---------- | --------------------- |\n| title              | Title text content                                 | `string`   | -                     |\n| titleFontSize      | Title text size                                    | `number`   | 16                    |\n| titleFontFamily    | Title text font                                    | `string`   | system-ui, sans-serif |\n| titleFontWeight    | Title font weight                                  | `number`   | bold                  |\n| titleLineHeight    | Title text line height                             | `number`   | 16                    |\n| titleTextAlign     | Horizontal alignment of content in title text line | `string`   | left                  |\n| titleTextBaseline  | Vertical baseline of title text                    | `string`   | top                   |\n| titleFill          | Fill color of title text                           | `string`   | #1D2129               |\n| titleFillOpacity   | Fill transparency of title text                    | `number`   | 0.9                   |\n| titleStroke        | Stroke color of title text                         | `string`   | transparent           |\n| titleStrokeOpacity | Stroke transparency of title text                  | `number`   | 1                     |\n| titleLineWidth     | Stroke width of title text                         | `number`   | 0                     |\n| titleLineDash      | Dash style of title text                           | `number[]` | []                    |\n| titleOpacity       | Overall transparency of title text                 | `number`   | 1                     |\n| titleShadowColor   | Shadow color of title text                         | `string`   | transparent           |\n| titleShadowBlur    | Gaussian blur coefficient of title text shadow     | `number`   | 0                     |\n| titleShadowOffsetX | Horizontal offset of title text shadow             | `number`   | 0                     |\n| titleShadowOffsetY | Vertical offset of title text shadow               | `number`   | 0                     |\n| titleCursor        | Mouse style of title text                          | `string`   | default               |\n| titleDx            | Horizontal offset of title text                    | `number`   | 0                     |\n| titleDy            | Vertical offset of title text                      | `number`   | 0                     |\n\n### subtitle\n\nThe subtitle, which can be customized with the following configurations for various subtitle styles.\n\n| Attr                  | Desc                                            | Type       | Default               |\n| --------------------- | ----------------------------------------------- | ---------- | --------------------- |\n| subtitle              | Subtitle text content                           | `string`   | -                     |\n| subtitleFontSize      | Subtitle text size                              | `number`   | 12                    |\n| subtitleFontFamily    | Subtitle text font                              | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | Subtitle font weight                            | `number`   | normal                |\n| subtitleLineHeight    | Subtitle text line height                       | `number`   | 12                    |\n| subtitleTextAlign     | Subtitle text line content horizontal alignment | `string`   | left                  |\n| subtitleTextBaseline  | Subtitle text vertical baseline                 | `string`   | top                   |\n| subtitleFill          | Subtitle text fill color                        | `string`   | #1D2129               |\n| subtitleFillOpacity   | Subtitle text fill transparency                 | `number`   | 0.65                  |\n| subtitleStroke        | Subtitle text stroke color                      | `string`   | transparent           |\n| subtitleStrokeOpacity | Subtitle text stroke transparency               | `number`   | 1                     |\n| subtitleLineWidth     | Subtitle text stroke width                      | `number`   | 0                     |\n| subtitleLineDash      | Subtitle text dashed line style                 | `number[]` | []                    |\n| subtitleOpacity       | Subtitle text overall transparency              | `number`   | 1                     |\n| subtitleShadowColor   | Subtitle text shadow color                      | `string`   | transparent           |\n| subtitleShadowBlur    | Subtitle text shadow Gaussian blur coefficient  | `number`   | 0                     |\n| subtitleShadowOffsetX | Subtitle text shadow horizontal offset          | `number`   | 0                     |\n| subtitleShadowOffsetY | Subtitle text shadow vertical offset            | `number`   | 0                     |\n| subtitleCursor        | Subtitle text mouse style                       | `string`   | default               |\n| subtitleDx            | Subtitle text horizontal offset                 | `number`   | 0                     |\n| subtitleDy            | Subtitle text vertical offset                   | `number`   | 0                     |\n\n## Try it\n\nFeel free to modify this example and try different configurations\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // Alignment of title\n      spacing: 4, // Spacing between main title and subtitle\n      size: 60, // Height of title, default is 44\n\n      // title\n      title: 'This is a title This is a title', // Title text\n      titleFontSize: 28, // Main title font size\n      titleFontFamily: 'sans-serif', // Main title font\n      titleFontWeight: 600, // Main title font weight\n      titleFill: '#fff', // Main title text color\n      titleFillOpacity: 1, // Main title text transparency\n      titleStroke: '#000', // Main title text stroke color\n      titleLineWidth: 2, // Main title text stroke line width\n      titleStrokeOpacity: 1, // Main title text stroke transparency\n\n      // subtitle\n      subtitle: 'This is a sub-', // Subtitle text\n      subtitleFontSize: 16, // Subtitle font size\n      subtitleFontFamily: 'Arial', // Subtitle font\n      subtitleFontWeight: 300, // Subtitle font weight\n      subtitleFill: '#2989FF', // Subtitle text color\n      subtitleFillOpacity: 1, // Subtitle text transparency\n      subtitleStroke: '#000', // Subtitle text stroke color\n      subtitleLineWidth: 1, // Subtitle text stroke line width\n      subtitleStrokeOpacity: 0.5, // Subtitle text stroke transparency\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: 'Ciallo' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Title.zh.md":"---\ntitle: 标题 Title\norder: 15\n---\n\n## 概述\n\nTitle（标题）表明了这张图的名称，传达图的简略内容\n\n## 基本用法\n\n以下是一个简单的 Title 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: '这是一个标题',\n      subTitle: '这是一个副标题',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                             | 类型                          | 默认值       | 必选 |\n| --------- | -------------------------------- | ----------------------------- | ------------ | ---- |\n| type      | 插件类型                         | string                        | `title`      | ✓    |\n| key       | 插件唯一标识符，用于后续更新     | string                        | -            |      |\n| title     | 标题内容 [样式配置](#title)      | `TitleStyle`                  | -            | ✓    |\n| subtitle  | 副标题内容 [样式配置](#subtitle) | `SubTitleStyle`               | -            |      |\n| spacing   | 主标题、副标题之间的上下间距     | number                        | 8            |      |\n| className | 标题画布类名                     | string                        | -            |      |\n| align     | 标题相对于画布的位置             | `left` \\| `center` \\| `right` | `left`       |      |\n| size      | 整个标题插件的高度               | number                        | 44           |      |\n| padding   | 内边距                           | number \\| number[]            | [16,24,0,24] |      |\n\n### size\n\n<description> _number_ **optional** </description>\n\n用于配置标题的空间高度大小，默认为 `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\n用于配置标题的的左右对齐方式，默认为 `left`，可以选择使用 `left`，`center`，`right`，分别代表着居左对齐、居中对齐、居右对齐。\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: '你好' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: '这是一个标题这是一个标题',\n        subtitle: '这是一个副标',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\n用于配置主标题和副标题之间的间距，默认为 `8`，合适的间距，可以让看起来整体更协调。\n\n### title\n\n的标题，具体来说是主标题，可以用以下的配置来定制标题的各种样式。\n\n| 属性               | 描述                           | 类型       | 默认值                |\n| ------------------ | ------------------------------ | ---------- | --------------------- |\n| title              | 标题文字内容                   | `string`   | -                     |\n| titleFontSize      | 标题文字大小                   | `number`   | 16                    |\n| titleFontFamily    | 标题文字字体                   | `string`   | system-ui, sans-serif |\n| titleFontWeight    | 标题字体粗细                   | `number`   | bold                  |\n| titleLineHeight    | 标题文字的行高                 | `number`   | 16                    |\n| titleTextAlign     | 标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| titleTextBaseline  | 标题文字垂直方向的基线         | `string`   | top                   |\n| titleFill          | 标题文字的填充色               | `string`   | #1D2129               |\n| titleFillOpacity   | 标题文字的填充透明度           | `number`   | 0.9                   |\n| titleStroke        | 标题文字的描边颜色             | `string`   | transparent           |\n| titleStrokeOpacity | 标题文字的描边透明度           | `number`   | 1                     |\n| titleLineWidth     | 标题文字描边宽度               | `number`   | 0                     |\n| titleLineDash      | 标题文字虚线样式               | `number[]` | []                    |\n| titleOpacity       | 标题文字整体透明度             | `number`   | 1                     |\n| titleShadowColor   | 标题文字阴影颜色               | `string`   | transparent           |\n| titleShadowBlur    | 标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| titleShadowOffsetX | 标题文字阴影水平偏移量         | `number`   | 0                     |\n| titleShadowOffsetY | 标题文字阴影垂直偏移量         | `number`   | 0                     |\n| titleCursor        | 标题文字鼠标样式               | `string`   | default               |\n| titleDx            | 标题文字在水平方向的偏移量     | `number`   | 0                     |\n| titleDy            | 标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n### subtitle\n\n的副标题，可以用以下的配置来定制副标题的各种样式。\n\n| 属性                  | 描述                             | 类型       | 默认值                |\n| --------------------- | -------------------------------- | ---------- | --------------------- |\n| subtitle              | 副标题文字内容                   | `string`   | -                     |\n| subtitleFontSize      | 副标题文字大小                   | `number`   | 12                    |\n| subtitleFontFamily    | 副标题文字字体                   | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | 副标题字体粗细                   | `number`   | normal                |\n| subtitleLineHeight    | 副标题文字的行高                 | `number`   | 12                    |\n| subtitleTextAlign     | 副标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| subtitleTextBaseline  | 副标题文字垂直方向的基线         | `string`   | top                   |\n| subtitleFill          | 副标题文字的填充色               | `string`   | #1D2129               |\n| subtitleFillOpacity   | 副标题文字的填充透明度           | `number`   | 0.65                  |\n| subtitleStroke        | 副标题文字的描边颜色             | `string`   | transparent           |\n| subtitleStrokeOpacity | 副标题文字的描边透明度           | `number`   | 1                     |\n| subtitleLineWidth     | 副标题文字描边宽度               | `number`   | 0                     |\n| subtitleLineDash      | 副标题文字虚线样式               | `number[]` | []                    |\n| subtitleOpacity       | 副标题文字整体透明度             | `number`   | 1                     |\n| subtitleShadowColor   | 副标题文字阴影颜色               | `string`   | transparent           |\n| subtitleShadowBlur    | 副标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| subtitleShadowOffsetX | 副标题文字阴影水平偏移量         | `number`   | 0                     |\n| subtitleShadowOffsetY | 副标题文字阴影垂直偏移量         | `number`   | 0                     |\n| subtitleCursor        | 副标题文字鼠标样式               | `string`   | default               |\n| subtitleDx            | 副标题文字在水平方向的偏移量     | `number`   | 0                     |\n| subtitleDy            | 副标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n## 尝试一下\n\n你可以在这个例子里随意修改并尝试不同的配置\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // 标题的对齐方式\n      spacing: 4, // 主标题和副标题之间的间距\n      size: 60, // 标题的高度，默认为 44\n\n      // 标题\n      title: '这是一个标题这是一个标题', // 标题的文本\n      titleFontSize: 28, // 主标题的字体大小\n      titleFontFamily: 'sans-serif', // 主标题的字体\n      titleFontWeight: 600, // 主标题的字体粗细\n      titleFill: '#fff', // 主标题的文字颜色\n      titleFillOpacity: 1, // 主标题的文字透明度\n      titleStroke: '#000', // 主标题的文字描边颜色\n      titleLineWidth: 2, // 主标题的文字描边线宽\n      titleStrokeOpacity: 1, // 主标题的文字描边透明度\n\n      // 副标题\n      subtitle: '这是一个副标', // 副标题的文本\n      subtitleFontSize: 16, // 副标题的字体大小\n      subtitleFontFamily: 'Arial', // 副标题的字体\n      subtitleFontWeight: 300, // 副标题的字体粗细\n      subtitleFill: '#2989FF', // 副标题的文字颜色\n      subtitleFillOpacity: 1, // 副标题的文字透明度\n      subtitleStroke: '#000', // 副标题的文字描边颜色\n      subtitleLineWidth: 1, // 副标题的文字描边线宽\n      subtitleStrokeOpacity: 0.5, // 副标题的文字描边透明度\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: '你好' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Toolbar.en.md":"---\ntitle: Toolbar\norder: 15\n---\n\n## Overview\n\nThe Toolbar is a plugin in G6 used to provide a collection of operation buttons, supporting common chart operations such as zoom in, zoom out, auto-fit, and reset. Through the toolbar, users can quickly access common functions of the chart, improving operational efficiency and user experience.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Quickly accessing common functions of the chart\n\n## Basic Usage\n\nBelow is a simple example of initializing the Toolbar plugin:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // Handle button click events\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property  | Description                                                                  | Type                                                                                        | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type      | Plugin type                                                                  | string                                                                                      | `toolbar`     | ✓        |\n| key       | Unique identifier for the plugin, used for updates                           | string                                                                                      | -             |          |\n| className | Additional CSS class name for the toolbar DOM element                        | string                                                                                      | -             |          |\n| position  | Toolbar position relative to the canvas, [optional values](#position)        | string                                                                                      | `'top-left'`  |          |\n| style     | Custom style for the toolbar DOM element, [common values](#style-attributes) | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| getItems  | Returns the list of toolbar items                                            | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -             | ✓        |\n| onClick   | Callback function after a toolbar item is clicked                            | (value: string, target: Element) => void                                                    | -             |          |\n\n### position\n\nThe `position` parameter supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side, top\n- `'left-bottom'`: Left side, bottom\n- `'right-top'`: Right side, top\n- `'right-bottom'`: Right side, bottom\n\n### style Attributes\n\n| Attribute       | Description      | Type   | Default Value       |\n| --------------- | ---------------- | ------ | ------------------- |\n| backgroundColor | Background color | string | `#fff`              |\n| border          | Border           | string | `1px solid #e8e8e8` |\n| borderRadius    | Border radius    | string | `4px`               |\n| height          | Height           | string | `auto`              |\n| margin          | Margin           | string | `12px`              |\n| opacity         | Opacity          | number | 0.9                 |\n| padding         | Padding          | string | `8px`               |\n| width           | Width            | string | `auto`              |\n\n### ToolbarItem\n\nEach toolbar item (ToolbarItem) includes the following attributes:\n\n| Attribute | Description                                                | Type     | Required |\n| --------- | ---------------------------------------------------------- | -------- | -------- |\n| id        | Icon ID of the item, see [Built-in Icons](#built-in-icons) | `string` | ✓        |\n| value     | Value returned when the item is clicked                    | `string` | ✓        |\n\n### Built-in Icons\n\nThe Toolbar provides the following built-in icon IDs:\n\n- `'zoom-in'`: Zoom in\n- `'zoom-out'`: Zoom out\n- `'redo'`: Redo\n- `'undo'`: Undo\n- `'edit'`: Edit\n- `'delete'`: Delete\n- `'auto-fit'`: Auto-fit view\n- `'export'`: Export chart\n- `'reset'`: Reset view\n- `'request-fullscreen'`: Request fullscreen\n- `'exit-fullscreen'`: Exit fullscreen\n\n### Custom Icons\n\nIn addition to using built-in icons, you can also use custom icons by introducing third-party icon libraries (such as Alibaba iconfont):\n\n```js\n// Introduce iconfont script\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // Replace with your iconfont script URL\ndocument.head.appendChild(iconFont);\n\n// Use custom icons in the toolbar\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // Use icons from iconfont\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Note: Custom icon IDs usually start with `icon-` and need to correspond to the icon names in the introduced iconfont.\n\n## Code Examples\n\n### Basic Toolbar\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo, undo need to be used with the history plugin\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### Custom Styles\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Common style attributes include:\n>\n> - `backgroundColor`: Background color\n> - `padding`: Padding\n> - `margin`/`marginTop`/`marginLeft`, etc.: Margin\n> - `border`: Border\n> - `borderRadius`: Border radius\n> - `boxShadow`: Shadow effect\n> - `opacity`: Opacity\n> - `width`/`height`: Width and height (default is content adaptive)\n> - `zIndex`: Layer (default is 100)\n> - `display`: Display mode (default is flex)\n\nThe toolbar container is set to `display: flex` by default, and child items use row layout by default (or change according to the direction configured by position). You can customize its appearance and position through `style`.\n\n### Asynchronous Loading of Toolbar Items\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Toolbar icons not displaying?\n\n- Check if the correct built-in icon ID is used\n- Ensure CSS styles are not overridden or conflicting\n\n### 2. How to use with other plugins?\n\nThe toolbar is often used in conjunction with other plugins (such as history):\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// Update toolbar position\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Toolbar.zh.md":"---\ntitle: 工具栏 Toolbar\norder: 15\n---\n\n## 概述\n\nToolbar 是 G6 中用于提供操作按钮集合的插件，支持放大、缩小、自适应、重置等常用图表操作。通过工具栏，用户可以快速访问图表的常用功能，提高操作效率和用户体验。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 快速访问图表的常用功能\n\n## 基本用法\n\n以下是一个简单的 Toolbar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // 处理按钮点击事件\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                             | 类型                                                                                        | 默认值       | 必选 |\n| --------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type      | 插件类型                                         | string                                                                                      | `toolbar`    | ✓    |\n| key       | 插件唯一标识符，用于后续更新                     | string                                                                                      | -            |      |\n| className | 工具栏DOM元素的额外CSS类名                       | string                                                                                      | -            |      |\n| position  | 工具栏位置，相对于画布，[可选值](#position)      | string                                                                                      | `'top-left'` |      |\n| style     | 工具栏DOM元素的自定义样式，[常用值](#style-属性) | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| getItems  | 返回工具栏项目列表                               | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -            | ✓    |\n| onClick   | 工具栏项目点击后的回调函数                       | (value: string, target: Element) => void                                                    | -            |      |\n\n### position\n\n`position` 参数支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n### style 属性\n\n| 属性            | 描述     | 类型   | 默认值              |\n| --------------- | -------- | ------ | ------------------- |\n| backgroundColor | 背景颜色 | string | `#fff`              |\n| border          | 边框     | string | `1px solid #e8e8e8` |\n| borderRadius    | 圆角     | string | `4px`               |\n| height          | 高度     | string | `auto`              |\n| margin          | 外边距   | string | `12px`              |\n| opacity         | 透明度   | number | 0.9                 |\n| padding         | 内边距   | string | `8px`               |\n| width           | 宽度     | string | `auto`              |\n\n### ToolbarItem\n\n每个工具栏项目 (ToolbarItem) 包含以下属性：\n\n| 属性  | 描述                                            | 类型     | 必选 |\n| ----- | ----------------------------------------------- | -------- | ---- |\n| id    | 项目的图标ID，内置图标ID见[内置图标](#内置图标) | `string` | ✓    |\n| value | 点击项目时返回的值                              | `string` | ✓    |\n\n### 内置图标\n\nToolbar 提供以下内置图标 ID：\n\n- `'zoom-in'`：放大\n- `'zoom-out'`：缩小\n- `'redo'`：重做\n- `'undo'`：撤销\n- `'edit'`：编辑\n- `'delete'`：删除\n- `'auto-fit'`：自适应视图\n- `'export'`：导出图表\n- `'reset'`：重置视图\n- `'request-fullscreen'`：请求全屏\n- `'exit-fullscreen'`：退出全屏\n\n### 自定义图标\n\n除了使用内置图标外，还可以通过引入第三方图标库（如阿里巴巴 iconfont）来使用自定义图标：\n\n```js\n// 引入 iconfont 脚本\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // 替换为你的 iconfont 脚本地址\ndocument.head.appendChild(iconFont);\n\n// 在工具栏中使用自定义图标\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // 使用 iconfont 中的图标\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 注意：自定义图标的 ID 通常以 `icon-` 开头，需要与引入的 iconfont 中的图标名称对应。\n\n## 代码示例\n\n### 基础工具栏\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo、undo 需要配合 history 插件使用\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### 自定义样式\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 常用的样式属性包括：\n>\n> - `backgroundColor`：背景颜色\n> - `padding`：内边距\n> - `margin`/`marginTop`/`marginLeft` 等：外边距\n> - `border`：边框\n> - `borderRadius`：圆角\n> - `boxShadow`：阴影效果\n> - `opacity`：透明度\n> - `width`/`height`：宽高（默认自适应内容）\n> - `zIndex`：层级（默认为 100）\n> - `display`：显示方式（默认为 flex）\n\n工具栏容器默认设置 `display: flex`，子项目默认使用行布局（或根据 position 配置的方向改变）。你可以通过 `style` 自定义其外观和位置。\n\n### 异步加载工具栏项\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 工具栏图标不显示？\n\n- 检查是否使用了正确的内置图标 ID\n- 确保 CSS 样式未被覆盖或冲突\n\n### 2. 如何结合其他插件使用？\n\n工具栏常常与其他插件（如历史记录）配合使用：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// 更新工具栏位置\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/plugin/Tooltip.en.md":"---\ntitle: Tooltip\norder: 16\n---\n\n## Overview\n\nThe Tooltip plugin is used to display additional information when users hover over or click on elements in the graph. It helps users better understand the data in the graph and improves the interactive experience.\n\n## Use Cases\n\n- **Detailed Information Display**: When users need to understand detailed information about elements, use Tooltip to display this information\n- **Data Visualization Assistance**: In data visualization, Tooltip can display detailed information about data points in charts, helping users better understand the data\n- **Interactive Feedback**: Provide immediate visual feedback for user mouse operations\n\n## Basic Usage\n\nThe simplest Tooltip plugin configuration:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property     | Description               | Type                                                                                                                                          | Default Value                         | Required |\n| ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------- |\n| type         | Plugin type               | string                                                                                                                                        | `tooltip`                             | ✓        |\n| key          | Identifier                | string                                                                                                                                        | -                                     |          |\n| position     | Tooltip position          | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                                        | `top-right`                           |          |\n| enable       | Whether plugin is enabled | boolean \\| ((event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |          |\n| getContent   | Custom content            | (event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |          |\n| onOpenChange | Show/hide callback        | (open: boolean) => void                                                                                                                       | -                                     |          |\n| trigger      | Trigger behavior          | `hover` \\| `click`                                                                                                                            | `hover`                               |\n| container    | Custom render container   | string \\| HTMLElement                                                                                                                         | -                                     |          |\n| offset       | Offset distance           | [number,number]                                                                                                                               | [10,10]                               |          |\n| enterable    | Whether pointer can enter | boolean                                                                                                                                       | false                                 |          |\n| title        | Title                     | string                                                                                                                                        | -                                     |\n| style        | Style object              | Record<string,any>                                                                                                                            | {'.tooltip': { visibility: 'hidden'}} |          |\n\n## Detailed Configuration\n\n### enable - Conditional Enable\n\nControls whether the plugin is enabled, supports passing functions to dynamically adjust enable logic.\n\n**Example: Enable Tooltip only for nodes**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Server Node' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Database Node' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: 'Connection' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // Enable only for nodes, not for edges\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>Node: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - Custom Content\n\nCustomize Tooltip content rendering, supports returning HTMLElement or string.\n\n**Example: Dynamically render custom HTML content**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: 'Server A', type: 'Application Server', status: 'Running', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: 'Database B', type: 'MySQL Database', status: 'Normal', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Type:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Status:</strong>\n                <span style=\"color: ${item.data.status === 'Running' || item.data.status === 'Normal' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Memory:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Connections:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Size:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">Connection Info</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Bandwidth:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Latency:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return 'No information available';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - Trigger Mode\n\nControls the trigger behavior of Tooltip.\n\n**Available values:**\n\n- `hover`: Trigger when mouse enters element (default)\n- `click`: Trigger when mouse clicks element\n\n**Example: Click-triggered Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Click me' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Click me too' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              Click Triggered 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              Element ID: ${items[0].id}<br/>\n              Name: ${items[0].data?.name || 'Unnamed'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - Display Position\n\nControls the display position of Tooltip relative to mouse position.\n\n**Available values:**\n\n- `top`: Top\n- `bottom`: Bottom\n- `left`: Left\n- `right`: Right\n- `top-left`: Top left\n- `top-right`: Top right (default)\n- `bottom-left`: Bottom left\n- `bottom-right`: Bottom right\n\n**Example: Tooltips at different positions**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Display at top ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Display at bottom ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `Display at left ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `Display at right ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - Offset\n\nSet the offset for Tooltip display position, with mouse position as the base point.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'Default offset' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'Custom offset' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Default offset [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // Offset 30px to the right, 10px up\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Custom offset [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - Mouse Enterable\n\nControls whether the mouse pointer can enter the tooltip box, commonly used for scenarios requiring interaction within the Tooltip.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'User A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: 'User B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">User Actions</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>Name:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>Email:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('Send message to ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Message\n              </button>\n              <button onclick=\"alert('View ${item.data.name} details')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Details\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - Style Customization\n\nCustomize Tooltip styles.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: 'Dark Theme' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: 'Light Theme' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Basic Tooltip](/en/examples/plugin/tooltip/#basic)\n- [Click-triggered Tooltip](/en/examples/plugin/tooltip/#click)\n- [Different tooltips for hover and click on the same element](/en/examples/plugin/tooltip/#dual)\n- [Custom styled Tooltip](/en/examples/plugin/tooltip/#custom-style)\n- [Asynchronous content loading Tooltip](/en/examples/plugin/tooltip/#async)\n\n## API\n","packages/site/docs/manual/plugin/Tooltip.zh.md":"---\ntitle: 提示框 Tooltip\norder: 16\n---\n\n## 概述\n\nTooltip 插件用于在用户将鼠标悬停或点击图中的元素时，显示额外的信息。它可以帮助用户更好地理解图中的数据，提高交互体验。\n\n## 使用场景\n\n- **详细信息展示**：当用户需要了解元素的详细信息时，使用 Tooltip 提示框来展示这些信息\n- **数据可视化辅助**：在数据可视化中，Tooltip 可以显示图表中数据点的详细信息，帮助用户更好地理解数据\n- **交互反馈**：为用户的鼠标操作提供即时的视觉反馈\n\n## 基本使用\n\n最简单的 Tooltip 插件配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性         | 描述                    | 类型                                                                                                                            | 默认值                                | 必选 |\n| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ---- |\n| type         | 插件类型                | string                                                                                                                          | `tooltip`                             | ✓    |\n| key          | 标识符                  | string                                                                                                                          | -                                     |      |\n| position     | 气泡框位置              | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                          | `top-right`                           |      |\n| enable       | 插件是否启用            | boolean \\| ((event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |      |\n| getContent   | 自定义内容              | (event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |      |\n| onOpenChange | 显示隐藏的回调          | (open: boolean) => void                                                                                                         | -                                     |      |\n| trigger      | 触发行为                | `hover` \\| `click`                                                                                                              | `hover`                               |\n| container    | tooltip自定义渲染的容器 | string \\| HTMLElement                                                                                                           | -                                     |      |\n| offset       | 偏移距离                | [number,number]                                                                                                                 | [10,10]                               |      |\n| enterable    | 指针是否可以进入        | boolean                                                                                                                         | false                                 |      |\n| title        | 标题                    | string                                                                                                                          | -                                     |\n| style        | 样式对象                | Record<string,any>                                                                                                              | {'.tooltip': { visibility: 'hidden'}} |      |\n\n## 详细配置说明\n\n### enable - 条件启用\n\n控制插件是否启用，支持传入函数动态调整启用逻辑。\n\n**示例：只对节点启用 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '服务器节点' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '数据库节点' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: '连接线' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // 只对节点启用，边不显示tooltip\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>节点: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - 自定义内容\n\n自定义渲染 Tooltip 内容，支持返回 HTMLElement 或 string。\n\n**示例：动态渲染自定义 HTML 内容**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: '服务器A', type: '应用服务器', status: '运行中', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: '数据库B', type: 'MySQL数据库', status: '正常', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>类型:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>状态:</strong>\n                <span style=\"color: ${item.data.status === '运行中' || item.data.status === '正常' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>内存:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>连接数:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>大小:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">连接信息</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>带宽:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>延迟:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return '暂无信息';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - 触发方式\n\n控制 Tooltip 的触发行为。\n\n**可选值：**\n\n- `hover`：鼠标移入元素时触发（默认）\n- `click`：鼠标点击元素时触发\n\n**示例：点击触发 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '点击我' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '也点击我' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              点击触发 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              元素ID: ${items[0].id}<br/>\n              名称: ${items[0].data?.name || '未命名'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - 显示位置\n\n控制 Tooltip 相对于鼠标位置的显示位置。\n\n**可选值：**\n\n- `top`: 顶部\n- `bottom`: 底部\n- `left`: 左侧\n- `right`: 右侧\n- `top-left`: 顶部靠左\n- `top-right`: 顶部靠右（默认）\n- `bottom-left`: 底部靠左\n- `bottom-right`: 底部靠右\n\n**示例：不同位置的 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `顶部显示 ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `底部显示 ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `左侧显示 ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `右侧显示 ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - 偏移量\n\n设置 Tooltip 显示位置的偏移量，以鼠标位置为基点。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: '默认偏移' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: '自定义偏移' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `默认偏移 [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // 向右偏移30px，向上偏移10px\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `自定义偏移 [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - 鼠标可进入\n\n控制鼠标指针是否可以进入气泡框，常用于需要在 Tooltip 内进行交互的场景。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '用户A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: '用户B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">用户操作</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>姓名:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>邮箱:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('发送消息给 ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                发消息\n              </button>\n              <button onclick=\"alert('查看 ${item.data.name} 的详情')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                详情\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - 样式自定义\n\n自定义 Tooltip 的样式。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: '深色主题' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: '浅色主题' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [基础提示框](/examples/plugin/tooltip/#basic)\n- [点击触发 Tooltip](/examples/plugin/tooltip/#click)\n- [鼠标移入和点击同一元素时显示不同的提示框](/examples/plugin/tooltip/#dual)\n- [自定义样式的 Tooltip](/examples/plugin/tooltip/#custom-style)\n- [异步加载内容的 Tooltip](/examples/plugin/tooltip/#async)\n","packages/site/docs/manual/plugin/Watermark.en.md":"---\ntitle: Watermark\norder: 17\n---\n\n## Overview\n\nThe watermark plugin supports using text and images as watermarks. The principle is to add a `background-image` attribute to the div of the Graph container, and then control the position and style of the watermark through CSS. For text watermarks, a hidden canvas is used to convert the text into an image.\n\n## Use Cases\n\n- Add copyright or ownership marks to charts\n- Mark the status of charts during presentations or previews\n- Add anti-leakage marks to sensitive data\n\n## Basic Usage\n\nBelow is a simple example of initializing the Watermark plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // Watermark text\n      opacity: 0.2, // Opacity\n      rotate: Math.PI / 12, // Rotation angle\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## Configuration Options\n\n| Property             | Description                                              | Type                                                                        | Default Value | Required |\n| -------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | -------- |\n| type                 | Plugin type                                              | string                                                                      | `watermark`   | ✓        |\n| width                | Width of a single watermark                              | number                                                                      | 200           |          |\n| height               | Height of a single watermark                             | number                                                                      | 100           |          |\n| opacity              | Opacity of the watermark                                 | number                                                                      | 0.2           |          |\n| rotate               | Rotation angle of the watermark                          | number                                                                      | Math.PI / 12  |          |\n| imageURL             | Image watermark URL, higher priority than text watermark | string                                                                      | -             |          |\n| text                 | Watermark text content                                   | string                                                                      | -             |          |\n| textFill             | Color of the text watermark                              | string                                                                      | `#000`        |          |\n| textFontSize         | Font size of the text watermark                          | number                                                                      | 16            |          |\n| textFontFamily       | Font of the text watermark                               | string                                                                      | -             |          |\n| textFontWeight       | Font weight of the text watermark                        | string                                                                      | -             |          |\n| textFontVariant      | Font variant of the text watermark                       | string                                                                      | -             |          |\n| textAlign            | Text alignment of the watermark                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`      |          |\n| textBaseline         | Baseline alignment of the text watermark                 | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`      |          |\n| backgroundRepeat     | Repeat mode of the watermark                             | string                                                                      | `repeat`      |          |\n| backgroundAttachment | Background attachment behavior of the watermark          | string                                                                      | -             |          |\n| backgroundBlendMode  | Background blend mode of the watermark                   | string                                                                      | -             |          |\n| backgroundClip       | Background clip of the watermark                         | string                                                                      | -             |          |\n| backgroundColor      | Background color of the watermark                        | string                                                                      | -             |          |\n| backgroundImage      | Background image of the watermark                        | string                                                                      | -             |          |\n| backgroundOrigin     | Background origin of the watermark                       | string                                                                      | -             |          |\n| backgroundPosition   | Background position of the watermark                     | string                                                                      | -             |          |\n| backgroundPositionX  | Horizontal position of the watermark background          | string                                                                      | -             |          |\n| backgroundPositionY  | Vertical position of the watermark background            | string                                                                      | -             |          |\n| backgroundSize       | Background size of the watermark                         | string                                                                      | -             |          |\n\n## Code Examples\n\n### Text Watermark\n\nThe simplest text watermark configuration:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Image Watermark\n\nUse an image as a watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style and position of the watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // Set font size\n      textFontFamily: 'Arial', // Set font\n      textFontWeight: 'bold', // Set font weight\n      textFill: '#1890ff', // Set text color\n      rotate: Math.PI / 6, // Set rotation angle\n      opacity: 0.15, // Set opacity\n      width: 180, // Set watermark width\n      height: 100, // Set watermark height\n      backgroundRepeat: 'space', // Set repeat mode\n      backgroundPosition: 'center', // Set position\n      textAlign: 'center', // Set text alignment\n      textBaseline: 'middle', // Set baseline alignment\n    },\n  ],\n});\n```\n\n## Real Cases\n\n- [Text Watermark](/examples/plugin/watermark/#text)\n- [Image Watermark](/examples/plugin/watermark/#repeat)\n","packages/site/docs/manual/plugin/Watermark.zh.md":"---\ntitle: 水印 Watermark\norder: 17\n---\n\n## 概述\n\n水印插件支持使用文本和图片作为水印，实现原理是在 Graph 容器的 div 上加上 `background-image` 属性，然后通过 CSS 来控制水印的位置和样式。对于文本水印，会使用隐藏 canvas 将文本转换为图片的方式来实现。\n\n## 使用场景\n\n- 为图表添加版权或所有权标识\n- 在演示或预览时标记图表的状态\n- 为敏感数据添加防泄露标记\n\n## 基本用法\n\n以下是一个简单的 Watermark 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // 水印文本\n      opacity: 0.2, // 透明度\n      rotate: Math.PI / 12, // 旋转角度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## 配置项\n\n| 属性                 | 描述                               | 类型                                                                        | 默认值       | 必选 |\n| -------------------- | ---------------------------------- | --------------------------------------------------------------------------- | ------------ | ---- |\n| type                 | 插件类型                           | string                                                                      | `watermark`  | ✓    |\n| width                | 单个水印的宽度                     | number                                                                      | 200          |      |\n| height               | 单个水印的高度                     | number                                                                      | 100          |      |\n| opacity              | 水印的透明度                       | number                                                                      | 0.2          |      |\n| rotate               | 水印的旋转角度                     | number                                                                      | Math.PI / 12 |      |\n| imageURL             | 图片水印的地址，优先级高于文本水印 | string                                                                      | -            |      |\n| text                 | 水印文本内容                       | string                                                                      | -            |      |\n| textFill             | 文本水印的颜色                     | string                                                                      | `#000`       |      |\n| textFontSize         | 文本水印的字体大小                 | number                                                                      | 16           |      |\n| textFontFamily       | 文本水印的字体                     | string                                                                      | -            |      |\n| textFontWeight       | 文本水印的字体粗细                 | string                                                                      | -            |      |\n| textFontVariant      | 文本水印的字体变体                 | string                                                                      | -            |      |\n| textAlign            | 文本水印的对齐方式                 | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`     |      |\n| textBaseline         | 文本水印的基线对齐方式             | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`     |      |\n| backgroundRepeat     | 水印的重复方式                     | string                                                                      | `repeat`     |      |\n| backgroundAttachment | 水印的背景定位行为                 | string                                                                      | -            |      |\n| backgroundBlendMode  | 水印的背景混合模式                 | string                                                                      | -            |      |\n| backgroundClip       | 水印的背景裁剪                     | string                                                                      | -            |      |\n| backgroundColor      | 水印的背景颜色                     | string                                                                      | -            |      |\n| backgroundImage      | 水印的背景图片                     | string                                                                      | -            |      |\n| backgroundOrigin     | 水印的背景原点                     | string                                                                      | -            |      |\n| backgroundPosition   | 水印的背景位置                     | string                                                                      | -            |      |\n| backgroundPositionX  | 水印的背景水平位置                 | string                                                                      | -            |      |\n| backgroundPositionY  | 水印的背景垂直位置                 | string                                                                      | -            |      |\n| backgroundSize       | 水印的背景大小                     | string                                                                      | -            |      |\n\n## 代码示例\n\n### 文本水印\n\n最简单的文本水印配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 图片水印\n\n使用图片作为水印：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义水印的样式和位置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // 设置字体大小\n      textFontFamily: 'Arial', // 设置字体\n      textFontWeight: 'bold', // 设置字体粗细\n      textFill: '#1890ff', // 设置文字颜色\n      rotate: Math.PI / 6, // 设置旋转角度\n      opacity: 0.15, // 设置透明度\n      width: 180, // 设置水印宽度\n      height: 100, // 设置水印高度\n      backgroundRepeat: 'space', // 设置重复方式\n      backgroundPosition: 'center', // 设置位置\n      textAlign: 'center', // 设置文本对齐\n      textBaseline: 'middle', // 设置基线对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n- [文本水印](/examples/plugin/watermark/#text)\n- [图片水印](/examples/plugin/watermark/#repeat)\n","packages/site/docs/manual/plugin/custom-plugin.en.md":"---\ntitle: Custom Plugin\norder: 20\n---\n\n## Overview\n\nCustom plugins can implement additional features, such as adding extra components, rendering logic, etc. Custom plugins can effectively achieve functional decoupling, better manage and orchestrate code, and facilitate subsequent maintenance.\n\n## Use Cases\n\n### Add extra components, rendering logic, etc.\n\n- **Extra components**: Such as built-in plugins like `Tooltip`, `Minimap`, `Snapline`, `Grid`, `Context Menu`, `Watermark`, etc.\n- **Rendering logic**: Such as built-in plugins like `Edge Bundling`, and `Remote Data Loading` ([Example](#remote-data-loading)), etc.\n\n### When built-in plugins cannot meet the requirements\n\nWhen built-in plugins cannot fully meet business needs, users can also make adjustments and modifications through custom plugins (inheriting built-in plugins).\n\n_(If the features supported by built-in plugins are more general, or if there are bugs in built-in plugins, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Custom Plugin Examples\n\nLike interactions, the implementation of plugins is also quite flexible, and you can implement your plugin in your preferred style.\n\nHere are a few simple custom plugin implementations:\n\n### Remote Data Loading\n\nAutomatically load remote data during graph instantiation:\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- In this example, we simulate a data loading plugin. After using this plugin, there is no need to pass data when instantiating the Graph, as the plugin will automatically load remote data.\n\n- `BasePlugin` is the base class for all plugins, and each custom plugin needs to inherit this base class.\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### Automatically Enable or Disable Animation Based on Node Count\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // Disable global animation when the number of nodes reaches this value\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In this example, we listen to the `GraphEvent.BEFORE_RENDER` event and determine whether the current number of nodes exceeds a specified value. If so, global animation is disabled; otherwise, it is enabled.\n- `maxLength` is a defined configuration item that can be passed in when initializing the graph instance. [Plugin Configuration](#configure-plugin)\n\n## Register Plugin\n\nRegister using the method provided by G6\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## Configure Plugin\n\n- You can pass the plugin type name or configuration parameter object in `plugins`, see [Configure Plugin](/manual/plugin/overview#configuration-method)\n\n- For example, the previous [Automatically Enable or Disable Animation Based on Node Count](#automatically-enable-or-disable-animation-based-on-node-count) is configured as follows:\n\n  ```typescript\n  const graph = new Graph({\n    // Other configurations\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","packages/site/docs/manual/plugin/custom-plugin.zh.md":"---\ntitle: 自定义插件\norder: 20\n---\n\n## 概述\n\n自定义插件可以实现一些额外的功能，例如添加额外的组件、渲染逻辑等。通过自定义插件可以很好地实现功能解耦，更好地进行管理、编排代码以及后续维护。\n\n## 使用场景\n\n### 添加额外的组件、渲染逻辑等\n\n- **额外的组件**：如内置插件的`提示框`、`小地图`、`对齐线`、`网格线`、`上下文菜单`、`水印`等\n- **渲染逻辑**：如内置插件的`边绑定`，以及`远程数据加载`（[示例](#远程数据加载)）等\n\n### 内置插件无法满足需求\n\n当内置插件无法完全满足业务需求时，用户也可以通过自定义插件（继承内置插件）进行调整和修改。\n\n_（如果需要内置插件支持的特性是较通用的，或者内置插件存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 自定义插件示例\n\n与交互类似，插件的实现也相当灵活，你可以以你喜欢的风格实现你的插件。\n\n下面列举几个简单的自定义插件实现：\n\n### 远程数据加载\n\n在图实例化过程中自动加载远程数据：\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- 在这个例子中，我们模拟实现了一个数据加载插件，在使用该插件后，实例化 Graph 时不用再传入数据，该插件会自动加载远程数据。\n\n- `BasePlugin` 是所有插件的基类，每个自定义插件都需要继承这个基类实现。\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### 自动判断节点数量开启或关闭动画\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // 节点数量达到这个值后关闭全局动画\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在这个例子中，我们监听 `GraphEvent.BEFORE_RENDER` 事件，在响应中判断当前节点数量是否大于指定值，是的话则关闭全局动画，否则开启\n- `maxLength` 是定义的配置项，可在初始化画布实例时传入具体配置，[插件配置](#配置插件)\n\n## 注册插件\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## 配置插件\n\n- 可在 `plugins` 中传入插件类型名称或配置参数对象，详见[配置插件](/manual/plugin/overview#配置方式)\n\n- 比如前面的[自动判断节点数量开启或关闭动画](#自动判断节点数量开启或关闭动画)，配置如下：\n\n  ```typescript\n  const graph = new Graph({\n    // 其他配置\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","packages/site/docs/manual/plugin/overview.en.md":"---\ntitle: Plugin Overview\norder: 0\n---\n\n## What is a Plugin\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nA Plugin is the most flexible extension mechanism in G6, allowing users to extend G6's functionality, such as adding graphical components to the canvas or implementing undo/redo features.\n\nMost customization needs can be achieved through plugins. G6 comes with some built-in plugins, such as: [Tooltip](/en/manual/plugin/tooltip), [Grid](/en/manual/plugin/grid-line), [History](/en/manual/plugin/history).\n\n## Built-in Plugins\n\nG6 provides a rich set of built-in plugins covering various common functional scenarios:\n\n| Category                     | Plugin Name                                                                                         | Registration Type  | Description                                                            |\n| ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |\n| **Visual Style Enhancement** |                                                                                                     |                    |                                                                        |\n|                              | [Grid Line](/en/manual/plugin/grid-line)                                                            | `grid-line`        | Displays grid reference lines on the canvas                            |\n|                              | [Background](/en/manual/plugin/background)                                                          | `background`       | Adds background images or colors to the canvas                         |\n|                              | [Watermark](/en/manual/plugin/watermark)                                                            | `watermark`        | Adds a watermark to the canvas to protect copyright                    |\n|                              | [Hull](/en/manual/plugin/hull)                                                                      | `hull`             | Creates an outline for a specified set of nodes                        |\n|                              | [Bubble Sets](/en/manual/plugin/bubble-sets)                                                        | `bubble-sets`      | Creates smooth bubble-like element outlines                            |\n|                              | [Snapline](/en/manual/plugin/snapline)                                                              | `snapline`         | Displays alignment reference lines when dragging elements              |\n| **Navigation and Overview**  |                                                                                                     |                    |                                                                        |\n|                              | [Minimap](/en/manual/plugin/minimap)                                                                | `minimap`          | Displays a thumbnail preview of the graph, supporting navigation       |\n|                              | [Fullscreen](/en/manual/plugin/fullscreen)                                                          | `fullscreen`       | Supports full-screen display and exit for charts                       |\n|                              | [Timebar](/en/manual/plugin/timebar)                                                                | `timebar`          | Provides filtering and playback control for temporal data              |\n| **Interactive Controls**     |                                                                                                     |                    |                                                                        |\n|                              | [Toolbar](/en/manual/plugin/toolbar)                                                                | `toolbar`          | Provides a collection of common operation buttons                      |\n|                              | [Context Menu](/en/manual/plugin/contextmenu)                                                       | `contextmenu`      | Displays a menu of selectable operations on right-click                |\n|                              | [Tooltip](/en/manual/plugin/tooltip)                                                                | `tooltip`          | Displays detailed information about elements on hover                  |\n|                              | [Legend](/en/manual/plugin/legend)                                                                  | `legend`           | Displays categories and corresponding style descriptions of chart data |\n| **Data Exploration**         |                                                                                                     |                    |                                                                        |\n|                              | [Fisheye](/en/manual/plugin/fisheye)                                                                | `fisheye`          | Provides a focus + context exploration experience                      |\n|                              | [Edge Filter Lens](/en/manual/plugin/edge-filter-lens)                                              | `edge-filter-lens` | Filters and displays edges within a specified area                     |\n|                              | [Edge Bundling](/en/manual/plugin/edge-bundling)                                                    | `edge-bundling`    | Bundles edges with similar paths together to reduce visual clutter     |\n| **Advanced Features**        |                                                                                                     |                    |                                                                        |\n|                              | [History](/en/manual/plugin/history)                                                                | `history`          | Supports undo/redo operations                                          |\n|                              | [Camera Setting](/enhttps://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | Configures camera parameters in a 3D scene                             |\n\nFor detailed configuration of each plugin, refer to the [Built-in Plugin Documentation](/en/manual/plugin/grid-line).\n\n## Configuration Methods\n\n### Basic Configuration\n\nSpecify the required plugins through the `plugins` array when initializing the graph instance:\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### Configuring Plugin Parameters\n\nFor plugins that require custom parameters, you can configure properties using the `object` form:\n\n```javascript {5-9}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // Specify a key for the plugin for future updates\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### Dynamically Updating Plugins\n\nG6 supports dynamic management of plugins during the runtime of the graph instance to meet complex interaction needs:\n\nUse the [getPlugins](/en/api/plugin#graphgetplugins) method to get the current list of plugins:\n\n```javascript\n// Get the list of plugins\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\nYou can adjust plugins using the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method:\n\n```javascript\n// Add a new plugin\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// Remove a plugin\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\nYou can update the configuration of a plugin using the [updatePlugin](/en/api/plugin#graphupdatepluginplugin) method:\n\n```javascript {6,14}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n\n// Update a single plugin\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>Updated content: ${e.target.id}</div>`,\n});\n```\n\n:::warning{title=Note}\nWhen using the `updatePlugin` method, you need to specify a unique `key` for the plugin during initialization.\n:::\n\n### Uninstalling Plugins\n\nUse the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method to uninstall plugins by setting the plugin configuration list to empty:\n\n```javascript\n// Uninstall all plugins\ngraph.setPlugins([]);\n```\n\n### Calling Plugin Methods\n\nSome plugins provide API methods for users to call, such as the `history` plugin providing `undo` and `redo` methods, allowing users to implement undo and redo operations by calling these methods.\n\nTo call these methods, you need to first get the plugin instance, which can be obtained through the [getPluginInstance](/en/api/plugin#graphgetplugininstancekey) method:\n\n```javascript\n// Configure the plugin\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// Get the plugin instance\nconst history = graph.getPluginInstance('my-history');\n\n// Call plugin methods\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=Note}\nThe `graph.getPluginInstance` method takes the plugin key value as a parameter, so if you need to get the plugin instance, you need to configure the corresponding plugin in the form of an `object` and pass in the `key` value.\n:::\n\nFor more plugin-related APIs, please refer to the [Plugin API Documentation](/en/api/plugin).\n\n## Custom Plugins\n\nWhen built-in plugins cannot meet your needs, you can:\n\n- Inherit and extend existing plugins\n- Create brand new custom plugins\n\nCustom plugins need to be registered before use. For detailed tutorials, please refer to the [Custom Plugin](/en/manual/plugin/custom-plugin) documentation.\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// Register custom plugin\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// Use custom plugin\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\nBy reasonably combining and configuring plugins, you can build graph visualization applications with rich features and excellent interactive experiences.\n","packages/site/docs/manual/plugin/overview.zh.md":"---\ntitle: 插件总览\norder: 0\n---\n\n## 什么是插件\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n插件(Plugin)是 G6 中最灵活的扩展机制，用户可以通过插件来扩展 G6 的功能，例如在画布中额外挂载图形组件、实现撤销重做等功能。\n\n绝大多数的定制需求都可以通过插件来实现，G6 内置了一些常用的插件，例如：[Tooltip](/manual/plugin/tooltip)、[Grid](/manual/plugin/grid-line)、[History](/manual/plugin/history)。\n\n## 内置插件\n\nG6 提供了丰富的内置插件，涵盖多种常见功能场景：\n\n| 分类             | 插件名称                                                                                   | 注册类型           | 功能描述                               |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------ | -------------------------------------- |\n| **视觉样式增强** |                                                                                            |                    |                                        |\n|                  | [网格线](/manual/plugin/grid-line)                                                         | `grid-line`        | 在画布上显示网格参考线                 |\n|                  | [背景](/manual/plugin/background)                                                          | `background`       | 为画布添加背景图片或颜色               |\n|                  | [水印](/manual/plugin/watermark)                                                           | `watermark`        | 为画布添加水印，保护版权               |\n|                  | [轮廓包围](/manual/plugin/hull)                                                            | `hull`             | 为指定节点集合创建轮廓                 |\n|                  | [气泡集](/manual/plugin/bubble-sets)                                                       | `bubble-sets`      | 创建平滑气泡状的元素集合轮廓           |\n|                  | [对齐线](/manual/plugin/snapline)                                                          | `snapline`         | 拖动元素时显示对齐参考线               |\n| **导航与概览**   |                                                                                            |                    |                                        |\n|                  | [缩略图](/manual/plugin/minimap)                                                           | `minimap`          | 显示图的缩略预览，支持导航             |\n|                  | [全屏](/manual/plugin/fullscreen)                                                          | `fullscreen`       | 支持图表全屏显示和退出                 |\n|                  | [时间轴](/manual/plugin/timebar)                                                           | `timebar`          | 提供时序数据的筛选和播放控制           |\n| **交互控件**     |                                                                                            |                    |                                        |\n|                  | [工具栏](/manual/plugin/toolbar)                                                           | `toolbar`          | 提供常用操作按钮集合                   |\n|                  | [上下文菜单](/manual/plugin/contextmenu)                                                   | `contextmenu`      | 右键点击时显示可选操作菜单             |\n|                  | [提示框](/manual/plugin/tooltip)                                                           | `tooltip`          | 悬停时显示元素详细信息                 |\n|                  | [图例](/manual/plugin/legend)                                                              | `legend`           | 显示图表数据的类别和对应样式说明       |\n| **数据探索**     |                                                                                            |                    |                                        |\n|                  | [鱼眼放大镜](/manual/plugin/fisheye)                                                       | `fisheye`          | 提供焦点+上下文的探索体验              |\n|                  | [边过滤镜](/manual/plugin/edge-filter-lens)                                                | `edge-filter-lens` | 在指定区域内筛选显示边                 |\n|                  | [边绑定](/manual/plugin/edge-bundling)                                                     | `edge-bundling`    | 将相似路径的边捆绑在一起，减少视觉混乱 |\n| **高级功能**     |                                                                                            |                    |                                        |\n|                  | [历史记录](/manual/plugin/history)                                                         | `history`          | 支持撤销/重做操作                      |\n|                  | [相机设置](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | 配置3D场景下的相机参数                 |\n\n各插件的详细配置可参考 [内置插件文档](/manual/plugin/grid-line)。\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `plugins` 数组指定需要的插件：\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### 配置插件参数\n\n对于需要自定义参数的插件，可以使用 `object` 形式配置属性：\n\n```javascript {5-9}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // 为插件指定key，便于后续更新\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### 动态更新插件\n\nG6 支持在图实例运行期间动态管理插件，满足复杂交互需求：\n\n通过 [getPlugins](/api/plugin#graphgetplugins) 方法获取当前插件列表：\n\n```javascript\n// 获取插件列表\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\n可以通过 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法调整插件：\n\n```javascript\n// 添加新插件\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// 移除插件\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\n可以通过 [updatePlugin](/api/plugin#graphupdatepluginplugin) 方法更新插件的配置：\n\n```javascript {6,14}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n\n// 更新单个插件\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>更新的内容：${e.target.id}</div>`,\n});\n```\n\n:::warning{title=注意}\n使用 `updatePlugin` 方法时，需要在初始化时为插件指定唯一的 `key`。\n:::\n\n### 卸载插件\n\n使用 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法同样可以卸载插件，将插件配置列表置为空即可：\n\n```javascript\n// 卸载所有插件\ngraph.setPlugins([]);\n```\n\n### 调用插件方法\n\n一些插件提供了可供用户调用的 API 方法，例如 `history` 插件提供了 `undo` 和 `redo` 方法，用户可以通过调用这些方法来实现撤销和重做操作。\n\n要调用这些方法，需要先获取到插件实例，可通过 [getPluginInstance](/api/plugin#graphgetplugininstancekey) 方法获取：\n\n```javascript\n// 配置插件\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// 获取插件实例\nconst history = graph.getPluginInstance('my-history');\n\n// 调用插件方法\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=注意}\n`graph.getPluginInstance` 方法接收插件 key 值作为参数，因此如果需要获取插件实例，需要将对应插件配置为 `object` 的形式，并传入 `key` 值。\n:::\n\n更多与插件相关的 API 请参考 [插件 API 文档](/api/plugin)。\n\n## 自定义插件\n\n当内置插件无法满足需求时，你可以：\n\n- 继承和扩展现有插件\n- 创建全新的自定义插件\n\n自定义插件需要先注册后使用。详细教程请参考 [自定义插件](/manual/plugin/custom-plugin) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// 注册自定义插件\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// 使用自定义插件\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\n通过合理组合和配置插件，你可以构建出功能丰富、交互体验出色的图可视化应用。\n","packages/site/docs/manual/theme/custom-palette.en.md":"---\ntitle: Custom Palette\norder: 4\n---\n\n## Overview\n\n[Core Concepts - Palette](/en/manual/core-concept/palette) mentions that G6 supports discrete palettes and continuous palettes. A discrete palette is essentially an array of colors, while a continuous palette is a color interpolator.\n\nTherefore, customizing a palette also adopts these two methods, and the following sections will introduce how to customize discrete and continuous palettes, respectively.\n\n## Implement Palette\n\n### Discrete Palette\n\nYou can simply define a string array that contains color values. Supported color values include: RGB color values, hexadecimal color values, and color names. Below is an example of a discrete palette:\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### Continuous Palette\n\nA continuous palette requires the definition of a color interpolator. The interpolator is a function that accepts a numerical value as a parameter and returns a color value. Below is an example of a continuous palette:\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can register a palette using the `register` method provided by G6. For more details, please refer to [Register Palette](/en/manual/core-concept/palette#register-palette)\n\n## Use Without Registration\n\nIn addition to registration, you can also bypass the registration mechanism and directly pass the palette value at the location where the palette is needed, for example:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // Pass in a color array.\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Pass in an interpolator\n    }\n  }\n}\n```\n","packages/site/docs/manual/theme/custom-palette.zh.md":"---\ntitle: 自定义色板\norder: 4\n---\n\n## 概述\n\n[色板](/manual/theme/palette) 中提到，G6 支持离散色板和连续色板，其中离散色板本质上是一个颜色数组，而连续色板是一个颜色插值器。\n\n因此自定义色板也采用这两种方式，下面分别介绍如何自定义离散色板和连续色板。\n\n## 实现色板\n\n### 离散色板\n\n直接定义一个包含颜色值的字符串数组即可，颜值值支持：RGB 色值、16 进制、颜色名，下面是一组离散色板示例：\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### 连续色板\n\n连续色板需要定义一个颜色插值器，插值器是一个函数，接受一个数值参数，返回一个颜色值，下面是一个连续色板示例：\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n通过 G6 提供的 register 方法注册即可，详见[注册色板](/manual/theme/palette#注册色板)\n\n## 非注册方式使用\n\n除此之外，你也可以在需要使用色板的位置跳过注册机制直接传入色板值，例如：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // 传入颜色数组\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 传入插值器\n    }\n  }\n}\n```\n","packages/site/docs/manual/theme/custom-theme.en.md":"---\ntitle: Custom Theme\norder: 2\n---\n\n## Overview\n\nIn G6, the theme is a subset of Graph Options and includes configurations related to the canvas and element styles. A theme can help you quickly switch between different graph styles.\n\n## Custom Theme\n\nFor element styles, the configurations within a theme are static and do not support the use of callback functions to dynamically calculate styles. Additionally, `type` is also not supported for configuration within a theme. A theme includes the following configurations:\n\n- `background`: Canvas background color\n- `node`: Node style\n- `edge`: Edge style\n- `combo`: Combo style\n\nBelow is a simple example of a theme configuration:\n\n```typescript\nconst theme = {\n  background: '#fff',\n  node: {\n    style: {\n      fill: '#e1f3fe',\n      lineWidth: 0,\n    },\n    selected: {\n      style: {\n        fill: '#3b71d6',\n        lineWidth: 1,\n      },\n    },\n  },\n  edge: {\n    // ...\n  },\n  combo: {\n    // ...\n  },\n};\n```\n\n❌ Incorrect Example\n\n```typescript\nconst theme = {\n  node: {\n    // ❌ The theme does not support configuring element types\n    type: 'rect',\n    style: {\n      // ❌ The theme does not support callback functions\n      fill: (d) => d.style.color,\n    },\n  },\n};\n```\n\n:::warning{title=Note}\nFor element state styles, please ensure that every property in the state style has a corresponding default style in the default style, otherwise it may result in the inability to clear the state style.\n:::\n\n## Register Theme\n\nYou can register a theme using the `register` method provided by G6. Here is an example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.THEME, 'custom-theme', theme);\n```\n\n## Configure Theme\n\nTo enable and configure a theme, you need to pass the `theme` option when instantiating the `Graph`:\n\n```typescript\n{\n  theme: 'custom-theme',\n}\n```\n\n### Switch Theme\n\nAfter the `Graph` instance is created, you can switch themes by using the [setTheme](/en/api/theme#graphsetthemetheme) method:\n\n```typescript\ngraph.setTheme('dark');\n```\n\nAdditionally, you can also obtain the current theme by using the `getTheme` method:\n\n```typescript\ngraph.getTheme();\n// => 'dark'\n```\n","packages/site/docs/manual/theme/custom-theme.zh.md":"---\ntitle: 自定义主题\norder: 2\n---\n\n除了使用内置主题外，G6 还支持创建自定义主题来满足特定的视觉需求。本文将介绍如何创建和使用自定义主题。\n\n## 创建自定义主题\n\n一个自定义主题需要遵循主题的基本结构，包含画布背景色和元素样式配置：\n\n```javascript\nconst customTheme = {\n  // 1. 画布背景色\n  background: '#f0f0f0',\n\n  // 2. 节点配置\n  node: {\n    // 调色板配置\n    palette: {\n      type: 'group',\n      color: ['#1783FF', '#00C9C9' /* 自定义颜色... */],\n    },\n    // 基础样式\n    style: {\n      fill: '#fff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他节点样式\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#e8f3ff',\n        stroke: '#1783FF',\n      },\n      // ... 其他状态样式\n    },\n  },\n\n  // 3. 边配置\n  edge: {\n    style: {\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他边样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n\n  // 4. Combo 配置\n  combo: {\n    style: {\n      fill: '#f7f7f7',\n      stroke: '#d9d9d9',\n      // ... 其他 Combo 样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n};\n```\n\n## 使用限制\n\n在创建自定义主题时，需要注意以下限制：\n\n1. **仅支持静态值**\n\n   ```javascript\n   // ❌ 错误示例：不支持回调函数\n   const theme = {\n     node: {\n       style: {\n         fill: (d) => d.style.color,\n       },\n     },\n   };\n   ```\n\n2. **不支持配置元素类型**\n\n   ```javascript\n   // ❌ 错误示例：不支持在主题中配置元素类型\n   const theme = {\n     node: {\n       type: 'rect',\n       style: {\n         fill: '#fff',\n       },\n     },\n   };\n   ```\n\n3. **状态样式需要对应默认样式**\n   ```javascript\n   // ✅ 正确示例：状态样式的属性在默认样式中都有定义\n   const theme = {\n     node: {\n       style: {\n         fill: '#fff',\n         stroke: '#000',\n       },\n       state: {\n         selected: {\n           fill: '#e8f3ff',\n           stroke: '#1783FF',\n         },\n       },\n     },\n   };\n   ```\n\n## 应用自定义主题\n\n先注册主题，然后通过名称引用：\n\n```javascript\n// 1. 注册主题\nimport { register, ExtensionCategory } from '@antv/g6';\nregister(ExtensionCategory.THEME, 'custom-theme', customTheme);\n\n// 2. 使用主题\nconst graph = new Graph({\n  theme: 'custom-theme',\n  // ... 其他配置\n});\n```\n","packages/site/docs/manual/theme/overview.en.md":"---\ntitle: Theme Overview\norder: 1\n---\n\n## Overview\n","packages/site/docs/manual/theme/overview.zh.md":"---\ntitle: 主题总览\norder: 1\n---\n\n## 概述\n\nG6 中的主题是 Graph Options 的子集，它包含了关于画布和元素样式的配置。多主题可以帮助你快速地切换不同的图样式。\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 主题结构\n\n一个主题由以下四个部分组成：\n\n1. **画布背景色 (background)**\n\n   - 控制整个画布的背景颜色\n\n2. **节点配置 (node)**\n\n   - 基础样式：填充色、描边、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于节点分组的颜色配置\n   - 状态样式：不同状态下的样式配置（选中、激活、禁用等）\n   - 动画配置：节点的动画效果配置\n\n3. **边配置 (edge)**\n\n   - 基础样式：线条样式、箭头、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于边分组的颜色配置\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：边的动画效果配置\n\n4. **Combo 配置 (combo)**\n   - 基础样式：填充、描边、折叠按钮等静态视觉属性\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：Combo 的动画效果配置\n\n> 注意：主题中的样式配置仅支持静态值，不支持回调函数形式的动态配置。如需动态样式，请使用图的配置项。\n\n## 内置主题\n\nG6 默认提供两种内置主题：\n\n### 亮色主题（默认）\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SPCES62UzzAAAAAAAAAAAAAAemJ7AQ/original\" alt=\"亮色主题\" />\n\n<details><summary>查看亮色主题完整配置项</summary>\n\n```js\nconst lightTheme = {\n  background: '#ffffff',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#000000',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#000000',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#000000',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fillOpacity: 0.25,\n        iconOpacity: 0.85,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.06,\n        fill: '#1B324F',\n        fillOpacity: 0.06,\n        iconFill: '#1B324F',\n        iconOpacity: 0.25,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.06,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#99ADD1',\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#99ADD1',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#99ADD1',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#1B324F',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#d9d9d9',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#ffffff',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#99ADD1',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99ADD1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99ADD1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d9d9d9',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#d9d9d9',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n### 暗色主题\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*qTlLSoAbaXYAAAAAAAAAAAAAemJ7AQ/original\" alt=\"暗色主题\" />\n\n<details><summary>查看暗色主题完整配置项</summary>\n\n```js\nconst darkTheme = {\n  background: '#000000',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#ffffff',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#d0e4ff',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#d0e4ff',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.45,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.25,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.45,\n        donutOpacity: 0.45,\n        fillOpacity: 0.45,\n        iconOpacity: 0.45,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.45,\n        strokeOpacity: 0.45,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fill: '#D0E4FF',\n        fillOpacity: 0.25,\n        iconFill: '#D0E4FF',\n        iconOpacity: 0.25,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#637088',\n        '#0F55A6',\n        '#008383',\n        '#9C5D38',\n        '#8B53A6',\n        '#4E40A6',\n        '#8F6608',\n        '#3E801D',\n        '#A65383',\n        '#175E75',\n        '#0F8248',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#637088',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#637088',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#D0E4FF',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#637088',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#000000',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#fdfdfd',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99add1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99add1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d0e4ff',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#969696',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n## 使用主题\n\n### 配置主题\n\n在创建图时通过 `theme` 选项指定要使用的主题：\n\n```javascript\nconst graph = new Graph({\n  theme: 'light', // 或 'dark'\n  // ... 其他配置\n});\n```\n\n### 切换主题\n\n创建图后，可以通过 `setTheme` 方法动态切换主题：\n\n```javascript\n// 切换到暗色主题\ngraph.setTheme('dark');\n\n// 获取当前主题\nconst currentTheme = graph.getTheme(); // 'dark'\n```\n\n## 样式优先级\n\n在 G6 中，元素的最终样式由多个层级的样式合并而成，按优先级从低到高排序：\n\n**⭐️ 主题默认样式** < 调色板样式 < 数据样式 < 图的默认样式 < **⭐️ 主题状态样式** < 图的状态样式\n\n详细说明：\n\n1. **主题默认样式**：主题系统提供的基础样式\n2. **调色板样式**：基于主题调色板配置的自动着色样式\n3. **数据样式**：在数据中定义的样式\n4. **图的默认样式**：通过图的配置项设置的样式\n5. **主题状态样式**：主题中定义的状态样式\n6. **图的状态样式**：通过图的配置项设置的状态样式\n\n更多关于自定义主题的内容，请参考[自定义主题](/manual/theme/custom-theme)。\n","packages/site/docs/manual/theme/palette.en.md":"---\ntitle: Palette\norder: 3\n---\n\n## Overview\n\nA palette refers to a set of predefined color collections that help users more conveniently select colors. In G6, a palette is a common option that allows users to configure the colors of elements such as nodes, edges, and links through the palette.\n\nPalettes are divided into two types: `discrete palette` and `continuous palette`.\n\nA discrete palette is an array of colors used to map discrete values within elements to different colors, such as the type of nodes, the relationship of edges, etc. Below is a simple example of a discrete palette:\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\nA continuous palette is an interpolator that takes a value between 0 and 1 and returns the corresponding color. It is used to map continuous values within elements to different colors, such as the degree of nodes, the weight of edges, etc. Below is a simple example of a continuous palette:\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can directly use the built-in palettes, but if you want to use other palettes, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=note}\n\nDuring the process of registering a palette, there is no distinction made between discrete and continuous palettes. It is necessary to ensure the consistency between the palette type and the data type when using the palette.\n:::\n\n### Built-in Palettes\n\nCurrently, G6 has 5 sets of commonly used discrete palettes that users can directly utilize:\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## Configure Palette\n\nCurrently, the configuration of palettes is mainly focused on elements, taking nodes as an example:\n\n### Discrete Palette\n\n1. Default Configuration: By directly setting the value of `palette` to the name of the palette, each node will be assigned a different color by default\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral is the Palette Name\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> When the number of elements exceeds the number of colors in the palette, the colors in the palette will be reused in a cyclic manner.\n\n2. Standard Configuration: The attributes for configuring a discrete palette include: `type: 'group'`, `field`, `color`, `invert`.\n\nAmong them, `type: 'group'` explicitly specifies that the current palette type is a discrete palette; `field` designates the field for grouping in the element data; `color` is the name of the palette; `invert` indicates whether to invert the palette.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\nIn the data, `node-1` and `node-4` belong to category A, `node-2` and `node-5` belong to category B, `node-3` and `node-6` belong to category C.\n\nConfigure the color of the nodes in such a way that nodes of the same category have the same color:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // Specify the palette type as a categorical palette.\n      field: 'category', // Specify the grouping field in the data.\n      color: 'tableau', // Use a Tableau-like palette.\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### Continuous Palette\n\nA continuous palette only supports standard configuration methods, with configuration properties including: `type: 'value'`, `field`, `color`, `invert`.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\nNow, create an interpolator that maps the maximum value to red (`rgb(255, 0, 0)`) and the minimum value to black (`rgb(0, 0, 0)`):\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\nConfigure the following so that the color of the nodes is mapped to different colors based on the value of the `value` field in the data:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // Specify the palette type as a continuous palette\n      field: 'value', // Specify the numerical field in the data\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Use an interpolator\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=note}\n\nThe built-in continuous palette does not support specifying a value range. If there is a need for more complex color mapping, it can be customized within the style mapping.\n:::\n\n## Custom Palette\n\nIf the built-in palette does not meet your requirements, you can customize the palette. For details, please refer to [Custom Palette](/en/manual/custom-extension/palette).\n\n## Priority\n\nThe palette generates styles based on the type of element. For nodes and combos, the color is mapped to the `fill` attribute; for edges, the color is mapped to the `stroke` attribute.\n\nIf both a palette and a style mapping are configured, the style mapping will override the palette colors. In the following example, the color of the nodes is always red:\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","packages/site/docs/manual/theme/palette.zh.md":"---\ntitle: 色板\norder: 3\n---\n\n## 概述\n\n色板(Palette)是指一组预定义的颜色集合，用于帮助用户更方便的选择颜色。在 G6 中，色板是一种常见的配置项，用户可以通过色板来配置节点、边、连线等元素的颜色。\n\n色板分为`离散色板`和`连续色板`两种类型。\n\n离散色板是一组颜色数组，用于将元素中的离散值映射到不同的颜色上，例如节点的类型、边的关系等。下面是一个简单的离散色板示例：\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\n连续色板是一个插值器，输入 0~1 的值，返回对应的颜色，用于将元素中的连续值映射到不同的颜色上，例如节点的度数、边的权重等。下面是一个简单的连续色板示例：\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n你可以直接使用内置色板，如果想使用其他色板，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=注意}\n在注册色板过程中并不会区分离散色板和连续色板，使用色板过程中需要自行保证色板类型和数据类型的一致性。\n:::\n\n### 内置色板\n\n目前 G6 内置了 5 套常用的离散色板，用户可以直接使用：\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## 配置色板\n\n目前开放色板配置的地方主要以元素为主，以节点为例：\n\n### 离散色板\n\n1. 默认配置，直接配置 `palette` 的值为色板名，会默认为每个节点分配不同的颜色\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral 为色板名\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> 当元素数量超过色板颜色数量时，会循环使用色板中的颜色\n\n2. 标准配置，离散色板配置属性包括：`type: 'group'`，`field`，`color`，`invert`\n\n其中 `type: 'group'` 显式指定了当前色板类型为离散色板；`field` 指定元素数据中的分组字段；`color` 为色板名；`invert` 为是否反转色板。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\n数据中 `node-1`，`node-4` 属于 A 类别，`node-2`，`node-5` 属于 B 类别，`node-3`，`node-6` 属于 C 类别。\n\n通过以下方式配置节点的颜色，使得同类别的节点颜色相同：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // 指定色板类型为分类色板\n      field: 'category', // 指定数据中的分组字段\n      color: 'tableau', // 使用 tableau 色板\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### 连续色板\n\n连续色板只支持标准方式配置，配置属性包括：`type: 'value'`，`field`，`color`，`invert`。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\n现在创建一个插值器，将最大值映射为红色(`rgb(255, 0, 0)`)，最小值映射为黑色(`rgb(0, 0, 0)`)：\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\n通过以下配置使得节点的颜色根据数据中的 `value` 字段的值映射到不同的颜色：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // 指定色板类型为连续色板\n      field: 'value', // 指定数据中的数值字段\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 使用插值器\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=注意}\n内置连续色板不支持指定值域范围，如果有更复杂的颜色映射需求，可以在样式映射中自定义\n:::\n\n## 自定义色板\n\n如果内置色板无法满足需求，可以自定义色板，具体请参考[自定义色板](/manual/theme/custom-palette)。\n\n## 优先级\n\n色板会基于元素类型生成样式，对于节点和组合，会将颜色映射到 `fill` 属性；对于边，会将颜色映射到 `stroke` 属性。\n\n如果同时配置了色板和样式映射，样式映射会覆盖色板颜色。下面的例子中，节点的颜色始终为红色：\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","packages/site/docs/manual/transform/MapNodeSize.en.md":"---\ntitle: MapNodeSize\norder: 1\n---\n\nIn graph visualization, the size of a node is usually used to convey the importance or influence of the node. By adjusting the size of the node based on the centrality of the node, we can more intuitively show the importance of each node in the network, helping users better understand and analyze complex network structures.\n\n## Options\n\n### centrality\n\n> [NodeCentralityOptions](#nodecentralityoptions) _\\| ((graphData:_ [GraphData](/manual/core-concept/data#图数据graphdata)_) =>_ _Map**&lt;**string, number>)_ **Default:** `type: 'eigenvector'`\n\nThe method of measuring the node centrality\n\n- `'degree'`: Degree centrality, measures centrality by the degree (number of connected edges) of a node. Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measures centrality by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measures centrality by the reciprocal of the average shortest path length from a node to all other nodes. Nodes with high closeness centrality usually can reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measures centrality by the degree of connection between a node and other central nodes. Nodes with high eigenvector centrality usually connect to other important nodes\n- `'pagerank'`: PageRank centrality, measures centrality by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to the page ranking algorithm\n- Custom centrality calculation method: `(graphData: GraphData) => Map<ID, number>`, where `graphData` is the graph data, and `Map<ID, number>` is the mapping from node ID to centrality value\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n### mapLabelSize\n\n> _boolean \\| [number, number]_ **Default:** `false`\n\nWhether to map label size synchronously\n\n### maxSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `80`\n\nThe maximum size of the node\n\n### minSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `20`\n\nThe minimum size of the node\n\n### scale\n\n> _'linear' \\| 'log' \\| 'pow' \\| 'sqrt' \\| ((value: number, domain: [number, number], range: [number, number]) => number)_ **Default:** `'log'`\n\nScale type\n\n- `'linear'`: Linear scale, maps a value from one range to another range linearly, commonly used for cases where the difference in centrality values is small\n\n- `'log'`: Logarithmic scale, maps a value from one range to another range logarithmically, commonly used for cases where the difference in centrality values is large\n\n- `'pow'`: Power-law scale, maps a value from one range to another range using power law, commonly used for cases where the difference in centrality values is large\n\n- `'sqrt'`: Square root scale, maps a value from one range to another range using square root, commonly used for cases where the difference in centrality values is large\n\n- Custom scale: `(value: number, domain: [number, number], range: [number, number]) => number`，where `value` is the value to be mapped, `domain` is the input range, and `range` is the output range\n","packages/site/docs/manual/transform/MapNodeSize.zh.md":"---\ntitle: 动态调整节点大小 MapNodeSize\norder: 1\n---\n\n## 概述\n\n在图可视化中，节点的大小通常用于传达节点的重要性或影响力。通过根据节点中心性调整节点的大小，我们可以更直观地展示网络中各个节点的重要性，从而帮助用户更好地理解和分析复杂的网络结构。\n\n## 使用场景\n\n需要通过节点大小来突出节点的重要性和影响力时，可使用此数据处理。\n\n以下为常见的场景：\n\n- **社交网络分析**：比如分析社交媒体平台中用户的活跃度与影响力，通过节点大小突出高互动用户。\n\n- **金融风险传导网络**：比如识别金融系统中承担关键资金流转职能的机构，预防系统性风险。\n\n- **交通枢纽规划**：比如优化城市地铁网络设计，识别换乘压力点。\n\n## 配置项\n\n| 属性         | 描述                                                       | 类型                                                                                                                               | 默认值               | 必选 |\n| ------------ | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type         | 数据处理类型                                               | map-node-size                                                                                                                      | -                    | ✓    |\n| centrality   | 节点中心性的度量方法，[配置项](#centrality)                | [NodeCentralityOptions](#nodecentralityoptions) \\| ((graphData: [GraphData](/manual/data#图数据graphdata)) => Map<string, number>) | `{ type: 'degree' }` |      |\n| mapLabelSize | 是否同步调整标签大小                                       | boolean \\| [number, number]                                                                                                        | false                |      |\n| maxSize      | 节点最大尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 80                   |      |\n| minSize      | 节点最小尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 20                   |      |\n| scale        | 插值函数，用于将节点中心性映射到节点大小，[配置项](#scale) | `linear` \\| `log` \\| `pow` \\| `sqrt` \\| ((value: number, domain: [number, number], range: [number, number]) => number)             | `log`                |      |\n\n### centrality\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n- 自定义中心性计算方法：`(graphData: GraphData) => Map<ID, number>`，其中 `graphData` 为图数据，`Map<ID, number>` 为节点 ID 到中心性值的映射\n\n**示例：**\n\n```typescript {6-9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n        direction: 'both',\n      },\n    },\n  ],\n});\n```\n\n效果如下（可切换度量方法查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-centrality.md\"></embed>\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n`direction`：表示统计哪些方向的边，`in` -入边、 `out` -出边、 `both` -入边和出边都考虑进去\n\n`directed`：是否为有向图\n\n`weightPropertyName`：边的权重属性名\n\n`epsilon`：PageRank 算法的收敛容差\n\n`linkProb`：PageRank 算法的阻尼系数，指任意时刻，用户访问到某节点后继续访问该节点链接的下一个节点的概率，经验值 0.85\n\n### scale\n\n- `'linear'`：线性插值函数，将一个值从一个范围线性映射到另一个范围，常用于处理中心性值的差异较小的情况\n- `'log'`：对数插值函数，将一个值从一个范围对数映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'pow'`：幂律插值函数，将一个值从一个范围幂律映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'sqrt'`：平方根插值函数，将一个值从一个范围平方根映射到另一个范围，常用于处理中心性值的差异较大的情况\n- 自定义插值函数：`(value: number, domain: [number, number], range: [number, number]) => number`，其中 `value` 为需要映射的值，`domain` 为输入值的范围，`range` 为输出值的范围\n\n**示例：**\n\n```typescript {9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n      },\n      scale: 'linear',\n    },\n  ],\n});\n```\n\n效果如下（该示例为基于度中心性 `degree` ，可切换插值函数查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-scale.md\"></embed>\n\n## 实际案例\n\n- [场景案例：独角兽和他们的投资者](/examples/feature/default/#unicorns-investors)\n","packages/site/docs/manual/transform/PlaceRadialLabels.en.md":"---\ntitle: PlaceRadialLabels\norder: 3\n---\n\n## Options\n\n### offset\n\n> _number_\n\nOffset\n","packages/site/docs/manual/transform/PlaceRadialLabels.zh.md":"---\ntitle: 径向标签 PlaceRadialLabels\norder: 2\n---\n\n**参考示例**：\n\n- [径向生态树](/examples/scene-case/tree-graph/#radial-dendrogram)\n- [径向紧凑树](/examples/scene-case/tree-graph/#radial-compact-tree)\n\n## 配置项\n\n### type\n\n> _`place-radial-labels` \\| string_\n\n此数据处理已内置，你可以通过 `type: 'place-radial-labels'` 来使用它。\n\n### offset\n\n> _number_\n\n偏移量\n","packages/site/docs/manual/transform/ProcessParallelEdges.en.md":"---\ntitle: ProcessParallelEdges\norder: 3\n---\n\nParallel Edges refer to multiple edges existing between two nodes in a graph structure. These edges share the same source and target nodes but may represent different relationships or attributes. To avoid edge overlap and confusion, two methods are provided for handling parallel edges: (1) Bundle Mode: Bundles parallel edges together and separates them from other edges by altering their curvature; (2) Merge Mode: Merges parallel edges into a single aggregated edge.\n\n## Options\n\n### distance\n\n> _number_\n\nThe distance between edges, only valid for bundling mode\n\n### edges\n\n> _string[]_\n\nThe edges to be handled, all edges by default\n\n### <Badge type=\"success\">Required</Badge> mode\n\n> _'bundle' \\| 'merge'_ **Default:** `'bundle'`\n\nProcessing mode\n\n- '`merge`': Merge parallel edges into one edge which is suitable for cases where parallel edges do not need to be distinguished\n\n- '`bundle`': Each edge will be bundled with all other parallel edges and separated from them by varying the curvature. If the number of parallel edges in a group is odd, the central edge will be drawn as a straight line, and the others will be drawn as curves\n\n### style\n\n> _PathStyleProps_ _\\| ((prev:_ [EdgeData](/api/graph/option#edgedata)_[]) =>_ _PathStyleProps)_\n\nThe style of the merged edge, only valid for merging mode\n","packages/site/docs/manual/transform/ProcessParallelEdges.zh.md":"---\ntitle: 平行边 ProcessParallelEdges\norder: 3\n---\n\n## 概述\n\n平行边（Parallel Edges）是指在图结构中，两个节点之间存在多条边。这些边共享相同的源节点和目标节点，但可能代表不同的关系或属性。为了避免边的重叠和混淆，提供了两种处理平行边的方式：\n\n- 捆绑模式（bundle）：将平行边捆绑在一起，通过改变曲率与其他边分开\n- 合并模式（merge）：将平行边合并为一条聚合\n\n## 使用场景\n\n下面为常见使用场景举例：\n\n- 双向数据流，比如客户端发送请求，服务端返回响应\n\n- 多依赖关系，即一个节点通过多种方式依赖另一个节点，比如微服务架构中，服务 A 调用服务 B的两个不同 API\n- 多链路，比如高可用架构中，主链路（实线，状态正常）与备份链路（灰色虚线，状态待机）同时展示\n\n## 基本用法\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges',\n      mode: 'bundle', // 默认就是捆绑模式了\n      distance: 30, // 配置捆绑模式下边之间的距离为30\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性     | 描述                                               | 类型                                                                                    | 默认值                  | 必选 |\n| -------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type     | 数据处理类型                                       | process-parallel-edges                                                                  | -                       | ✓    |\n| distance | 边之间的距离，仅在捆绑模式下有效                   | number                                                                                  | 15                      |      |\n| edges    | 考虑要处理的边，默认为全部边                       | string[]                                                                                | -                       |      |\n| mode     | 处理模式，[配置项](#mode)                          | `'bundle'`                                                                              | `'merge'` \\| `'bundle'` |      |\n| style    | 合并边的样式，仅在合并模式下有效，[配置项](#style) | PathStyleProps \\| ((prev: [EdgeData](/manual/data#边数据edgedata)[]) => PathStyleProps) | -                       |      |\n\n### mode\n\n提供了两种处理模式：\n\n- `'merge'`: 将平行边合并为一条边，适用于不需要区分平行边的情况，[示例](#合并模式)\n\n`merge` 使用的是内置的直线（ [`line`](/manual/element/edge/Line) ）来展示合并边。\n\n- `'bundle'`: 每条边都会与其他所有平行边捆绑在一起，并通过改变曲率与其他边分开。如果一组平行边的数量是奇数，那么中心的边将被绘制为直线，其他的边将被绘制为曲线，[示例](#捆绑模式)\n\n`bundle` 使用的是内置的二次贝塞尔曲线（ [`quadratic`](/manual/element/edge/Quadratic) ）来实现，数据处理过程会强制把每个 `edgeDatum.type` 改为 `quadratic`，并计算每条线的曲率。\n\n:::warning{title=注意}\n\n禁止在创建 Graph 实例时配置 `edge.type` 即默认的边类型，因为它的优先级比 `edgeDatum.type` 要高，会导致 `bundle` 模式的处理无法生效。\n\n:::\n\n### style\n\n合并边的样式，仅在合并模式下有效\n\n#### PathStyleProps\n\n下表列出了常用的属性，更多属性请参考 [PathStyleProps](https://g.antv.antgroup.com/api/basic/path#pathstyleprops)。\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| fill           | 填充色                    | string                        | `#1783FF` |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |\n| lineDash       | 描边虚线样式              | number[]                      | -         |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |\n| lineWidth      | 描边宽度                  | number                        | 1         |\n| opacity        | 透明度                    | number \\| string              | 1         |\n| shadowBlur     | 阴影模糊度                | number                        | -         |\n| shadowColor    | 阴影颜色                  | string                        | -         |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |\n| stroke         | 描边色                    | string                        | `#000`    |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |\n\n## 代码示例\n\n### 捆绑模式\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'C' },\n    { source: 'C', target: 'A' },\n    ...Array.from({ length: 10 }).map((_, i) => ({\n      id: `edge:A-B${i}`,\n      source: 'A',\n      target: 'B',\n      data: {\n        label: `A->B:${i}`,\n      },\n    })),\n    ...Array.from({ length: 5 }).map((_, i) => ({\n      id: `edge:B-C${i}`,\n      source: 'B',\n      target: 'C',\n      data: {\n        label: `B->C:${i}`,\n      },\n    })),\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      ports: [{ placement: 'center' }],\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n    },\n  },\n  behaviors: ['drag-element'],\n  transforms: ['process-parallel-edges'],\n});\n\ngraph.render();\n```\n\n### 合并模式\n\n下面是一个简单的合并模式的例子，需要注意：\n\n- 不需要合并（即两个节点间只有一条边）的边，合并样式不会在这条边上生效，比如例子中的 **A->C**\n- 合并样式实际上是赋值给 `datum.style` ，也就是优先级会比实例化 Graph 时配置的默认样式低（ `edge.style` ），所以例子中合并样式的 `startArrow` 没有生效\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'B' },\n    { source: 'B', target: 'A' },\n    { id: 'B-C:1', source: 'B', target: 'C' },\n    { id: 'B-C:2', source: 'B', target: 'C' },\n    { source: 'A', target: 'C' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n      startArrow: false,\n    },\n  },\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      mode: 'merge',\n      style: {\n        halo: true,\n        haloOpacity: 0.2,\n        haloStroke: 'red',\n        startArrow: true,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","packages/site/docs/manual/transform/custom-transform.en.md":"---\ntitle: Custom Transform\norder: 4\n---\n","packages/site/docs/manual/transform/custom-transform.zh.md":"---\ntitle: 自定义数据处理\norder: 4\n---\n\n## 概述\n\n自定义数据处理允许用户在业务实现过程中，把额外的数据处理封装起来，在渲染前或者布局后对数据进行进一步处理。用户通过自定义数据处理，实现部分数据处理解耦，更好地进行管理、编排代码以及提高代码可维护性。\n\n## 开始前\n\n用户在进行自定义数据处理前，需要仔细阅读并掌握数据处理器的 [实现原理和执行时机](/manual/transform/overview#实现原理) 。\n\n## 代码示例\n\n接下来将讲述两个可能的业务场景，并通过自定义数据处理来实现：\n\n### 不展示游离节点\n\n- **需求**\n\n  游离节点，即没有连线的节点，画布渲染时不展示游离节点\n\n- **实现**\n\n  ```typescript\n  import type { DrawData, DrawContext } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory } from '@antv/g6';\n\n  class HideFreeNode extends BaseTransform {\n    public beforeDraw(input: DrawData, context: DrawContext): DrawData {\n      const { model } = this.context;\n      const { add, update, remove } = input;\n\n      add.nodes.forEach((nodeData, nodeId) => {\n        // 获取节点的相关连线\n        const edges = model.getRelatedEdgesData(nodeId);\n        // 没有任何连线的的节点则从add里面移除，添加到remove里面\n        if (!edges.length) {\n          add.nodes.delete(nodeId);\n          remove.nodes.set(nodeId, nodeData);\n        }\n      });\n\n      return input;\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/hide-free-node.md\"></embed>\n\n- **说明**\n\n  示例中总共有6个节点，id为1-6，id为4的节点没有连线，因此被移除了。\n\n  通过 `getRelatedEdgesData` 获取节点的相关连线，没有则把该节点放到 `remove.nodes` 里面去，并从 `add.nodes` 里面移除。\n\n### 环形布局径向label\n\n- **需求**\n\n  使用 [环形布局](/manual/layout/circular-layout) 时，节点 label 的也需要像内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 一样实现径向展示（但 PlaceRadialLabels 只支持径向布局，环形布局不是径向布局）\n\n- **实现**\n\n  ```typescript\n  import type { RuntimeContext, DrawContext, Point, TransformArray, Vector2, Vector3 } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory, BaseTransformOptions } from '@antv/g6';\n\n  // 目前circular布局没有暴露方法可以获取布局中心，这里简单处理先固定一个，配置circular布局时center与这里保持一致即可\n  const circularCenter = [300, 300];\n\n  // 下面的函数 G6 没有暴露出来，先自行声明\n  function subtract(a: Vector2 | Vector3, b: Vector2 | Vector3): Vector2 | Vector3 {\n    return a.map((v, i) => v - b[i]) as Vector2 | Vector3;\n  }\n  function rad(a: Vector2 | Vector3): number {\n    const [x, y] = a;\n    if (!x && !y) return 0;\n    return Math.atan2(y, x);\n  }\n  function rad2deg(rad: number): number {\n    return rad * (180 / Math.PI);\n  }\n\n  interface CircularRadialLabelsOptions extends BaseTransformOptions {\n    offset?: number; // 偏移量\n  }\n\n  class CircularRadialLabels extends BaseTransform<CircularRadialLabelsOptions> {\n    static defaultOptions = {\n      offset: 5,\n    };\n    constructor(context: RuntimeContext, options: CircularRadialLabelsOptions) {\n      super(context, Object.assign({}, CircularRadialLabels.defaultOptions, options));\n    }\n    get center(): Point {\n      return circularCenter;\n    }\n    public afterLayout() {\n      const { graph, model } = this.context;\n      const data = model.getData();\n      data.nodes?.forEach((datum) => {\n        const radian = rad(subtract([datum.style.x, datum.style.y], this.center));\n        const isLeft = Math.abs(radian) > Math.PI / 2;\n        const isLeaf = !datum.children || datum.children.length === 0;\n        const nodeId = datum.id;\n        const node = this.context.element?.getElement(nodeId);\n        if (!node || !node.isVisible()) return;\n\n        const nodeHalfWidth = graph.getElementRenderStyle(nodeId).size / 2;\n        const offset = (isLeaf ? 1 : -1) * (nodeHalfWidth + this.options.offset);\n\n        const labelTransform: TransformArray = [\n          ['translate', offset * Math.cos(radian), offset * Math.sin(radian)],\n          ['rotate', isLeft ? rad2deg(radian) + 180 : rad2deg(radian)],\n        ];\n\n        model.updateNodeData([\n          {\n            id: datum.id,\n            style: {\n              labelTextAlign: isLeft === isLeaf ? 'right' : 'left',\n              labelTextBaseline: 'middle',\n              labelTransform,\n            },\n          },\n        ]);\n      });\n\n      graph.draw();\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/circular-radial-labels.md\"></embed>\n\n- **说明**\n  上面的实现基本是参考内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 来实现的，区别是这里的实现是通过拿到布局中心来计算偏移和旋转，具体可参考 PlaceRadialLabels 的 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/place-radial-labels.ts)\n","packages/site/docs/manual/transform/overview.en.md":"---\ntitle: Data Transformation Overview\norder: 0\n---\n\n## Overview\n","packages/site/docs/manual/transform/overview.zh.md":"---\ntitle: 数据处理总览\norder: 0\n---\n\n## 什么是数据处理\n\n数据处理（ `transform` ），也叫数据转换器，是 G6 提供的支持在 **渲染前( `beforeDraw` )** 或者 **布局后( `afterLayout` )** 对绘制数据进行转化处理的机制，用户可以通过数据处理很方便地对数据处理逻辑进行封装解耦。\n\n## 实现原理\n\n### 基类\n\n所有的数据处理器都是基于 [BaseTransform](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/base-transform.ts) 这个基类进行实现，里面定义了两个基类方法 `beforeDraw` 和 `afterLayout` ：\n\n```typescript\nexport abstract class BaseTransform<T extends BaseTransformOptions = BaseTransformOptions> extends BaseExtension<T> {\n  public beforeDraw(data: DrawData, context: DrawContext): DrawData {\n    return data;\n  }\n\n  public afterLayout(type: 'pre', data: DrawData): void;\n  public afterLayout(type: 'post', data?: undefined): void;\n  public afterLayout(type: 'pre' | 'post', data?: DrawData) {}\n}\n```\n\n以下是这两个方法里核心的参数类型说明：\n\n- **DrawData**\n\n  ```typescript\n  type ProcedureData = {\n    nodes: Map<ID, NodeData>;\n    edges: Map<ID, EdgeData>;\n    combos: Map<ID, ComboData>;\n  };\n\n  type DrawData = {\n    add: ProcedureData; // 本次渲染需要新增的元素\n    update: ProcedureData; // 本次渲染需要更新的元素\n    remove: ProcedureData; // 本次渲染需要移除的元素\n  };\n  ```\n\n- **pre | post**\n\n  pre：绘制前进行的布局（只会在首次布局触发）\n\n  post：完成绘制后进行的布局\n\n### 执行时机\n\n- **beforeDraw**\n\n  下面是每次渲染时数据处理的执行流程/时机：\n\n  <img width=\"300px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Pb3kRI2yHo8AAAAAAAAAAAAAemJ7AQ/original\"/>\n\n  **详细说明：**\n\n  1. G6 在每次渲染前计算出 `add`、`update`、`remove`，分别对应为需要新增、更新、移除的元素，以下简称为 `DrawData`\n  2. 此时数据处理介入，按配置顺序执行每个数据处理的 `beforeDraw` 方法，参数则为 `DrawData`\n  3. 数据处理器中，对 `DrawData` 里面的元素数据进行改动，即可以按需对 `add`、`update`、`remove` 里面的元素数据进行修改、移除或者插入元素数据等，最终把改动后的 `DrawData` 返回给渲染主体逻辑\n  4. 在执行数据处理后，执行对应的新增、更新、移除元素的操作，完成渲染\n\n:::info{title=提示}\n触发渲染的场景分为主动和被动，列举如下：\n\n- **主动：** 用户主动调用 `graph.render()` 、 `graph.draw()` 或者在自定义插件、交互等实例里面通过上下文拿到元素控制器（ [ElementController](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/element.ts) ）实例调用 `this.context.element.draw()`，等（ `graph.render()` 和 `graph.draw()` 也是调用元素控制器的 `draw` 方法）\n- **被动：** 部分内置交互和插件有触发渲染，布局执行后也有触发渲染更新元素位置，等\n\n:::\n\n- **afterLayout**：在执行完布局计算并开始更新节点位置后，执行数据处理\n\n## 内置数据处理\n\n- **G6 提供给用户的内置数据处理如下：**\n\n各数据处理详细配置可参考 [内置数据处理文档](/manual/transform/map-node-size)。\n\n| 数据处理名称                                        | 注册类型                 | 功能描述                                             | 执行时机   |\n| --------------------------------------------------- | ------------------------ | ---------------------------------------------------- | ---------- |\n| [动态调整节点大小](/manual/transform/map-node-size) | `map-node-size`          | 根据节点中心性调整节点的大小                         | beforeDraw |\n| [径向标签](/manual/transform/place-radial-labels)   | `place-radial-labels`    | 根据径向布局自动调整节点标签样式，包括位置和旋转角度 | afterDraw  |\n| [平行边](/manual/transform/process-parallel-edges)  | `process-parallel-edges` | 处理平行边，即多条边共享同一源节点和目标节点         | beforeDraw |\n\n- **G6 内嵌的数据处理如下：**\n\n除了提供给用户选用的数据处理外， G6 也封装并使用了以下数据处理机制来实现基础功能。以下数据处理不开放给用户配置使用，默认必带（列举出来供用户有需要时点击查看并参考源码）：\n\n| 数据处理名称                                                                                                            | 注册类型                | 功能描述                                                                                                                                                      | 执行时机   |\n| ----------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| [调整combo绘制顺序](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/arrange-draw-order.ts)              | `arrange-draw-order`    | combo 嵌套时，优先绘制子 combo                                                                                                                                | beforeDraw |\n| [处理组合的展开收起](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-combo.ts)          | `collapse-expand-combo` | 收起时，移除 combo 内部元素、销毁内部边，外部边则连到收起的 combo 上；<br />展开时，反之；                                                                    | beforeDraw |\n| [处理（树图）节点的收起和展开](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-node.ts) | `collapse-expand-node`  | 绘制前，处理（树图）节点的收起和展开                                                                                                                          | beforeDraw |\n| [获取边的实际端点](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/get-edge-actual-ends.ts)             | `get-edge-actual-ends`  | 配合`collapse-expand-combo`实现收起时，combo 外部连到内部节点的边改为连到收起的 combo 上（`collapse-expand-combo`只是在收起时判断并标记了这些边需要更新端点） | beforeDraw |\n| [更新节点、combo相关边](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/update-related-edge.ts)         | `update-related-edges`  | 如果更新了节点/combo，则把连接的边也一起更新了                                                                                                                | beforeDraw |\n\n:::warning{title=注意}\n\n上面 G6 为实现自身基础功能使用的数据处理仅供参考，不可改动。如有需要在这些数据处理基础上做特殊处理，可通过 [自定义数据处理](#自定义数据处理) 实现。\n\n:::\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `transforms` 数组指定需要的数据处理：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n### 配置数据处理参数\n\n对于需要自定义参数的数据处理，可以使用 `object` 形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    'place-radial-labels',\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges-1',\n      mode: 'bundle',\n      distance: 30,\n    },\n  ],\n});\n```\n\n### 动态更新数据处理\n\nG6 支持在图实例运行期间动态管理数据处理：\n\n- 可以通过 [setTransforms](/api/transform#graphsettransformstransforms) 方法调整数据处理器：\n\n```javascript\n// 添加新的数据处理器\ngraph.setTransforms((transforms) => [...transforms, 'place-radial-labels']);\n\n// 移除数据处理器\ngraph.setTransforms((transforms) => transforms.filter((t) => t !== 'place-radial-labels'));\n```\n\n- 可以通过 [updateTransform](/api/transform#graphupdatetransformtransform) 方法更新数据处理的配置：\n\n```javascript\n// 更新单个数据处理器\ngraph.updateTransform({\n  key: 'process-parallel-edges-1',\n  distance: 100,\n});\n```\n\n:::warning{title=注意}\n使用`updateTransform`方法时，需要在初始化时为数据处理指定唯一的`key`。\n:::\n\n### 卸载数据处理\n\n使用 [setTransforms](/api/transform#graphsettransformstransforms) 方法同样可以卸载数据处理，将数据处理配置列表置为空即可：\n\n```javascript\n// 卸载所有数据处理器\ngraph.setTransforms([]);\n```\n\n## 自定义数据处理\n\n当内置数据处理器无法满足需求时，你可以：\n\n- 继承和扩展现有数据处理\n- 创建全新的自定义数据处理\n\n自定义数据处理需要先注册后使用。详细教程请参考 [自定义数据处理](/manual/transform/custom-transform) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomTransform } from './my-custom-transform';\n\n// 注册自定义数据处理器\nregister(ExtensionCategory.TRANSFORM, 'my-custom-transform', MyCustomTransform);\n\n// 使用自定义数据处理\nconst graph = new Graph({\n  transforms: ['my-custom-transform'],\n});\n```\n","packages/site/docs/manual/whats-new/feature.en.md":"---\ntitle: Feature\norder: 1\n---\n\n## 🏖️ Brand New Design Specification for Graphs\n\nG6 version 5.0 has redesigned the Options specification. While ensuring comprehensive capabilities, it optimizes the options structure to be more intuitive and easier to understand.\n\nYou only need to quickly grasp the basic [core concepts](/en/manual/graph/graph) to get started with G6 quickly and achieve graph visualization without delay.\n\n**😰 The 4.0 Options** had a complex nested structure and was less semantically capable\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 The 5.0 Options** has a clear structure and is easy to understand\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 Brand New API Design\n\nG6 5.0 features a cleaner, easy-to-use API design that is more in line with modern front-end frameworks.\n\n## 🌲 Merging Graphs with Tree Graphs\n\nTree graphs are essentially a type of directed acyclic graph. G6 5.0 has integrated the design of graphs and tree graphs, reducing the cost of understanding and usage.\n\nNow, you can directly use `Graph` to instantiate and draw tree graphs in G6, without the need to use `TreeGraph`. You simply need to specify the layout as a tree graph layout.\n\nAdditionally, G6 provides the `treeToGraphData` utility method to help you quickly convert tree graph data into graph data.\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 Multi-Renderer Support\n\nG6 5.0 employs the next-generation @antv/g rendering engine, which has been newly designed. It offers support for multiple renderers such as `Canvas`, `SVG`, and `WebGL`. Additionally, it supports the mixed use of different renderers on layered canvases.\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other configurations\n  // Use the WebGL renderer\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 High-Performance Layouts\n\nG6 5.0 has adopted a brand-new layout engine, with some layouts implemented in Rust, providing higher performance for layout calculations. Additionally, there is support for WebGPU acceleration in certain layouts.\n\n> 🚀 To utilize high-performance layouts, you will need to install the `@antv/layout-wasm` package\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... Other Layout Configurations\n  },\n});\n```\n\n## 🎨 Multiple Themes Mechanism\n\nG6 5.0 comes with two built-in themes: light and dark, and allows for flexible customization based on the use case. For details, please refer to [Custom Theme](/en/manual/custom-extension/theme).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D Large Graphs\n\nG6 5.0 provides 3D rendering, layout, interaction capabilities, and can be used by import 3d elements, renderer, and behaviors from `@antv/g6-extension-3D` registration, see: [Using 3D](/manual/further-reading/3d).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 Plugin Optimization and Enhancement\n\nG6 5.0 has optimized and enhanced existing plugins, decoupling Graph from plugins, and providing richer capabilities while optimizing configurations.\n\nPlease visit [Plugin](/en/api/plugins/bubble-sets) to experience the capabilities of more plugins.\n\n## 💼 Optimized Package Size\n\nThanks to the well-modularized design and extension registration mechanism of G6 5.0, modules that are not used will not be packaged into the final build file, reducing the package size.\n\nCompared to 4.0, the UMD package size has been reduced from 1.8 MB to 0.96 MB, a reduction of nearly 50%.\n","packages/site/docs/manual/whats-new/feature.zh.md":"---\ntitle: 新版本特性\norder: 1\n---\n\n## 🏖️ 全新设计图配置范式\n\nG6 5.0 重新设计了图配置范式，在保证能力完善的基础上，优化配置项结构，更加直观、易于理解。\n\n仅需快速了解基本[核心概念](/manual/graph/graph)，即可快速上手 G6，快速实现图可视化。\n\n**😰 4.0 配置项** 嵌套结构复杂，语义化能力较弱\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 5.0 配置项** 结构清晰，易于理解\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 全新 API 设计\n\nG6 5.0 采用了更加简洁、易用的 API 设计，更加符合现代前端框架的设计风格。\n\n## 🌲 合并图与树图\n\n树图本质上是一种单向无环图，G6 5.0 融合了图与树图的设计，降低了理解和使用成本。\n\n现在，你可以在 G6 中直接使用 `Graph` 来实例化绘制树图，而不需要再使用 `TreeGraph`，仅需指定布局为树图布局即可。\n\n此外，G6 提供了 `treeToGraphData` 工具方法，帮助你快速将树图数据转换为图数据。\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 多渲染器支持\n\nG6 5.0 采用了新一代设计的 @antv/g 渲染引擎，提供了 `Canvas` `SVG` `WebGL` 多种渲染器支持，并且分层画布支持不同渲染器的混合使用。\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 WebGL 渲染器\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 高性能布局\n\nG6 5.0 采用了全新布局引擎，部分布局提供 Rust 实现，提供了更高性能的布局计算。另有布局支持 WebGPU 加速。\n\n> 🚀 高性能布局需要安装 `@antv/layout-wasm` 包\n\n```typescript\nimport { ForceAtlas2Layout, initThreads, supportsThreads } from '@antv/layout-wasm';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'forceatlas2-wasm', ForceAtlas2Layout);\n\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'forceatlas2-wasm',\n    threads,\n    // ... 其他布局配置\n  },\n});\n```\n\n> GPU 加速布局需要安装 `@antv/layout-gpu` 包\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他布局配置\n  },\n});\n```\n\n## 🎨 多主题机制\n\nG6 5.0 内置了亮色、暗色两套主题，并可基于使用场景进行灵活定制，具体可参考[自定义主题](/manual/theme/custom-theme)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D 大图\n\nG6 5.0 提供了 3D 大图渲染、布局、交互能力，从 `@antv/g6-extension-3d` 中引入 3D 元素、渲染器、交互等注册即可使用，详见：[使用 3D](/manual/further-reading/3d)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 插件优化增强\n\nG6 5.0 对现有插件进行了优化增强，解除了 Graph 与插件之间的耦合，并优化配置的同时提供了更加丰富了能力。\n\n敬请前往[插件](/manual/plugin/overview)体验更多插件的能力。\n\n## 💼 优化包体积\n\n得益于 G6 5.0 良好的模块化的设计以及扩展注册机制，对于未使用的模块，不会被打包到最终的构建文件中，减小了包体积。\n\n与 4.0 相比，UMD 包体积从 1.8 MB 减小到 0.96 MB，减小了近 50%。\n","packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md":"---\ntitle: Upgrade from 5.0 to 5.1 (Layout)\norder: 7\n---\n\nThis page focuses on layout documentation changes introduced in G6 `5.1`. Starting from `5.1`, layout pages prioritize the field naming aligned with `@antv/layout`; common `5.0` layout writeups are collected here for migration reference.\n\n## What Changed\n\n- Since `5.1`, layout docs prioritize shared `@antv/layout` fields such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`\n- Individual layout pages mainly keep the recommended `5.1` writeup\n- If you are migrating an existing `5.0` project, use this page to map old field names to the new documentation style\n\n## D3Force: center force to shortcut fields\n\nIn `5.0` documentation, the center force was commonly written inside `center`:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is the shortcut fields:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` maps to `centerX`\n- `center.y` maps to `centerY`\n- `center.strength` maps to `centerStrength`\n\nFor the full field description, see [D3Force Layout](/en/manual/layout/d3-force-layout).\n\n## ComboCombined: innerLayout / outerLayout to layout\n\nIn `5.0` documentation, the inner combo layout and the outer layout were commonly configured separately:\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is a single `layout` entry that returns different configurations for different levels based on `comboId`:\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- When `comboId` has a value, it refers to the layout inside a combo\n- When `comboId` is empty, it refers to the outermost layout\n- Multiple layout choices are unified under the `layout` entry\n\nFor the `5.1` recommended form, see [ComboCombined Layout](/en/manual/layout/combo-combined-layout).\n\n## Migration Suggestion\n\n1. Identify the matching layout type from your existing `5.0` project\n2. Map the old fields to the recommended `5.1` documentation style\n3. Return to the specific layout page to verify shared fields and defaults\n","packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md":"---\ntitle: 从 5.0 升级到 5.1（布局）\norder: 7\n---\n\n本文档聚焦 G6 `5.1` 中布局文档的写法调整。`5.1` 的布局页面会优先展示与 `@antv/layout` 对齐后的字段；`5.0` 中常见的布局写法统一收敛到本文档中，便于迁移时对照。\n\n## 总体变化\n\n- `5.1` 起，布局文档会优先展示 `@antv/layout` 的公共字段，例如 `width` `height` `center` `enableWorker` `node` `edge`\n- 各布局页主要保留 `5.1` 推荐写法，`5.0` 中常见写法请以本文档为准\n- 迁移时，建议先按旧项目中的字段定位，再映射到 `5.1` 文档里的推荐配置\n\n## D3Force：center force 改为快捷字段\n\n`5.0` 文档中，常见把中心力写在 `center` 中：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\n`5.1` 文档中推荐写成更直接的快捷字段：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` 对应 `centerX`\n- `center.y` 对应 `centerY`\n- `center.strength` 对应 `centerStrength`\n\n如果你需要继续对照完整字段说明，可查看 [D3Force 布局](/manual/layout/d3-force-layout)。\n\n## ComboCombined：innerLayout / outerLayout 收敛为 layout\n\n`5.0` 文档中，常见分别配置 Combo 内部布局和最外层布局：\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\n`5.1` 文档中推荐使用单个 `layout` 字段，根据 `comboId` 为不同层级返回布局配置：\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- `comboId` 有值时，表示当前为 Combo 内部层级\n- `comboId` 为空时，表示当前为最外层布局\n- 多层布局选择统一收敛到 `layout` 入口\n\n如果你需要查看 `5.1` 推荐写法，可查看 [ComboCombined 布局](/manual/layout/combo-combined-layout)。\n\n## 迁移建议\n\n1. 先按旧项目中的布局类型定位到本文档对应条目\n2. 再把 `5.0` 字段映射成 `5.1` 文档里的推荐写法\n3. 最后回到具体布局页，核对公共字段和默认值\n","packages/site/docs/manual/whats-new/upgrade.en.md":"---\ntitle: Upgrade To 5.0\norder: 6\n---\n\nThis document will guide you through the process of upgrading from G6 version `4.x` to `5.x`. If you are using version `3.x`, please upgrade to version `4.x` first.\n\n## Preparation Before Upgrade\n\n1. Please ensure that your current git branch is clean and there is no uncommitted code.\n2. Refer to the [Installation](./getting-started/installation) document to install version `5.x` and remove the dependencies for version `4.x`.\n\n## Start Upgrade\n\n### Data\n\nThe data format in the new version has changed as follows:\n\n1. All style attributes in `nodes`, `edges`, and `combos` need to be placed within `style`, and data attributes should be stored in `data`:\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // The label is a non-stylistic attribute, placed in the data, and can be accessed in the style mapping function\n    // The `size` is a stylistic attribute, placed within the `style`\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\nSince we have redesigned and implemented the elements, please refer to the corresponding documentation to modify the new element options:\n\n- [Node](/en/api/elements/nodes/base-node)\n- [Edge](/en/api/elements/edges/base-edge)\n- [Combo](/en/api/elements/combos/base-combo)\n\n2. If you need to specify the element type in the data, you can use the `type` attribute:\n\n```typescript\n{\n  nodes: [\n    // Specify the node type as rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### Options\n\n<Badge type=\"warning\">Change</Badge> **fitView / fitCenter / fitViewPadding**\n\n- The `fitView` and `fitCenter` options have been merged into `autoFit`.\n- To use `fitView`, you can configure it as `autoFit: 'view'`\n- To use `fitCenter`, you can configure it as `autoFit: 'center'`\n- You can also pass an object for full configuration:\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- The `fitViewPadding` has been changed to `padding`.\n\n<Badge type=\"error\">Removed</Badge> **linkCenter**\n\nIn version 5.x, the edge connection mechanism will attempt to connect to nodes/Combos in the following order:\n\n1. Connect Port\n2. Outline\n3. Center\n\n<Badge type=\"error\">Removed</Badge> **groupByTypes**\n\n<Badge type=\"error\">Removed</Badge> **autoPaint**\n\nPlease manually call the `render` or `draw` method to perform rendering.\n\n<Badge type=\"warning\">Changed</Badge> **modes**\n\nIn version 5.x, interaction modes have been removed. You can switch the currently enabled behaviors by setting `behaviors`.\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">Change</Badge> **defaultNode / defaultEdge / defaultCombo**\n\nThe element styles have been moved to `[element].style`, for example, `defaultNode` has been changed to `node.style`:\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\nElement state styles have been moved to `[element].state`, for example, `nodeStateStyles` has been changed to `node.stateStyles`:\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **animate / animateCfg**\n\n- The `animate` options has been changed to `animation`\n- `animate` and `animateCfg` have been merged into `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **minZoom / maxZoom**\n\n- The `minZoom` and `maxZoom` options have been merged into `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **renderer**\n\nG6 5.x supports multi-layer canvases and defaults to using the `canvas` renderer.\n\nThe `renderer` no longer supports the string type and has been changed to a callback function:\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **enabledStack / maxStep**\n\nThe built-in undo and redo functionality has been removed in version 5.x. For related capabilities, please use a plugin to implement.\n\n### API\n\n<Badge type=\"warning\">Change</Badge> **data / save / read / changeData**\n\nVersion 5.x offers a completely new data API. For details, see [Data API](/en/api/data).\n\n- The `data` and `changeData` methods from 4.x are replaced by `setData` in 5.x.\n- The `save` method from 4.x is replaced by `getData` in 5.x.\n- The `read` method from 4.x is replaced by `setData` + `render` in 5.x.\n\n<Badge type=\"warning\">Change</Badge> **get / set**\n\nTo access Graph options, please use `getOptions` or the `getXxx` API, such as `getZoomRange`, `getBehaviors`, etc. The `set` method is analogous.\n\n<Badge type=\"warning\">Change</Badge> **getContainer**\n\nDirect API to obtain the container is not currently supported, but you can obtain it through `graph.getCanvas().getContainer()`.\n\n> In most cases, you do not need to directly manipulate the container.\n\n<Badge type=\"error\">Removed</Badge> **getGroup**\n\n<Badge type=\"warning\">Change</Badge> **getMinZoom / getMaxZoom**\n\nUse `getZoomRange` to obtain the values.\n\n<Badge type=\"warning\">Change</Badge> **setMinZoom / setMaxZoom**\n\nUse the `setZoomRange` method to set the values.\n\n<Badge type=\"warning\">Change</Badge> **getWidth / getHeight**\n\nUse `getSize` to get the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **changeSize**\n\nUse `setSize` to set the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **zoom**\n\nChanged to `zoomBy`.\n\n<Badge type=\"warning\">Change</Badge> **translate**\n\nChanged to `translateBy`.\n\n<Badge type=\"warning\">Change</Badge> **moveTo**\n\nChanged to `translateTo`.\n\n<Badge type=\"warning\">Change</Badge> **focusItem**\n\nChanged to `focusElement`.\n\n<Badge type=\"error\">Removed</Badge> **addItem / updateItem / removeItem**\n\nTo add or remove elements, use the methods `addData` / `updateData` / `removeData` to manipulate data.\n\n<Badge type=\"error\">Removed</Badge> **refreshItem**\n\n<Badge type=\"error\">Removed</Badge> **refreshPositions**\n\n<Badge type=\"error\">Removed</Badge> **updateCombo**\n\n<Badge type=\"error\">Removed</Badge> **updateCombos**\n\n<Badge type=\"error\">Removed</Badge> **updateComboTree**\n\n<Badge type=\"warning\">Change</Badge> **node / edge / combo**\n\nUse the `setNode` / `setEdge` / `setCombo` methods as alternatives.\n\n<Badge type=\"warning\">Change</Badge> **showItem / hideItem**\n\nUse the `setElementVisibility` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **getNodes / getEdges / getCombos / getComboChildren / getNeighbors / find / findById / findAll / findAllByState**\n\nIn version 5.x, direct retrieval of element instances is not supported.\n\n- To obtain element data, use the methods `getData`, `getNodeData`, `getEdgeData`, `getComboData`, which support searching by element ID.\n- To obtain child node data, use the `getChildrenData` method.\n- To obtain neighbor node data, use the `getNeighborNodesData` method.\n- To find element data based on state, use the `getElementDataByState` method.\n\n<Badge type=\"warning\">Change</Badge> **collapseCombo / expandCombo**\n\nUse the `collapseElement` / `expandElement` methods as alternatives.\n\n<Badge type=\"error\">Removed</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">Removed</Badge> **createCombo**\n\nCombos can now be added using the `addData` / `addComboData` methods.\n\n<Badge type=\"error\">Removed</Badge> **uncombo**\n\nCombos can now be removed using the `removeData` / `removeComboData` methods.\n\n<Badge type=\"warning\">Change</Badge> **setItemState**\n\nUse the `setElementState` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **clearItemStates**\n\n- To clear all states of a single element: `graph.setElementState(id, [])`\n- To clear all states of multiple elements: `graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">Removed</Badge> **priorityState**\n\nWhen using `setElementState`, the state that appears later in the array has a higher priority.\n\n<Badge type=\"error\">Removed</Badge> **setMode**\n\nUse `setBehaviors` to set the current behaviors.\n\n<Badge type=\"error\">Removed</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">Change</Badge> **layout**\n\nDoes not support parameters. To configure the layout, please use `setLayout`.\n\n<Badge type=\"warning\">Change</Badge> **updateLayout**\n\nChanged to `setLayout`.\n\n<Badge type=\"error\">Removed</Badge> **destroyLayout**\n\n<Badge type=\"warning\">Change</Badge> **addBehaviors / removeBehaviors**\n\nReplaced with `setBehaviors`.\n\n<Badge type=\"error\">Removed</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- For multiple `Hull` instances, you need to configure multiple `hull` plugins in `plugins`, such as:\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- Operations to retrieve, update, and remove `Hull` are implemented through `setPlugins`, `updatePlugin`.\n\n<Badge>Not yet available</Badge> **getNodeDegree**\n\n<Badge>Not yet available</Badge> **getShortestPathMatrix**\n\n<Badge>Not yet available</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">Removed</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\nAll undo and redo related APIs should be called after obtaining the corresponding plugin, for example:\n\n```typescript\n// 'history' is the key configured for use with the plugin\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">Removed</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\nAnimation-related information is now emitted through events:\n\n- Animation start event: `beforeanimate`\n- Animation end event: `afteranimate`\n- To stop an animation:\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">Change</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x uses a different coordinate system than 4.x. For details, see [Coordinate](/en/manual/further-reading/coordinate).\n\n<Badge type=\"error\">Removed</Badge> **setTextWaterMarker / setImageWaterMarker**\n\nFor watermark functionality, please refer to the [Watermark](/en/api/plugins/watermark)plugin.\n\n<Badge type=\"warning\">Change</Badge> **toFullDataURL**\n\nReplaced with `toDataURL`, specify the parameter as: `mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">Removed</Badge> **downloadFullImage / downloadImage**\n\nOnly the capability to export as a `DataURL` is provided. If you need to download an image, please refer to the following example code:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **clear**\n\nUse `setData` + `draw` to clear data and the canvas.\n\n### Extension Registration\n\nUnlike G6 4.x, G6 5.x uses a unified extension registration function (register). You can refer to the [Extension Register](/en/manual/core-concept/extension#register-extension) to register G6 extensions.\n\nThe following G6 4.x registration functions have been deprecated:\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### Events\n\nCompared to G6 4.x, G6 5.x has the following differences in events:\n\n- The `mouse` and `touch` events have been removed and are unified under the `pointer` event.\n- The naming convention for lifecycle events is usually in the format of: `before/after` + `object/property` + `action`, for example: `beforeelementcreate` is triggered before an element is created.\n- The following events have been removed:\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- The following element change events have been removed, but you can still access them through `beforeelementupdate` and `afterelementupdate`:\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- The following events have been changed:\n  - The `graphstatechange` event has been changed to `beforeelementstatechange` / `afterelementstatechange`.\n  - The `viewportchange` event has been changed to `beforetransform` / `aftertransform`.\n\nFor a complete list of events, please refer to [Event](/en/api/reference/g6#event).\n","packages/site/docs/manual/whats-new/upgrade.zh.md":"---\ntitle: 升级到 5.0\norder: 6\n---\n\n本文档将引导你从 G6 `4.x` 版本升级到 `5.x` 版本。如果你使用的是 `3.x` 版本，请先升级到 `4.x` 版本。\n\n## 升级前准备\n\n1. 请确保当前 git 分支是干净的，没有未提交的代码。\n2. 参考 [安装](/manual/getting-started/installation) 文档安装 `5.x` 版本，并移除 `4.x` 版本依赖。\n\n## 开始升级\n\n### 数据\n\n新版本的数据格式有所变化，具体如下：\n\n1. `nodes` `edges` `combos` 中所有样式属性都需要放在 `style` 中，`data` 中存放数据属性：\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // label 为非样式属性，放在 data 中，可在样式映射函数中访问\n    // size 为样式属性，放在 style 中\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\n由于我们重新设计实现了元素，新的元素配置项请参考相应文档进行修改：\n\n- [Node](/manual/element/node/overview)\n- [Edge](/manual/element/edge/overview)\n- [Combo](/manual/element/combo/overview)\n\n2. 如果要在数据中指定元素类型，可以使用 `type` 属性：\n\n```typescript\n{\n  nodes: [\n    // 指定节点类型为 rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### 配置项\n\n<Badge type=\"warning\">变更</Badge> **fitView / fitCenter / fitViewPadding**\n\n- `fitView` 和 `fitCenter` 配置项已经合并为 `autoFit`\n- 若要使用 `fitView`，可以配置为 `autoFit: 'view'`\n- 若要使用 `fitCenter`，可以配置为 `autoFit: 'center'`\n- 也可以传入对象进行完整配置：\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- `fitViewPadding` 已变更为 `padding`\n\n<Badge type=\"error\">移除</Badge> **linkCenter**\n\n5.x 的边连接机制会按照如下顺序依次尝试连接到节点/Combo：\n\n1. 连接桩\n2. 轮廓\n3. 中心\n\n<Badge type=\"error\">移除</Badge> **groupByTypes**\n\n<Badge type=\"error\">移除</Badge> **autoPaint**\n\n请手动调用 `render` 或 `draw` 方法进行绘制。\n\n<Badge type=\"warning\">变更</Badge> **modes**\n\n5.x 已经移除交互模式，你可以通过设置 `behaviors` 来切换当前启用的交互行为。\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">变更</Badge> **defaultNode / defaultEdge / defaultCombo**\n\n元素样式已移至 `[element].style` 中，如 `defaultNode` 变更为 `node.style`：\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\n元素状态样式已移至 `[element].state` 中，如 `nodeStateStyles` 变更为 `node.stateStyles`：\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **animate / animateCfg**\n\n- `animate` 配置项已变更为 `animation`\n- `animate` 和 `animateCfg` 已合并为 `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **minZoom / maxZoom**\n\n`minZoom` 和 `maxZoom` 已合并为 `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **renderer**\n\nG6 5.x 支持多层画布，默认使用 `canvas` 渲染。\n\nrenderer 不再支持字符串类型，变更为回调函数：\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">移除</Badge> **enabledStack / maxStep**\n\n5.x 已移除内置撤销重做功能，相关能力请使用插件实现。\n\n### API\n\n<Badge type=\"warning\">变更</Badge> **data / save / read / changeData**\n\n5.x 提供了全新的数据 API，详见 [数据 API](/api/data)。\n\n- 4.x `data` `changeData` 方法使用 5.x `setData` 替代\n- 4.x `save` 方法使用 5.x `getData` 替代\n- 4.x `read` 方法使用 5.x `setData` + `render` 替代\n\n<Badge type=\"warning\">变更</Badge> **get / set**\n\n若要访问 Graph options，请使用 `getOptions` 或者 `getXxx` API，例如 `getZoomRange` `getBehaviors` 等。 `set` 同理。\n\n<Badge type=\"warning\">变更</Badge> **getContainer**\n\n暂不支持直接获取容器的 API，但可以通过 `graph.getCanvas().getContainer()` 获取。\n\n> 绝大部分情况下，你都不需要直接操作容器。\n\n<Badge type=\"error\">移除</Badge> **getGroup**\n\n<Badge type=\"warning\">变更</Badge> **getMinZoom / getMaxZoom**\n\n使用 `getZoomRange` 获取。\n\n<Badge type=\"warning\">变更</Badge> **setMinZoom / setMaxZoom**\n\n使用 `setZoomRange` 方法设置。\n\n<Badge type=\"warning\">变更</Badge> **getWidth / getHeight**\n\n使用 `getSize` 获取。\n\n<Badge type=\"warning\">变更</Badge> **changeSize**\n\n使用 `setSize` 设置。\n\n<Badge type=\"warning\">变更</Badge> **zoom**\n\n变更为 `zoomBy`。\n\n<Badge type=\"warning\">变更</Badge> **translate**\n\n变更为 `translateBy`。\n\n<Badge type=\"warning\">变更</Badge> **moveTo**\n\n变更为 `translateTo`。\n\n<Badge type=\"warning\">变更</Badge> **focusItem**\n\n变更为 `focusElement`。\n\n<Badge type=\"error\">移除</Badge> **addItem / updateItem / removeItem**\n\n通过 `addData` / `updateData` / `removeData` 方法操作数据来添加或删除元素。\n\n<Badge type=\"error\">移除</Badge> **refreshItem**\n\n<Badge type=\"error\">移除</Badge> **refreshPositions**\n\n<Badge type=\"error\">移除</Badge> **updateCombo**\n\n<Badge type=\"error\">移除</Badge> **updateCombos**\n\n<Badge type=\"error\">移除</Badge> **updateComboTree**\n\n<Badge type=\"warning\">变更</Badge> **node / edge / combo**\n\n使用 `setNode` / `setEdge` / `setCombo` 方法替代。\n\n<Badge type=\"warning\">变更</Badge> **showItem / hideItem**\n\n使用 `setElementVisibility` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **getNodes / getEdges / getCombos / getComboChildren /getNeighbors /find /findById / findAll /findAllByState**\n\n5.x 不支持直接获取元素实例。\n\n- 若要获取元素数据，使用 `getData` `getNodeData` `getEdgeData` `getComboData` 方法，支持传入元素 id 进行查找。\n- 获取子节点数据，使用 `getChildrenData` 方法。\n- 获取邻居节点数据，使用 `getNeighborNodesData` 方法。\n- 基于状态查找元素数据，使用 `getElementDataByState`。\n\n<Badge type=\"warning\">变更</Badge> **collapseCombo / expandCombo**\n\n使用 `collapseElement` / `expandElement` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">移除</Badge> **createCombo**\n\n通过 `addData` / `addComboData` 方法添加 Combo。\n\n<Badge type=\"error\">移除</Badge> **uncombo**\n\n通过 `removeData` / `removeComboData` 方法移除 Combo。\n\n<Badge type=\"warning\">变更</Badge> **setItemState**\n\n使用 `setElementState` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **clearItemStates**\n\n- 清除单个元素所有状态：`graph.setElementState(id, [])`\n- 清除多个元素所有状态：`graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">移除</Badge> **priorityState**\n\n`setElementState` 时状态数组中靠后的状态优先级更高。\n\n<Badge type=\"error\">移除</Badge> **setMode**\n\n使用 `setBehaviors` 来设置当前交互。\n\n<Badge type=\"error\">移除</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">变更</Badge> **layout**\n\n不支持参数，如需配置布局，请使用 `setLayout`。\n\n<Badge type=\"warning\">变更</Badge> **updateLayout**\n\n变更为 `setLayout`。\n\n<Badge type=\"error\">移除</Badge> **destroyLayout**\n\n<Badge type=\"warning\">变更</Badge> **addBehaviors / removeBehaviors**\n\n使用 `setBehaviors` 替代。\n\n<Badge type=\"error\">移除</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- 多个 `Hull` 需在 `plugins` 中配置多个 `hull` 插件，如：\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- `Hull` 的获取、更新、移除操作通过 `setPlugins`, `updatePlugin` 实现。\n\n<Badge>暂未提供</Badge> **getNodeDegree**\n\n<Badge>暂未提供</Badge> **getShortestPathMatrix**\n\n<Badge>暂未提供</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">移除</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\n所有撤销重做相关 API 请获取到对应插件后调用 API，例：\n\n```typescript\n// 'history' 为使用插件时配置的 key\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">移除</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\n动画相关信息通过事件抛出：\n\n- 动画开始事件：`beforeanimate`\n- 动画结束事件：`afteranimate`\n- 停止动画：\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">变更</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x 采用了与 4.x 不同的坐标系，详见 [坐标系](/manual/further-reading/coordinate)。\n\n<Badge type=\"error\">移除</Badge> **setTextWaterMarker / setImageWaterMarker**\n\n要使用水印功能，请参考 [水印](/manual/plugin/watermark)插件。\n\n<Badge type=\"warning\">变更</Badge> **toFullDataURL**\n\n使用 `toDataURL` 替代，指定参数为：`mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">移除</Badge> **downloadFullImage / downloadImage**\n\n仅提供导出为 `DataURL` 的能力，如需下载图片，请参考如下实例代码：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">移除</Badge> **clear**\n\n使用 `setData` + `draw` 清空数据和画布。\n\n### 扩展注册\n\n与 G6 4.x 不同，G6 5.x 使用的统一的扩展注册函数(register)，你可以参考 [注册扩展](/manual/graph/extension#注册扩展) 来注册 G6 扩展。\n\n下列 G6 4.x 的注册函数已经废除：\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### 事件\n\n与 G6 4.x 相比，G6 5.x 的事件但存下如下差异：\n\n- 移除了 `mouse` 和 `touch` 事件，统一使用 `pointer` 事件\n- 生命周期事件名命名格式通常为： `before/after` + `对象/属性` + `操作`，例如：`beforeelementcreate` 表示在创建元素前触发\n- 下列事件已被移除：\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- 下列元素变更事件被移除，但你仍可通过 `beforeelementupdate` 和 `afterelementupdate` 获取：\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- 下列事件有所变更：\n  - graphstatechange 事件变更为 beforeelementstatechange / afterelementstatechange\n  - viewportchange 事件变更为 beforetransform / aftertransform\n\n完整的事件列表请参考 [事件](/api/event)。\n"},"items":[{"name":"translation.mdc","path":".cursor/rules/translation.mdc","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/.cursor/rules/translation.mdc","title":"Cursor Rule: translation","category":"cursor-rule","format":"mdc","content":"---\ndescription: 翻译\nglobs:\nalwaysApply: false\n---\n# Translation Guidelines for site/docs\n\nWhen translating files under the `site/docs` directory, please adhere to the following guidelines:\n\n1. **Consistency in Terminology**: Ensure that terminology is consistent throughout the document. Use a glossary if available to maintain uniformity in terms.\n\n   **Glossary**:\n\n   - 画布 (Canvas)\n   - 元素 (Element)\n   - 节点 (Node)\n   - 边 (Edge)\n   - 组合 (Combo)\n   - 交互 (Behavior)\n   - 布局 (Layout)\n   - 插件 (Plugin)\n   - 动画 (Animation)\n   - 数据处理 (Transform)\n   - 色板 (Palette)\n   - 配置项 (Option)\n   - 图数据 (Graph Data)\n   - 树图 (Tree Graph)\n   - 属性 (Property)\n   - 描述 (Description)\n   - 类型 (Type)\n   - 默认值 (Default Value)\n   - 必选 (Required)\n\n2. **Adjust Hyperlinks**: Review and adjust hyperlinks to ensure they point to the correct translated sections or documents. Verify that all links are functional and correctly formatted.\n\n   - **Internal Links**: In the English version, all internal links should have a `/en` prefix, while the Chinese version should not have any prefix. Ensure this prefix is added to all internal links in English documents to avoid any oversight.\n   - **Anchor Points**: For anchor points following a `#`, if they contain Chinese characters, they should be adjusted to match the corresponding title in the English version rather than being directly translated.\n   - **External Links**: Convert external links appropriately to ensure they align with the language and context of the document.\n\n3. **Direct Writing to Translated Documents**: Translations should be stored in corresponding `.en.md` or `.zh.md` files within the same directory. Ensure that the translated content is placed in the correct location within the document.\n\n   - When translating from Chinese to English, create or update the `.en.md` file in the same directory.\n   - When translating from English to Chinese, create or update the `.zh.md` file in the same directory.\n\n4. **Support for Partial Content Translation**: Allow for the selection and translation of specific sections of content. Translated sections should be inserted into the appropriate location within the document, maintaining the logical flow and structure.\n\n   - **Full Document Translation**: If the entire document is selected for translation, replace the entire content with the translated version.\n   - **Partial Content Translation**: If only specific sections are selected, find the appropriate place to replace or insert the translated content, ensuring the document's logical flow and structure are maintained.\n\n5. **Contextual Translation**: Avoid literal translations. Ensure that the translation fits the English context and conveys the intended meaning accurately.\n\n6. **Direct Modification**: Translations should be directly modified in the corresponding `.en.md` or `.zh.md` files without returning the translated content separately. Ensure that the changes are saved in the correct file and location.\n\n7. **Preserve Metadata Order**: Do not modify the `order` attribute in the page metadata during translation. This ensures that the document order remains consistent across different language versions.\n\n8. **Add '/en' Prefix to Internal Links**: Ensure that all internal links in English documentation have the '/en' prefix to maintain consistency and correct navigation.\n\nBy following these guidelines, translations will be more accurate and consistent, facilitating easier review and integration into the documentation.\n","frontmatter":{"description":"翻译","alwaysApply":false},"isInternal":false,"tokens":872,"sizeBytes":3575},{"name":"behavior.en.md","path":"packages/site/docs/api/behavior.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/behavior.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Behavior\norder: 8\n---\n\n## Overview of Behavior\n\nBehavior is a core building block of G6, precisely defining the interaction between users and the graph. Each Behavior plugin is a highly encapsulated functional unit, integrating event listening, state management, and response handling logic for specific scenarios.\n\nG6's built-in Behaviors cover most common interaction needs and provide a flexible extension mechanism, allowing developers to create customized interaction experiences based on business scenarios. For a complete list of behavior types, configuration options, and development examples, please refer to the [Behavior Overview](/en/manual/behavior/overview) section.\n\n## API Reference\n\n### Graph.getBehaviors()\n\nGet all configured behaviors in the current graph.\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**Return Value**\n\n- **Type**: [BehaviorOptions](#behavioroptions)\n- **Description**: All configured behaviors in the current graph\n\n**Example**\n\n```typescript\n// Get all current behaviors\nconst behaviors = graph.getBehaviors();\nconsole.log('Current graph behaviors:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\nSet the behaviors of the graph, replacing all existing behaviors.\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                    | Type                                                                              | Default | Required |\n| --------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------- | -------- |\n| behaviors | New behavior configuration, or a function returning new configuration based on the current one | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -       | ✓        |\n\n**Note**\n\nThe set behaviors will completely replace the original ones. To add new behaviors, you can use functional updates:\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**Example 1**: Set basic behaviors\n\n```typescript\n// Set basic behaviors\ngraph.setBehaviors([\n  'drag-canvas', // Drag canvas\n  'zoom-canvas', // Zoom canvas\n  'drag-element', // Drag element\n]);\n```\n\n**Example 2**: Set behaviors with configuration\n\n```typescript\ngraph.setBehaviors([\n  // String form (using default configuration)\n  'drag-canvas',\n\n  // Object form (custom configuration)\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // Specify a unique identifier for subsequent updates\n    sensitivity: 1.5, // Zoom sensitivity\n  },\n\n  // Enable drag only on nodes\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // Enable drag only on nodes\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new behavior\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// Replace specific behavior\ngraph.setBehaviors((currentBehaviors) => {\n  // Filter out existing zoom behaviors\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // Add new zoom behavior configuration\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\nUpdate the configuration of a specific behavior, identified by the `key`.\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                             | Type                                          | Default | Required |\n| --------- | --------------------------------------- | --------------------------------------------- | ------- | -------- |\n| behavior  | Configuration of the behavior to update | [UpdateBehaviorOption](#updatebehavioroption) | -       | ✓        |\n\n**Note**\n\nTo update a behavior, the original behavior configuration must specify the `key` field to accurately locate and update the behavior.\n\n**Example 1**: Update behavior configuration\n\n```typescript\n// Specify key when initially setting behaviors\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// Update behavior configuration\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // Specify the behavior to update\n  sensitivity: 2.0, // New zoom sensitivity\n  enableOptimize: true, // Add new configuration\n});\n```\n\n**Example 2**: Disable/Enable behavior\n\n```typescript\n// Set behaviors with keys\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// Disable drag functionality\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// Re-enable later\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## Type Definitions\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // Interaction type\n  type: string;\n\n  // Interaction key, a unique identifier for identifying and further operating this interaction\n  key?: string;\n\n  // There may be other configuration items for different types of interactions\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // Unique identifier of the behavior to update\n  key: string;\n\n  // Other configuration items to update\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"Behavior","order":"8"},"isInternal":false,"tokens":1478,"sizeBytes":5913},{"name":"behavior.zh.md","path":"packages/site/docs/api/behavior.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/behavior.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 交互\norder: 8\n---\n\n## 交互概述\n\n交互（Behavior）是 G6 的核心构建模块，它精确定义了用户与图之间的互动行为。每个 Behavior 插件都是一个高度封装的功能单元，内部集成了特定场景下的事件监听、状态管理和响应处理逻辑。\n\nG6 的内置 Behavior 涵盖了大多数常见交互需求，同时提供了灵活的扩展机制，支持开发者根据业务场景构建定制化交互体验。\n有关完整的交互行为类型、配置选项及开发示例，请参阅 [交互总览](/manual/behavior/overview) 章节。\n\n## API 参考\n\n### Graph.getBehaviors()\n\n获取当前图表中所有已配置的交互行为。\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**返回值**\n\n- **类型**: [BehaviorOptions](#behavioroptions)\n- **描述**: 当前图表中已配置的所有交互行为\n\n**示例**\n\n```typescript\n// 获取当前所有交互行为\nconst behaviors = graph.getBehaviors();\nconsole.log('当前图表的交互行为:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\n设置图表的交互行为，将替换所有现有的交互行为。\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**参数**\n\n| 参数      | 描述                                                 | 类型                                                                              | 默认值 | 必选 |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | ------ | ---- |\n| behaviors | 新的交互行为配置，或一个基于当前配置返回新配置的函数 | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -      | ✓    |\n\n**说明**\n\n设置的交互会全量替换原有的交互，如果需要新增交互可以使用函数式更新：\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**示例 1**: 设置基本交互\n\n```typescript\n// 设置基本交互\ngraph.setBehaviors([\n  'drag-canvas', // 拖拽画布\n  'zoom-canvas', // 缩放画布\n  'drag-element', // 拖拽元素\n]);\n```\n\n**示例 2**: 设置带配置的交互\n\n```typescript\ngraph.setBehaviors([\n  // 字符串形式（使用默认配置）\n  'drag-canvas',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // 指定唯一标识，用于后续更新\n    sensitivity: 1.5, // 缩放灵敏度\n  },\n\n  // 只有节点上启用拖拽\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // 仅在节点上启用拖拽\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的交互行为\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// 替换特定交互行为\ngraph.setBehaviors((currentBehaviors) => {\n  // 过滤掉现有的缩放交互\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // 添加新的缩放交互配置\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\n更新指定的交互行为配置，需要通过 `key` 标识要更新的交互。\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**参数**\n\n| 参数     | 描述               | 类型                                          | 默认值 | 必选 |\n| -------- | ------------------ | --------------------------------------------- | ------ | ---- |\n| behavior | 更新的交互行为配置 | [UpdateBehaviorOption](#updatebehavioroption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个交互，必须在原始交互配置中指定 `key` 字段，以便能够准确找到并更新该交互。\n\n**示例 1**: 更新交互配置\n\n```typescript\n// 初始设置交互时指定 key\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// 更新交互配置\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // 指定要更新的交互\n  sensitivity: 2.0, // 新的缩放灵敏度\n  enableOptimize: true, // 添加新配置\n});\n```\n\n**示例 2**: 禁用/启用交互\n\n```typescript\n// 设置带 key 的行为\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// 禁用拖拽功能\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// 稍后重新启用\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## 类型定义\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // 交互类型\n  type: string;\n\n  // 交互 key，即唯一标识，用于标识交互，从而进一步操作此交互\n  key?: string;\n\n  // 针对不同类型的交互，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // 要更新的交互的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"交互","order":"8"},"isInternal":false,"tokens":1029,"sizeBytes":5513},{"name":"canvas.en.md","path":"packages/site/docs/api/canvas.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/canvas.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Canvas Operations\norder: 1\n---\n\n## Overview of Canvas Operations\n\nG6 provides a series of canvas operation APIs to control and obtain basic information about the canvas. With these APIs, you can:\n\n- Get the canvas instance\n- Get and set the canvas size\n- Operate the canvas renderer and layers\n\n## API Reference\n\n### Graph.getCanvas()\n\nGet the canvas instance, which can be used for low-level canvas operations.\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**Return Value Description**\n\nThe Canvas instance includes the following main functions:\n\n- `getLayer(name?: string)`: Get the specified layer\n- `getLayers()`: Get all layers\n- `getCamera()`: Get the camera instance\n- `getRoot()`: Get the root node\n- `setCursor(cursor: string)`: Set the mouse cursor style\n\n**Example**\n\n```typescript\n// Get the canvas instance\nconst canvas = graph.getCanvas();\n\n// Get the main layer\nconst mainLayer = canvas.getLayer('main');\n\n// Set the mouse cursor style\ncanvas.setCursor('pointer');\n\n// Get the root node of the canvas\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\nGet the size of the current canvas container. Returns an array containing the width and height.\n\n```typescript\ngetSize(): [number, number];\n```\n\n**Example**\n\n```typescript\n// Get the canvas size\nconst [width, height] = graph.getSize();\nconsole.log('Canvas width:', width);\nconsole.log('Canvas height:', height);\n\n// Use the size information for calculations\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\nSet the size of the canvas container. This method will update both the canvas and container size.\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description            | Type   | Default | Required |\n| --------- | ---------------------- | ------ | ------- | -------- |\n| width     | Canvas width (pixels)  | number | -       | ✓        |\n| height    | Canvas height (pixels) | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set a fixed size\ngraph.setSize(800, 600);\n```\n","frontmatter":{"title":"Canvas Operations","order":"1"},"isInternal":false,"tokens":516,"sizeBytes":2068},{"name":"canvas.zh.md","path":"packages/site/docs/api/canvas.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/canvas.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 画布操作\norder: 1\n---\n\n## 画布操作概述\n\nG6 提供了一系列画布操作 API，用于控制和获取画布的基本信息。通过这些 API，你可以：\n\n- 获取画布实例\n- 获取和设置画布尺寸\n- 操作画布渲染器和图层\n\n## API 参考\n\n### Graph.getCanvas()\n\n获取画布实例，返回的实例可用于进行底层的画布操作。\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**返回值类型说明**\n\nCanvas 实例包含以下主要功能：\n\n- `getLayer(name?: string)`: 获取指定图层\n- `getLayers()`: 获取所有图层\n- `getCamera()`: 获取相机实例\n- `getRoot()`: 获取根节点\n- `setCursor(cursor: string)`: 设置鼠标样式\n\n**示例**\n\n```typescript\n// 获取画布实例\nconst canvas = graph.getCanvas();\n\n// 获取主图层\nconst mainLayer = canvas.getLayer('main');\n\n// 设置鼠标样式\ncanvas.setCursor('pointer');\n\n// 获取画布根节点\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\n获取当前画布容器的尺寸。返回一个包含宽度和高度的数组。\n\n```typescript\ngetSize(): [number, number];\n```\n\n**示例**\n\n```typescript\n// 获取画布尺寸\nconst [width, height] = graph.getSize();\nconsole.log('画布宽度:', width);\nconsole.log('画布高度:', height);\n\n// 使用尺寸信息进行计算\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\n设置画布容器的尺寸。这个方法会同时更新画布和容器的大小。\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述             | 类型   | 默认值 | 必选 |\n| ------ | ---------------- | ------ | ------ | ---- |\n| width  | 画布宽度（像素） | number | -      | ✓    |\n| height | 画布高度（像素） | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置固定尺寸\ngraph.setSize(800, 600);\n```\n","frontmatter":{"title":"画布操作","order":"1"},"isInternal":false,"tokens":327,"sizeBytes":1886},{"name":"coordinate.en.md","path":"packages/site/docs/api/coordinate.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/coordinate.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Coordinate Transformation\norder: 12\n---\n\n## Overview of Coordinate Systems\n\nUnderstanding different coordinate systems and their transformations is crucial in graph visualization. G6 involves multiple coordinate systems, each used for different scenarios:\n\n- **Client Coordinate System**: Origin is at the top-left corner of the browser viewport, measured in pixels. Typically used for handling browser events.\n- **Screen Coordinate System**: Origin is at the top-left corner of the screen, affected by page scrolling.\n- **Page Coordinate System**: Origin is at the top-left corner of the document, considering document scrolling.\n- **Canvas Coordinate System**: Also known as the world coordinate system, used for drawing and layout, with the origin at the top-left corner of the canvas element.\n- **Viewport Coordinate System**: The visible area of the canvas, with the origin at the top-left corner of the viewport. The viewport can be panned and zoomed to view different areas of the Canvas.\n\nIn this [example](https://g.antv.antgroup.com/en/examples/canvas/canvas-basic#coordinates), moving the mouse shows the position in various coordinate systems:\n\n![Coordinate System Diagram](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\nWhen the canvas is not panned or zoomed, the Viewport and Canvas coordinate systems coincide. With user interactions like dragging or zooming, the two systems may shift.\n\nG6 provides a series of APIs for converting between different coordinate systems, detailed below.\n\n## API Reference\n\n### Graph.getCanvasByClient(point)\n\nConvert browser coordinates (client coordinates) to canvas coordinates.\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description              | Type                                         | Default | Required |\n| --------- | ------------------------ | -------------------------------------------- | ------- | -------- |\n| point     | Browser coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getCanvasByViewport(point)\n\nConvert viewport coordinates to canvas coordinates.\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                         | Default | Required |\n| --------- | ------------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Viewport coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getClientByCanvas(point)\n\nConvert canvas coordinates to browser client coordinates.\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the browser client coordinate system\n\n### Graph.getViewportByCanvas(point)\n\nConvert canvas coordinates to viewport coordinates.\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the viewport coordinate system\n","frontmatter":{"title":"Coordinate Transformation","order":"12"},"isInternal":false,"tokens":1040,"sizeBytes":4165},{"name":"coordinate.zh.md","path":"packages/site/docs/api/coordinate.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/coordinate.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 坐标转换\norder: 12\n---\n\n## 坐标系概述\n\n在图可视化中，理解不同的坐标系及其转换关系至关重要。G6 中涉及多种坐标系，它们各自用于不同的场景：\n\n- **Client 坐标系**：浏览器视口左上角为原点，单位为像素。通常用于处理浏览器事件。\n- **Screen 坐标系**：屏幕左上角为原点，会受页面滚动影响。\n- **Page 坐标系**：文档左上角为原点，考虑文档滚动。\n- **Canvas 坐标系**：也称为世界坐标系，图形绘制和布局时使用的坐标系，画布元素左上角为原点。\n- **Viewport 坐标系**：视口坐标系，当前可见的画布区域，视口左上角为原点。视口通过平移、缩放等操作，可以观察不同的 Canvas 区域。\n\n在这个[示例](https://g.antv.antgroup.com/zh/examples/canvas/canvas-basic#coordinates)中，移动鼠标可以看到鼠标所在位置在各个坐标系下的值：\n\n![坐标系关系图](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\n当画布没有发生平移和缩放时，Viewport 坐标系与 Canvas 坐标系重合。随着用户的交互（如拖拽画布、缩放），两个坐标系会出现偏移。\n\nG6 提供了一系列 API 用于在不同坐标系之间进行转换，下面将详细介绍这些 API。\n\n## API 参考\n\n### Graph.getCanvasByClient(point)\n\n将浏览器坐标（客户端坐标）转换为画布坐标。\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述         | 类型                                         | 默认值 | 必选 |\n| ----- | ------------ | -------------------------------------------- | ------ | ---- |\n| point | 浏览器坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getCanvasByViewport(point)\n\n将视口坐标转换为画布坐标。\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 视口坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getClientByCanvas(point)\n\n将画布坐标转换为浏览器客户端坐标。\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 浏览器客户端坐标系下的坐标点\n\n### Graph.getViewportByCanvas(point)\n\n将画布坐标转换为视口坐标。\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 视口坐标系下的坐标点\n","frontmatter":{"title":"坐标转换","order":"12"},"isInternal":false,"tokens":623,"sizeBytes":3607},{"name":"data.en.md","path":"packages/site/docs/api/data.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/data.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Data\norder: 0\n---\n\n## Overview of Data Operations\n\nG6 provides a comprehensive [data](/en/manual/data) operation API, covering the complete lifecycle of graph data from query, modification to update.\n\n## API Reference\n\n### Graph.getData()\n\nGet the complete data of the graph.\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**Return Value**:\n\n- **Type**: [GraphData](#graphdata)\n\n- **Description**: Returns the complete graph data containing all nodes, edges, and combo data\n\n**Example**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('Node data:', graphData.nodes);\nconsole.log('Edge data:', graphData.edges);\nconsole.log('Combo data:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\nGet node data, supporting three calling methods.\n\n```typescript\n// Get all node data\ngetNodeData(): NodeData[];\n\n// Get single node data\ngetNodeData(id: ID): NodeData;\n\n// Get multiple node data\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Node ID       | string   | -       |          |\n| ids       | Node ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **Description**: Returns the specified node data or node data array\n\n**Example**:\n\n```typescript\n// Get all nodes\nconst nodes = graph.getNodeData();\n\n// Get single node\nconst node = graph.getNodeData('node1');\nconsole.log('Node position:', node.style.x, node.style.y);\n\n// Get multiple nodes\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\nGet edge data, supporting three calling methods.\n\n```typescript\n// Get all edge data\ngetEdgeData(): EdgeData[];\n\n// Get single edge data\ngetEdgeData(id: ID): EdgeData;\n\n// Get multiple edge data\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Edge ID       | string   | -       |          |\n| ids       | Edge ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **Description**: Returns the specified edge data or edge data array\n\n**Example**:\n\n```typescript\n// Get all edges\nconst edges = graph.getEdgeData();\n\n// Get single edge\nconst edge = graph.getEdgeData('edge1');\nconsole.log('Edge source and target:', edge.source, edge.target);\n\n// Get multiple edges\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\nGet combo data, supporting three calling methods.\n\n```typescript\n// Get all combo data\ngetComboData(): ComboData[];\n\n// Get single combo data\ngetComboData(id: ID): ComboData;\n\n// Get multiple combo data\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter | Description    | Type     | Default | Required |\n| --------- | -------------- | -------- | ------- | -------- |\n| id        | Combo ID       | string   | -       |          |\n| ids       | Combo ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **Description**: Returns the specified combo data or combo data array\n\n**Example**:\n\n```typescript\n// Get all combos\nconst combos = graph.getComboData();\n\n// Get single combo\nconst combo = graph.getComboData('combo1');\nconsole.log('Nodes in combo:', combo.children);\n\n// Get multiple combos\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\nGet single element data, supporting two calling methods.\n\n⚠️ **Note**: This API directly gets the data of the element without considering the element type.\n\n```typescript\n// Get single element data\ngetElementData(id: ID): ElementDatum;\n\n// Get multiple element data\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type     | Default | Required |\n| --------- | ---------------- | -------- | ------- | -------- |\n| id        | Element ID       | string   | -       |          |\n| ids       | Element ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: ElementDatum \\| ElementDatum[]\n- **Description**: Directly gets the data of the element without considering the element type\n\n**Example**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('Element data:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('Multiple element data:', elements);\n```\n\n### Graph.getElementDataByState()\n\nGet element data in a specified state, supporting three calling methods.\n\n```typescript\n// Get node data in a specified state\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// Get edge data in a specified state\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// Get combo data in a specified state\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter   | Description  | Type                              | Default | Required |\n| ----------- | ------------ | --------------------------------- | ------- | -------- |\n| elementType | Element type | `'node'` \\| `'edge'` \\| `'combo'` | -       | ✓        |\n| state       | State        | string                            | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **Description**: Returns node data, edge data, or combo data in the specified state\n\n**Example**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('Selected nodes:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('Selected edges:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('Selected combos:', selectedCombos);\n```\n\n**Built-in States**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\nGet the data of neighbor nodes of a node or combo.\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[]\n- **Description**: Returns neighbor node data\n\n**Example**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('Neighbor nodes:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\nGet the data of edges related to a node or combo.\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type                          | Default | Required |\n| --------- | ---------------- | ----------------------------- | ------- | -------- |\n| id        | Node or combo ID | string                        | -       | ✓        |\n| direction | Edge direction   | `'in'` \\| `'out'` \\| `'both'` | -       |          |\n\n**Return Value**:\n\n- **Type**: EdgeData[]\n- **Description**: Returns the data of edges related to the specified node or combo\n\n**Example**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('Related edges:', relatedEdges);\n```\n\n### Graph.getParentData()\n\nGet the data of the parent element of a node or combo.\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       |          |\n\n**Return Value**:\n\n- **Type**: NodeData \\| ComboData \\| undefined\n- **Description**: Returns the parent element data, or undefined if it does not exist\n\n**Example**:\n\n```typescript\n// Get the parent node in a tree graph\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// Get the parent combo in a combo\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\nGet the data of child elements of a node or combo.\n\n```typescript\ngetChildrenData(id: ID): (NodeData \\| ComboData)[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: (NodeData \\| ComboData)[]\n- **Description**: Returns an array of child element data\n\n**Note**:\n\n- **Querying combo's child elements**: If the id corresponds to a combo element, you can directly use this API to get all its child elements.\n- **Querying node's child elements**: If the id corresponds to a node, only when the graph data is a tree structure (i.e., the node data maintains a `children` field, and `children` is an array of child node IDs for that node), can you use this API to get the child elements of that node. Otherwise, an empty array is returned.\n\n**Example**:\n\n```typescript\n// Get the child elements of a combo\nconst children = graph.getChildrenData('combo1');\nconsole.log('Number of child nodes:', children.length);\n\n// Process each child element\nchildren.forEach((child) => {\n  console.log('Child element ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\nGet the data of all ancestor elements of a node or combo.\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of ancestor element data, ordered from parent to root\n\n**Example**:\n\n```typescript\n// Get all ancestor nodes in a tree graph\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  'Ancestor node path:',\n  treeAncestors.map((node) => node.id),\n);\n\n// Get all parent combos in a combo\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\nGet the data of all descendant elements of a node or combo.\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of descendant element data\n\n**Example**:\n\n```typescript\n// Get all descendants of a node\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('Number of descendants:', descendants.length);\n\n// Process all descendant elements\ndescendants.forEach((descendant) => {\n  console.log('Descendant element ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\nSet the complete data of the graph.\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                        | Default | Required |\n| --------- | ----------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | New graph data or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Directly set data\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// Use functional incremental update: get current graph data and return new graph data\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\nAdd new element data.\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                              | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Graph data to add or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\nAdd new node data.\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Node data to add or a function returning node data | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single node\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: 'Node 1' },\n  },\n]);\n\n// Add multiple nodes\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// Functional addition\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\nAdd new edge data.\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                          | Default | Required |\n| --------- | -------------------------------------------------- | ------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to add or a function returning edge data | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single edge\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: 'Relation',\n    },\n  },\n]);\n\n// Add multiple edges\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// Functional addition\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\nAdd new combo data.\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                          | Type                                                            | Default | Required |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to add or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\nAdd child node data to a tree graph node.\n\n⚠️ **Note**: Use addNodeData / addComboData methods to add child nodes to a combo.\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**Parameters**:\n\n| Parameter    | Description     | Type                    | Default | Required |\n| ------------ | --------------- | ----------------------- | ------- | -------- |\n| parentId     | Parent node ID  | string                  | -       | ✓        |\n| childrenData | Child node data | [NodeData](#nodedata)[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\nRemove element data.\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                               | Type                                               | Default | Required |\n| --------- | --------------------------------------------------------- | -------------------------------------------------- | ------- | -------- |\n| ids       | Element IDs to remove or a function returning element IDs | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\nRemove node data.\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Node IDs to remove or a function returning node IDs | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\nRemove edge data.\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Edge IDs to remove or a function returning edge IDs | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\nRemove combo data.\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                            | Default | Required |\n| --------- | ----------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Combo IDs to remove or a function returning combo IDs | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\nUpdate element data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                 | Type                                                                             | Default | Required |\n| --------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Element data to update or a function returning element data | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\nUpdate node data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                           | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------- | ------- | -------- |\n| data      | Node data to update or a function returning node data | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\nUpdate edge data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                                                                                         | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to update or a function returning edge data | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\nUpdate combo data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                             | Type                                                            | Default | Required |\n| --------- | ------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to update or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\nDetermine if an node exists\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n| Parameter | Description | Type | Default | Required |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id | Node ID to be judged | [ID](#id) | - | ✓ |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\nDetermine if an edge exists\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description          | Type      | Default | Required |\n| --------- | -------------------- | --------- | ------- | -------- |\n| id        | Edge ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\nDetermine if combo exists\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description           | Type      | Default | Required |\n| --------- | --------------------- | --------- | ------- | -------- |\n| id        | Combo ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## Type Definitions\n\n### ID\n\nElement ID type.\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\nMultiple element ID type.\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 graph data type.\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\nNode data type.\n\n```typescript\ninterface NodeData {\n  id: string; // Node ID\n  type?: string; // Node type\n  data?: Record<string, any>; // Node data\n  style?: Record<string, any>; // Node style\n  states?: string[]; // Initial node states\n  combo?: string; // Belonging combo\n  children?: string[]; // Array of child node IDs\n}\n```\n\nFor detailed type definitions, please refer to [Node Data](/en/manual/data#nodedata).\n\n### EdgeData\n\nEdge data type.\n\n```typescript\ninterface EdgeData {\n  source: string; // Source ID\n  target: string; // Target ID\n  id?: string; // Edge ID\n  type?: string; // Edge type\n  data?: Record<string, any>; // Edge data\n  style?: Record<string, any>; // Edge style\n  states?: string[]; // Initial edge states\n}\n```\n\nFor detailed type definitions, please refer to [Edge Data](/en/manual/data#edgedata).\n\n### ComboData\n\nCombo data type.\n\n```typescript\ninterface ComboData {\n  id: string; // Combo ID\n  type?: string; // Combo type\n  data?: Record<string, any>; // Combo data\n  style?: Record<string, any>; // Combo style\n  states?: string[]; // Initial combo states\n  combo?: string; // Parent combo ID\n}\n```\n\nFor detailed type definitions, please refer to [Combo Data](/en/manual/data#combodata).\n","frontmatter":{"title":"Data","order":"0"},"isInternal":false,"tokens":6570,"sizeBytes":26410},{"name":"data.zh.md","path":"packages/site/docs/api/data.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/data.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 数据\norder: 0\n---\n\n## 数据操作概述\n\nG6 提供了一套全面的 [数据](/manual/data) 操作 API，覆盖了图数据从查询、修改到更新的完整生命周期。\n\n## API 参考\n\n### Graph.getData()\n\n获取图的完整数据。\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**返回值**:\n\n- **类型**: [GraphData](#graphdata)\n\n- **描述**: 返回包含所有节点、边和组合数据的完整图数据\n\n**示例**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('节点数据:', graphData.nodes);\nconsole.log('边数据:', graphData.edges);\nconsole.log('组合数据:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\n获取节点数据，支持三种调用方式。\n\n```typescript\n// 获取所有节点数据\ngetNodeData(): NodeData[];\n\n// 获取单个节点数据\ngetNodeData(id: ID): NodeData;\n\n// 批量获取多个节点数据\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 节点 ID      | string   | -      |      |\n| ids  | 节点 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **描述**: 返回指定的节点数据或节点数据数组\n\n**示例**:\n\n```typescript\n// 获取所有节点\nconst nodes = graph.getNodeData();\n\n// 获取单个节点\nconst node = graph.getNodeData('node1');\nconsole.log('节点位置:', node.style.x, node.style.y);\n\n// 获取多个节点\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\n获取边数据，支持三种调用方式。\n\n```typescript\n// 获取所有边数据\ngetEdgeData(): EdgeData[];\n\n// 获取单条边数据\ngetEdgeData(id: ID): EdgeData;\n\n// 批量获取多条边数据\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**参数**:\n\n| 参数 | 描述       | 类型     | 默认值 | 必选 |\n| ---- | ---------- | -------- | ------ | ---- |\n| id   | 边 ID      | string   | -      |      |\n| ids  | 边 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **描述**: 返回指定的边数据或边数据数组\n\n**示例**:\n\n```typescript\n// 获取所有边\nconst edges = graph.getEdgeData();\n\n// 获取单条边\nconst edge = graph.getEdgeData('edge1');\nconsole.log('边的起点和终点:', edge.source, edge.target);\n\n// 获取多条边\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\n获取组合数据,支持三种调用方式。\n\n```typescript\n// 获取所有组合数据\ngetComboData(): ComboData[];\n\n// 获取单个组合数据\ngetComboData(id: ID): ComboData;\n\n// 批量获取多个组合数据\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 组合 ID      | string   | -      |      |\n| ids  | 组合 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **描述**: 返回指定的组合数据或组合数据数组\n\n**示例**:\n\n```typescript\n// 获取所有组合\nconst combos = graph.getComboData();\n\n// 获取单个组合\nconst combo = graph.getComboData('combo1');\nconsole.log('组合包含的节点:', combo.children);\n\n// 获取多个组合\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\n获取单个元素数据，支持两种调用方式。\n\n⚠️ **注意**: 此 API 直接获取元素的数据而不必考虑元素类型。\n\n```typescript\n// 获取单个元素数据\ngetElementData(id: ID): ElementDatum;\n\n// 批量获取多个元素数据\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 元素 ID      | string   | -      |      |\n| ids  | 元素 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: ElementDatum \\| ElementDatum[]\n- **描述**: 直接获取元素的数据而不必考虑元素类型\n\n**示例**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('元素数据:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('多个元素数据:', elements);\n```\n\n### Graph.getElementDataByState()\n\n获取指定状态下的元素数据，支持三种调用方式。\n\n```typescript\n// 获取指定状态下的节点数据\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// 获取指定状态下的边数据\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// 获取指定状态下的组合数据\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**参数**:\n\n| 参数        | 描述     | 类型                              | 默认值 | 必选 |\n| ----------- | -------- | --------------------------------- | ------ | ---- |\n| elementType | 元素类型 | `'node'` \\| `'edge'` \\| `'combo'` | -      | ✓    |\n| state       | 状态     | string                            | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **描述**: 返回指定状态下的节点数据、边数据或组合数据\n\n**示例**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('选中的节点:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('选中的边:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('选中的组合:', selectedCombos);\n```\n\n**内置状态**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\n获取节点或组合的一跳邻居节点数据。\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[]\n- **描述**: 返回邻居节点数据\n\n**示例**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('邻居节点:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\n获取节点或组合关联边的数据。\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**参数**:\n\n| 参数      | 描述            | 类型                          | 默认值 | 必选 |\n| --------- | --------------- | ----------------------------- | ------ | ---- |\n| id        | 节点或组合的 ID | string                        | -      | ✓    |\n| direction | 边的方向        | `'in'` \\| `'out'` \\| `'both'` | -      |      |\n\n**返回值**:\n\n- **类型**: EdgeData[]\n- **描述**: 返回与指定节点或组合关联的边数据\n\n**示例**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('关联边:', relatedEdges);\n```\n\n### Graph.getParentData()\n\n获取节点或组合的父元素数据。\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      |      |\n\n**返回值**:\n\n- **类型**: NodeData \\| ComboData \\| undefined\n- **描述**: 返回父元素数据,如果不存在则返回 undefined\n\n**示例**:\n\n```typescript\n// 获取树图中节点的父节点\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// 获取组合中节点的父组合\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\n获取节点或组合的子元素数据。\n\n```typescript\ngetChildrenData(id: ID):(NodeData \\| ComboData)[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: (NodeData \\| ComboData)[]\n- **描述**: 返回子元素数据数组\n\n**注意**:\n\n- **查询 combo 的子元素**：如果 id 对应的是 combo 元素，可以直接通过此 API 获取其所有子元素。\n- **查询节点的子元素**：如果 id 对应的是节点，只有当图数据为树结构（即节点数据中维护有 `children` 字段，且 `children` 为该节点的子节点 ID 数组）时，才能通过此 API 获取到该节点的子元素。否则返回空数组。\n\n**示例**:\n\n```typescript\n// 获取组合的子元素\nconst children = graph.getChildrenData('combo1');\nconsole.log('子节点数量:', children.length);\n\n// 处理每个子元素\nchildren.forEach((child) => {\n  console.log('子元素ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\n获取节点或组合的所有祖先元素数据。\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回祖先元素数据数组，从父节点到根节点的顺序排列\n\n**示例**:\n\n```typescript\n// 获取树图中节点的所有祖先节点\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  '祖先节点路径:',\n  treeAncestors.map((node) => node.id),\n);\n\n// 获取组合中节点的所有父组合\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\n获取节点或组合的所有后代元素数据。\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回后代元素数据数组\n\n**示例**:\n\n```typescript\n// 获取节点的所有后代\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('后代数量:', descendants.length);\n\n// 处理所有后代元素\ndescendants.forEach((descendant) => {\n  console.log('后代元素ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\n设置图的完整数据。\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                           | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 新的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 直接设置数据\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// 使用函数式增量更新：获取当前图数据，并返回新的图数据\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\n新增元素数据。\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 需要添加的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\n新增节点数据。\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 要添加的节点数据或返回节点数据的函数 | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: '节点 1' },\n  },\n]);\n\n// 批量添加节点\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// 函数式添加\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\n新增边数据。\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                          | 默认值 | 必选 |\n| ---- | -------------------------------- | ------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的边数据或返回边数据的函数 | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单条边\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: '关系',\n    },\n  },\n]);\n\n// 批量添加边\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// 函数式添加\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\n新增组合数据。\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\n为树图节点添加子节点数据。\n\n⚠️ **注意**: 为组合添加子节点使用 addNodeData / addComboData 方法。\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**参数**:\n\n| 参数         | 描述       | 类型                    | 默认值 | 必选 |\n| ------------ | ---------- | ----------------------- | ------ | ---- |\n| parentId     | 父节点 ID  | string                  | -      | ✓    |\n| childrenData | 子节点数据 | [NodeData](#nodedata)[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\n删除元素数据。\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                               | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的元素 ID 或返回元素 ID 的函数 | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\n删除节点数据。\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的节点 ID 或返回节点 ID 的函数 | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\n删除边数据。\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                            | 默认值 | 必选 |\n| ---- | -------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的边 ID 或返回边 ID 的函数 | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\n删除组合数据。\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的组合 ID 或返回组合 ID 的函数 | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\n更新元素数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                                             | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的元素数据或返回元素数据的函数 | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\n更新节点数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                           | 默认值 | 必选 |\n| ---- | ------------------------------------ | ---------------------------------------------- | ------ | ---- |\n| data | 要更新的节点数据或返回节点数据的函数 | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\n更新边数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                                                                                         | 默认值 | 必选 |\n| ---- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的边数据或返回边数据的函数 | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\n更新组合数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\n判断节点是否存在\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                 | 类型      | 默认值 | 必选 |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的节点id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\n判断边是否存在\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述               | 类型      | 默认值 | 必选 |\n| ---- | ------------------ | --------- | ------ | ---- |\n| id   | 需要进行判断的边id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\n判断combo是否存在\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                      | 类型      | 默认值 | 必选 |\n| ---- | ------------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的combo组合id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## 类型定义\n\n### ID\n\n元素 ID 类型。\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\n多个元素 ID 类型。\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 图数据类型。\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\n节点数据类型。\n\n```typescript\ninterface NodeData {\n  id: string; // 节点 ID\n  type?: string; // 节点类型\n  data?: Record<string, any>; // 节点数据\n  style?: Record<string, any>; // 节点样式\n  states?: string[]; // 节点初始状态\n  combo?: string; // 所属组合\n  children?: string[]; // 子节点 ID 数组\n}\n```\n\n详细类型定义请参考 [节点数据](/manual/data#节点数据nodedata)。\n\n### EdgeData\n\n边数据类型。\n\n```typescript\ninterface EdgeData {\n  source: string; // 起点 ID\n  target: string; // 终点 ID\n  id?: string; // 边 ID\n  type?: string; // 边类型\n  data?: Record<string, any>; // 边数据\n  style?: Record<string, any>; // 边样式\n  states?: string[]; // 边初始状态\n}\n```\n\n详细类型定义请参考 [边数据](/manual/data#边数据edgedata)。\n\n### ComboData\n\n组合数据类型。\n\n```typescript\ninterface ComboData {\n  id: string; // 组合 ID\n  type?: string; // 组合类型\n  data?: Record<string, any>; // 组合数据\n  style?: Record<string, any>; // 组合样式\n  states?: string[]; // 组合初始状态\n  combo?: string; // 父组合 ID\n}\n```\n\n详细类型定义请参考 [组合数据](/manual/data#组合数据combodata)。\n","frontmatter":{"title":"数据","order":"0"},"isInternal":false,"tokens":5071,"sizeBytes":24904},{"name":"element.en.md","path":"packages/site/docs/api/element.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/element.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Element Operations\norder: 1\n---\n\n## Overview of Element Operations\n\nThe [Element](/en/manual/element/overview) operation API in G6 allows you to control the behavior and attributes of elements such as nodes, edges, and Combos in the graph. These APIs can be used for:\n\n1. **Element State Management**: Set, update, or remove the state of elements\n2. **Element Display Control**: Control the z-index and visibility of elements\n3. **Element Collapse/Expand**: Operate the collapse/expand state of collapsible elements\n4. **Element Position Operations**: Move and align element positions\n5. **Element Focus**: Focus the viewport on specific elements\n\nThrough these operations, you can achieve rich interactive effects and visual presentations.\n\n## API Reference\n\n### Graph.getElementPosition(id)\n\nGet the position of an element.\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Returns the coordinates of the element\n\n**Example**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\nGet the rendering bounding box of the element itself and its child nodes in the world coordinate system.\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [AABB](#aabb)\n- **Description**: Returns the rendering bounding box of the element\n\n### Graph.getElementRenderStyle(id)\n\nGet the rendering style of an element.\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Record<string, any>\n- **Description**: Returns the rendering style of the element\n\n### Graph.getElementState(id)\n\nGet the state of an element.\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [State](#state)[]\n- **Description**: Returns the state of the element\n\n### Graph.getElementType(id)\n\nGet the type of an element.\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: string\n- **Description**: Returns the type of the element\n\n### Graph.getElementVisibility(id)\n\nGet the visibility of an element.\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden';\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: 'visible' | 'hidden'\n- **Description**: Returns the visibility of the element\n\n### Graph.getElementZIndex(id)\n\nGet the z-index of an element.\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: number\n- **Description**: Returns the z-index of the element\n\n### Graph.setElementState(id, state, options)\n\nSet the state of an element, supporting two calling methods:\n\n```typescript\n// Set the state of a single element\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// Set the state of multiple elements\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element State Setting**\n\n| Parameter | Description       | Type            | Default | Required |\n| --------- | ----------------- | --------------- | ------- | -------- | --- |\n| id        | Element ID to set | string          | -       | ✓        |\n| state     | State to set      | [State](#state) | State[] | -        | ✓   |\n| animation | Enable animation  | boolean         | -       |          |\n\n**Batch Element State Setting**\n\n| Parameter | Description                    | Type                       | Default  | Required |\n| --------- | ------------------------------ | -------------------------- | -------- | -------- | --- |\n| state     | Mapping of element ID to state | Record<ID, [State](#state) | State[]> | -        | ✓   |\n| animation | Enable animation               | boolean                    | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the state setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the state of a single element\nawait graph.setElementState('node1', 'selected');\n\n// Set the state of multiple elements\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\nSet the visibility of an element, supporting two calling methods:\n\n```typescript\n// Set the visibility of a single element\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// Set the visibility of multiple elements\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Visibility Setting**\n\n| Parameter  | Description       | Type      | Default  | Required |\n| ---------- | ----------------- | --------- | -------- | -------- | --- |\n| id         | Element ID to set | string    | -        | ✓        |\n| visibility | Visibility to set | 'visible' | 'hidden' | -        | ✓   |\n| animation  | Enable animation  | boolean   | -        |          |\n\n**Batch Element Visibility Setting**\n\n| Parameter  | Description                         | Type                 | Default   | Required |\n| ---------- | ----------------------------------- | -------------------- | --------- | -------- | --- |\n| visibility | Mapping of element ID to visibility | Record<ID, 'visible' | 'hidden'> | -        | ✓   |\n| animation  | Enable animation                    | boolean              | -         |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the visibility setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the visibility of a single element\nawait graph.setElementVisibility('node1', 'hidden');\n\n// Set the visibility of multiple elements\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\nSet the z-index of an element, supporting two calling methods:\n\n```typescript\n// Set the z-index of a single element\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// Set the z-index of multiple elements\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Z-Index Setting**\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n| zIndex    | Z-Index     | number | -       | ✓        |\n\n**Batch Element Z-Index Setting**\n\n| Parameter | Description                      | Type               | Default | Required |\n| --------- | -------------------------------- | ------------------ | ------- | -------- |\n| zIndex    | Mapping of element ID to z-index | Record<ID, number> | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the z-index setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the z-index of a single element\nawait graph.setElementZIndex('node1', 10);\n\n// Set the z-index of multiple elements\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\nSet the node style mapping, i.e., the value of `options.node`.\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| node      | Node configuration | [NodeOptions](/en/manual/element/node/overview) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Set the fill color of all nodes to red\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\nSet the edge style mapping, i.e., the value of `options.edge`.\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| edge      | Edge configuration | [EdgeOptions](/en/manual/element/edge/overview) | -       | ✓        |\n\n### Graph.setCombo(combo)\n\nSet the combo style mapping, i.e., the value of `options.combo`.\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description         | Type                                              | Default | Required |\n| --------- | ------------------- | ------------------------------------------------- | ------- | -------- |\n| combo     | Combo configuration | [ComboOptions](/en/manual/element/combo/overview) | -       | ✓        |\n\n### Graph.collapseElement(id, options)\n\nCollapse the specified element, usually used to collapse Combos or nodes with child elements.\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                     | Type    | Default                                                 | Required |\n| --------- | --------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to collapse                                          | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for collapsing nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the collapse operation is complete\n\n**Example**:\n\n```typescript\n// Simple collapse with default configuration\nawait graph.collapseElement('combo1');\n\n// Collapse with animation\ngraph.collapseElement('combo1', true);\n\n// Collapse while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\nExpand the specified element, usually used to expand previously collapsed Combos or nodes.\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                    | Type    | Default                                                 | Required |\n| --------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to expand                                           | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for expanding nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the expand operation is complete\n\n**Example**:\n\n```typescript\n// Simple expand with default configuration\nawait graph.expandElement('combo1');\n\n// Expand with animation\nawait graph.expandElement('combo1', true);\n\n// Expand while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\nBring the specified element to the front, making it appear above other overlapping elements.\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default  | Required |\n| --------- | ----------- | ------ | -------- | -------- | --- |\n| id        | Element ID  | string | string[] | -        | ✓   |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\n// Bring a node to the front\ngraph.frontElement('node1');\n\n// Bring multiple selected nodes to the front\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\nShow the specified element.\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the show operation is complete\n\n**Example**:\n\n```typescript\n// Show a single element\nawait graph.showElement('node1');\n\n// Show an element with animation\nawait graph.showElement('node1', true);\n\n// Show multiple elements\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\nHide the specified element.\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the hide operation is complete\n\n**Example**:\n\n```typescript\n// Hide an element without animation\nawait graph.hideElement('node1');\n\n// Hide an element with animation\nawait graph.hideElement('node1', true);\n\n// Hide multiple elements\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\nTranslate an element by a specified distance, supporting two calling methods:\n\n```typescript\n// Translate an element by a specified distance (relative translation)\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// Translate multiple elements by a specified distance (relative translation)\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Translation**\n\n| Parameter | Description                            | Type             | Default | Required |\n| --------- | -------------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                             | string           | -       | ✓        |\n| offset    | Relative translation distance [dx, dy] | [number, number] | -       | ✓        |\n| animation | Enable animation                       | boolean          | -       |          |\n\n**Batch Element Translation**\n\n| Parameter | Description                                   | Type                         | Default | Required |\n| --------- | --------------------------------------------- | ---------------------------- | ------- | -------- |\n| offsets   | Mapping of element ID to translation distance | Record<ID, [number, number]> | -       | ✓        |\n| animation | Enable animation                              | boolean                      | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the translation operation is complete\n\n**Example**:\n\n```typescript\n// Translate right by 100 pixels and down by 50 pixels\nawait graph.translateElementBy('node1', [100, 50]);\n\n// Translate with animation\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// Apply the same translation to multiple nodes\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\nMove an element to a specified position, supporting two calling methods:\n\n```typescript\n// Move an element to a specified position (absolute position)\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// Move multiple elements to specified positions (absolute position)\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Movement**\n\n| Parameter | Description                     | Type             | Default | Required |\n| --------- | ------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                      | string           | -       | ✓        |\n| position  | Target absolute position [x, y] | [number, number] | -       | ✓        |\n| animation | Enable animation                | boolean          | -       |          |\n\n**Batch Element Movement**\n\n| Parameter | Description                              | Type                             | Default | Required |\n| --------- | ---------------------------------------- | -------------------------------- | ------- | -------- |\n| positions | Mapping of element ID to target position | Record<string, [number, number]> | -       | ✓        |\n| animation | Enable animation                         | boolean                          | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the movement operation is complete\n\n**Example**:\n\n```typescript\n// Move a node to position (200, 300) on the canvas\nawait graph.translateElementTo('node1', [200, 300]);\n\n// Move with animation\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// Arrange a group of nodes neatly\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\nFocus on the specified element, centering it in the viewport.\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                         | Type                                                            | Default  | Required |\n| --------- | ----------------------------------- | --------------------------------------------------------------- | -------- | -------- | --- |\n| id        | One or more element IDs to focus on | string                                                          | string[] | -        | ✓   |\n| animation | Viewport animation configuration    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the focus operation is complete\n\n**Example**:\n\n```typescript\n// Focus on a single node\nawait graph.focusElement('node1');\n\n// Use custom animation configuration\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// Focus on multiple nodes\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## Type Definitions\n\n### CollapseExpandNodeOptions\n\nConfiguration options for collapsing or expanding elements.\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * Enable animation\n   */\n  animation?: boolean;\n  /**\n   * Ensure the position of expanded/collapsed nodes remains unchanged\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) is a fundamental concept in computer graphics.\n\n```typescript\ninterface AABB {\n  x: number; // x-coordinate of the top-left corner of the rectangle\n  y: number; // y-coordinate of the top-left corner of the rectangle\n  width: number; // Width of the rectangle\n  height: number; // Height of the rectangle\n}\n```\n\n### State\n\nElement state type.\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","frontmatter":{"title":"Element Operations","order":"1"},"isInternal":false,"tokens":5341,"sizeBytes":21426},{"name":"element.zh.md","path":"packages/site/docs/api/element.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/element.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 元素操作\norder: 1\n---\n\n## 元素操作概述\n\nG6 中的 [元素](/manual/element/overview) 操作 API 允许您控制图中节点、边和组合(Combo)等元素的行为和属性。这些 API 可以用于：\n\n1. **元素状态管理**：设置、更新或移除元素的状态\n2. **元素显示控制**：控制元素的层级、可见性\n3. **元素展开/收起**：操作可折叠元素的展开/收起状态\n4. **元素位置操作**：移动、对齐元素位置\n5. **元素聚焦**：将视口聚焦到特定元素\n\n通过这些操作，您可以实现丰富的交互效果和视觉呈现。\n\n## API 参考\n\n### Graph.getElementPosition(id)\n\n获取元素位置。\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 返回元素的坐标位置\n\n**示例**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\n获取元素自身以及子节点在世界坐标系下的渲染包围盒。\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [AABB](#aabb)\n- **描述**: 返回元素的渲染包围盒\n\n### Graph.getElementRenderStyle(id)\n\n获取元素的渲染样式。\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Record\\<string, any\\>\n- **描述**: 返回元素的渲染样式\n\n### Graph.getElementState(id)\n\n获取元素的状态。\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [State](#state)[]\n- **描述**: 返回元素的状态\n\n### Graph.getElementType(id)\n\n获取元素类型。\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: string\n- **描述**: 返回元素的类型\n\n### Graph.getElementVisibility(id)\n\n获取元素可见性。\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden' ;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: 'visible' | 'hidden'\n- **描述**: 返回元素的可见性\n\n### Graph.getElementZIndex(id)\n\n获取元素层级。\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: number\n- **描述**: 返回元素的层级\n\n### Graph.setElementState(id, state, options)\n\n设置元素状态，支持两种调用方式：\n\n```typescript\n// 设置单个元素状态\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// 批量设置元素状态\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素状态设置**\n\n| 参数      | 描述                | 类型                       | 默认值 | 必选 |\n| --------- | ------------------- | -------------------------- | ------ | ---- |\n| id        | 要设置状态的元素 ID | string                     | -      | ✓    |\n| state     | 要设置的状态        | [State](#state) \\| State[] | -      | ✓    |\n| animation | 是否启用动画        | boolean                    | -      |      |\n\n**批量元素状态设置**\n\n| 参数      | 描述               | 类型                                   | 默认值 | 必选 |\n| --------- | ------------------ | -------------------------------------- | ------ | ---- |\n| state     | 元素ID到状态的映射 | Record<ID, [State](#state) \\| State[]> | -      | ✓    |\n| animation | 是否启用动画       | boolean                                | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，状态设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素状态\nawait graph.setElementState('node1', 'selected');\n\n// 设置多个元素状态\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\n设置元素的可见性，支持两种调用方式：\n\n```typescript\n// 设置单个元素可见性\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// 批量设置元素可见性\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素可见性设置**\n\n| 参数       | 描述                  | 类型                      | 默认值 | 必选 |\n| ---------- | --------------------- | ------------------------- | ------ | ---- |\n| id         | 要设置可见性的元素 ID | string                    | -      | ✓    |\n| visibility | 要设置的可见性        | `'visible'` \\| `'hidden'` | -      | ✓    |\n| animation  | 是否启用动画          | boolean                   | -      |      |\n\n**批量元素可见性设置**\n\n| 参数       | 描述                 | 类型                                  | 默认值 | 必选 |\n| ---------- | -------------------- | ------------------------------------- | ------ | ---- |\n| visibility | 元素ID到可见性的映射 | Record<ID, `'visible'` \\| `'hidden'`> | -      | ✓    |\n| animation  | 是否启用动画         | boolean                               | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，可见性设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素可见性\nawait graph.setElementVisibility('node1', 'hidden');\n\n// 设置多个元素可见性\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\n设置元素的层级，有两种调用方式：\n\n```typescript\n// 设置单个元素层级\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// 批量设置元素层级\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**参数**:\n\n**单个元素层级设置**\n\n| 参数   | 描述    | 类型   | 默认值 | 必选 |\n| ------ | ------- | ------ | ------ | ---- |\n| id     | 元素 ID | string | -      | ✓    |\n| zIndex | 层级    | number | -      | ✓    |\n\n**批量元素层级设置**\n\n| 参数   | 描述               | 类型               | 默认值 | 必选 |\n| ------ | ------------------ | ------------------ | ------ | ---- |\n| zIndex | 元素ID到层级的映射 | Record<ID, number> | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，层级设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素层级\nawait graph.setElementZIndex('node1', 10);\n\n// 设置多个元素层级\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\n设置节点样式映射。即 `options.node` 的值。\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述     | 类型                                         | 默认值 | 必选 |\n| ---- | -------- | -------------------------------------------- | ------ | ---- |\n| node | 节点配置 | [NodeOptions](/manual/element/node/overview) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 设置所有的节点填充色为红色\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\n设置边样式映射。即 `options.edge` 的值。\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述   | 类型                                         | 默认值 | 必选 |\n| ---- | ------ | -------------------------------------------- | ------ | ---- |\n| edge | 边配置 | [EdgeOptions](/manual/element/edge/overview) | -      | ✓    |\n\n### Graph.setCombo(combo)\n\n设置组合样式映射。即 `options.combo` 的值。\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**参数**:\n\n| 参数  | 描述     | 类型                                           | 默认值 | 必选 |\n| ----- | -------- | ---------------------------------------------- | ------ | ---- |\n| combo | 组合配置 | [ComboOptions](/manual/element/combo/overview) | -      | ✓    |\n\n### Graph.collapseElement(id, options)\n\n收起指定元素，通常用于折叠组合(Combo)或具有子元素的节点。\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要收起的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或收起节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，收起操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单收起，使用默认配置\nawait graph.collapseElement('combo1');\n\n// 收起并启用动画\nawait graph.collapseElement('combo1', true);\n\n// 收起并保证展开/收起的节点位置不变\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\n展开指定元素，通常用于展开先前收起的组合(Combo)或节点。\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要展开的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或展开节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，展开操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单展开，使用默认配置\nawait graph.expandElement('combo1');\n\n// 展开并启用动画\nawait graph.expandElement('combo1', true);\n\n// 展开并保证展开/收起的节点位置不变\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\n将指定元素置于最顶层，使其显示在其他重叠元素之上。\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型               | 默认值 | 必选 |\n| ---- | ------- | ------------------ | ------ | ---- |\n| id   | 元素 ID | string \\| string[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\n// 将节点置于最顶层\ngraph.frontElement('node1');\n\n// 对于选中的多个节点，都置于最顶层\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\n显示指定元素。\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，显示操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 显示单个元素\nawait graph.showElement('node1');\n\n// 带动画显示元素\nawait graph.showElement('node1', true);\n\n// 显示多个元素\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\n隐藏指定元素。\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，隐藏操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 无动画隐藏元素\nawait graph.hideElement('node1');\n\n// 带动画隐藏元素\nawait graph.hideElement('node1', true);\n\n// 隐藏多个元素\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\n相对平移元素指定距离，支持两种调用方式：\n\n```typescript\n// 将元素平移指定距离（相对平移）\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素平移指定距离（相对平移）\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素平移**\n\n| 参数      | 描述                    | 类型             | 默认值 | 必选 |\n| --------- | ----------------------- | ---------------- | ------ | ---- |\n| id        | 要平移的元素 ID         | string           | -      | ✓    |\n| offset    | 平移的相对距离 [dx, dy] | [number, number] | -      | ✓    |\n| animation | 是否启用动画            | boolean          | -      |      |\n\n**批量元素平移**\n\n| 参数      | 描述                   | 类型                         | 默认值 | 必选 |\n| --------- | ---------------------- | ---------------------------- | ------ | ---- |\n| offsets   | 元素ID到平移距离的映射 | Record<ID, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                      | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，平移操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 向右平移100像素，向下平移50像素\nawait graph.translateElementBy('node1', [100, 50]);\n\n// 带动画平移\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// 对多个节点应用相同的平移\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\n将元素移动到指定位置，支持两种调用方式：\n\n```typescript\n// 将元素移动到指定位置（绝对位置）\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素移动到指定位置（绝对位置）\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素移动**\n\n| 参数      | 描述                | 类型             | 默认值 | 必选 |\n| --------- | ------------------- | ---------------- | ------ | ---- |\n| id        | 要移动的元素 ID     | string           | -      | ✓    |\n| position  | 目标绝对位置 [x, y] | [number, number] | -      | ✓    |\n| animation | 是否启用动画        | boolean          | -      |      |\n\n**批量元素移动**\n\n| 参数      | 描述                   | 类型                             | 默认值 | 必选 |\n| --------- | ---------------------- | -------------------------------- | ------ | ---- |\n| positions | 元素ID到目标位置的映射 | Record<string, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                          | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，移动操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 将节点移动到画布的 (200, 300) 位置\nawait graph.translateElementTo('node1', [200, 300]);\n\n// 带动画移动\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// 将一组节点整齐排列\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\n聚焦到指定元素，使元素居中于视口。\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述                      | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| id        | 要聚焦的一个或多个元素 ID | string \\| string[]                                              | -      | ✓    |\n| animation | 视口动画配置              | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，聚焦操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 聚焦到单个节点\nawait graph.focusElement('node1');\n\n// 使用自定义动画配置\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// 聚焦到多个节点\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## 类型定义\n\n### CollapseExpandNodeOptions\n\n收起或展开元素的配置选项。\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * 是否使用动画\n   */\n  animation?: boolean;\n  /**\n   * 保证展开/收起的节点位置不变\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) 是\"轴对齐包围盒\"的缩写，是计算机图形学中的一个基础概念。\n\n```typescript\ninterface AABB {\n  x: number; // 矩形左上角的 x 坐标\n  y: number; // 矩形左上角的 y 坐标\n  width: number; // 矩形宽度\n  height: number; // 矩形高度\n}\n```\n\n### State\n\n元素状态类型。\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n","frontmatter":{"title":"元素操作","order":"1"},"isInternal":false,"tokens":3832,"sizeBytes":19328},{"name":"event.en.md","path":"packages/site/docs/api/event.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/event.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Event Listening\norder: 11\n---\n\n## Overview of the Event System\n\nG6 provides a powerful event mechanism that allows you to respond to various interactive behaviors occurring in the chart, such as node clicks, edge hovers, canvas drags, etc. Through the event system, you can implement complex interactive logic to enhance user experience.\n\n### Event Categories\n\nEvents in G6 can be broadly categorized into the following types:\n\n1. **Element Events**: Events related to nodes, edges, and Combos, such as `node:click`, `edge:mouseenter`\n2. **Canvas Events**: Events related to the entire canvas, such as `canvas:drag`, `canvas:wheel`\n3. **Lifecycle Events**: Events related to the chart lifecycle, such as `beforerender`, `afterrender`\n\n### Event Naming Convention\n\nG6 events follow the `[object]:[event]` format, for example:\n\n- `node:click` - Node click event\n- `edge:mouseenter` - Mouse enters edge event\n- `canvas:drag` - Canvas drag event\n\n## Best Practice: Using Constant Enums\n\nG6 provides a complete set of event constant enums, and it is **strongly recommended** to use these constants instead of directly using string event names:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// Use constant enums to listen to events\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**Advantages**:\n\n- Type safety, avoiding string spelling errors\n- Provides intelligent code hints and auto-completion\n\n## API Reference\n\n### Graph.on(eventName, callback, once)\n\nListen to a specified event and execute a callback function when the event is triggered.\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n| once      | Whether to listen only once                            | boolean            | -       |          |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Listen to node click event\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // Get the ID of the clicked node\n  console.log(`Node ${target.id} was clicked`);\n\n  // Get node data\n  const nodeData = graph.getNodeData(target.id);\n  console.log('Node data:', nodeData);\n\n  // Modify node state\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen to edge mouse enter event\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// Listen to canvas drag event\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('Canvas is being dragged');\n});\n```\n\n### Graph.once(eventName, callback)\n\nListen to an event once, and automatically remove the listener after the event is triggered once.\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// Listen to the chart's first load completion event, executed only once\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('Chart rendered for the first time');\n  // Execute one-time initialization operations\n  highlightImportantNodes();\n});\n\n// Wait for the user to click a node for the first time and then perform operations\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('User clicked a node for the first time:', evt.target.id);\n  showTutorialTip('You can drag nodes to change their position');\n});\n```\n\n### Graph.off()\n\nRemove all event listeners.\n\n```typescript\noff(): this;\n```\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\n// Remove all event listeners\ngraph.off();\nconsole.log('All event listeners have been removed');\n```\n\n### Graph.off(eventName)\n\nRemove all listeners of a specified event type.\n\n```typescript\noff(eventName: string): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type   | Default | Required |\n| --------- | --------------------------- | ------ | ------- | -------- |\n| eventName | Name of the event to remove | string | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Remove all node click event listeners\ngraph.off(NodeEvent.CLICK);\nconsole.log('All node click event listeners have been removed');\n\n// Remove related temporary event listeners after a certain operation mode ends\nfunction exitEditMode() {\n  // Remove all listeners in edit mode\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('Exited edit mode');\n}\n```\n\n### Graph.off(eventName, callback)\n\nRemove a specific callback function for a specific event.\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type                     | Default | Required |\n| --------- | --------------------------- | ------------------------ | ------- | -------- |\n| eventName | Name of the event to remove | string                   | -       | ✓        |\n| callback  | Callback function to remove | (...args: any[]) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Define callback function\nconst handleNodeClick = (evt) => {\n  console.log('Node clicked:', evt.target.id);\n};\n\n// Add listener\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// Later, remove this specific listener at a certain point\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('Specific node click event listener has been removed');\n```\n\n## Event Constant Enums\n\nG6 provides various event constant enums to facilitate developers in using standardized event names. Below is a detailed description of all event constants:\n\n### Node Events (NodeEvent)\n\n| Constant Name | Event Name          | Description                                                                   |\n| ------------- | ------------------- | ----------------------------------------------------------------------------- |\n| CLICK         | `node:click`        | Triggered when a node is clicked                                              |\n| DBLCLICK      | `node:dblclick`     | Triggered when a node is double-clicked                                       |\n| POINTER_OVER  | `node:pointerover`  | Triggered when the pointer enters a node                                      |\n| POINTER_LEAVE | `node:pointerleave` | Triggered when the pointer leaves a node                                      |\n| POINTER_ENTER | `node:pointerenter` | Triggered when the pointer enters a node or its child elements (non-bubbling) |\n| POINTER_MOVE  | `node:pointermove`  | Triggered when the pointer moves over a node                                  |\n| POINTER_OUT   | `node:pointerout`   | Triggered when the pointer leaves a node                                      |\n| POINTER_DOWN  | `node:pointerdown`  | Triggered when the pointer is pressed down on a node                          |\n| POINTER_UP    | `node:pointerup`    | Triggered when the pointer is released on a node                              |\n| CONTEXT_MENU  | `node:contextmenu`  | Triggered when the context menu is opened on a node                           |\n| DRAG_START    | `node:dragstart`    | Triggered when dragging a node starts                                         |\n| DRAG          | `node:drag`         | Triggered during node dragging                                                |\n| DRAG_END      | `node:dragend`      | Triggered when node dragging ends                                             |\n| DRAG_ENTER    | `node:dragenter`    | Triggered when a draggable item enters a node                                 |\n| DRAG_OVER     | `node:dragover`     | Triggered when a draggable item is over a node                                |\n| DRAG_LEAVE    | `node:dragleave`    | Triggered when a draggable item leaves a node                                 |\n| DROP          | `node:drop`         | Triggered when a draggable item is dropped on a node                          |\n\n### Edge Events (EdgeEvent)\n\n| Constant Name | Event Name          | Description                                                                    |\n| ------------- | ------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `edge:click`        | Triggered when an edge is clicked                                              |\n| DBLCLICK      | `edge:dblclick`     | Triggered when an edge is double-clicked                                       |\n| POINTER_OVER  | `edge:pointerover`  | Triggered when the pointer enters an edge                                      |\n| POINTER_LEAVE | `edge:pointerleave` | Triggered when the pointer leaves an edge                                      |\n| POINTER_ENTER | `edge:pointerenter` | Triggered when the pointer enters an edge or its child elements (non-bubbling) |\n| POINTER_MOVE  | `edge:pointermove`  | Triggered when the pointer moves over an edge                                  |\n| POINTER_OUT   | `edge:pointerout`   | Triggered when the pointer leaves an edge                                      |\n| POINTER_DOWN  | `edge:pointerdown`  | Triggered when the pointer is pressed down on an edge                          |\n| POINTER_UP    | `edge:pointerup`    | Triggered when the pointer is released on an edge                              |\n| CONTEXT_MENU  | `edge:contextmenu`  | Triggered when the context menu is opened on an edge                           |\n| DRAG_ENTER    | `edge:dragenter`    | Triggered when a draggable item enters an edge                                 |\n| DRAG_OVER     | `edge:dragover`     | Triggered when a draggable item is over an edge                                |\n| DRAG_LEAVE    | `edge:dragleave`    | Triggered when a draggable item leaves an edge                                 |\n| DROP          | `edge:drop`         | Triggered when a draggable item is dropped on an edge                          |\n\n### Combo Events (ComboEvent)\n\n| Constant Name | Event Name           | Description                                                                    |\n| ------------- | -------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `combo:click`        | Triggered when a Combo is clicked                                              |\n| DBLCLICK      | `combo:dblclick`     | Triggered when a Combo is double-clicked                                       |\n| POINTER_OVER  | `combo:pointerover`  | Triggered when the pointer enters a Combo                                      |\n| POINTER_LEAVE | `combo:pointerleave` | Triggered when the pointer leaves a Combo                                      |\n| POINTER_ENTER | `combo:pointerenter` | Triggered when the pointer enters a Combo or its child elements (non-bubbling) |\n| POINTER_MOVE  | `combo:pointermove`  | Triggered when the pointer moves over a Combo                                  |\n| POINTER_OUT   | `combo:pointerout`   | Triggered when the pointer leaves a Combo                                      |\n| POINTER_DOWN  | `combo:pointerdown`  | Triggered when the pointer is pressed down on a Combo                          |\n| POINTER_UP    | `combo:pointerup`    | Triggered when the pointer is released on a Combo                              |\n| CONTEXT_MENU  | `combo:contextmenu`  | Triggered when the context menu is opened on a Combo                           |\n| DRAG_START    | `combo:dragstart`    | Triggered when dragging a Combo starts                                         |\n| DRAG          | `combo:drag`         | Triggered during Combo dragging                                                |\n| DRAG_END      | `combo:dragend`      | Triggered when Combo dragging ends                                             |\n| DRAG_ENTER    | `combo:dragenter`    | Triggered when a draggable item enters a Combo                                 |\n| DRAG_OVER     | `combo:dragover`     | Triggered when a draggable item is over a Combo                                |\n| DRAG_LEAVE    | `combo:dragleave`    | Triggered when a draggable item leaves a Combo                                 |\n| DROP          | `combo:drop`         | Triggered when a draggable item is dropped on a Combo                          |\n\n### Canvas Events (CanvasEvent)\n\n| Constant Name | Event Name            | Description                                                                       |\n| ------------- | --------------------- | --------------------------------------------------------------------------------- |\n| CLICK         | `canvas:click`        | Triggered when clicking on the canvas blank area                                  |\n| DBLCLICK      | `canvas:dblclick`     | Triggered when double-clicking on the canvas blank area                           |\n| POINTER_OVER  | `canvas:pointerover`  | Triggered when the pointer enters the canvas                                      |\n| POINTER_LEAVE | `canvas:pointerleave` | Triggered when the pointer leaves the canvas                                      |\n| POINTER_ENTER | `canvas:pointerenter` | Triggered when the pointer enters the canvas or its child elements (non-bubbling) |\n| POINTER_MOVE  | `canvas:pointermove`  | Triggered when the pointer moves over the canvas                                  |\n| POINTER_OUT   | `canvas:pointerout`   | Triggered when the pointer leaves the canvas                                      |\n| POINTER_DOWN  | `canvas:pointerdown`  | Triggered when the pointer is pressed down on the canvas                          |\n| POINTER_UP    | `canvas:pointerup`    | Triggered when the pointer is released on the canvas                              |\n| CONTEXT_MENU  | `canvas:contextmenu`  | Triggered when the context menu is opened on the canvas                           |\n| DRAG_START    | `canvas:dragstart`    | Triggered when dragging the canvas starts                                         |\n| DRAG          | `canvas:drag`         | Triggered during canvas dragging                                                  |\n| DRAG_END      | `canvas:dragend`      | Triggered when canvas dragging ends                                               |\n| DRAG_ENTER    | `canvas:dragenter`    | Triggered when a draggable item enters the canvas                                 |\n| DRAG_OVER     | `canvas:dragover`     | Triggered when a draggable item is over the canvas                                |\n| DRAG_LEAVE    | `canvas:dragleave`    | Triggered when a draggable item leaves the canvas                                 |\n| DROP          | `canvas:drop`         | Triggered when a draggable item is dropped on the canvas                          |\n| WHEEL         | `canvas:wheel`        | Triggered when scrolling the mouse wheel on the canvas                            |\n\n### Graph Lifecycle Events (GraphEvent)\n\n| Constant Name            | Event Name               | Description                                    |\n| ------------------------ | ------------------------ | ---------------------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | Triggered before canvas initialization         |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | Triggered after canvas initialization          |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | Triggered before viewport size change          |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | Triggered after viewport size change           |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | Triggered before element creation              |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | Triggered after element creation               |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | Triggered before element update                |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | Triggered after element update                 |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | Triggered before element destruction           |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | Triggered after element destruction            |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | Triggered before element translation           |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | Triggered after element translation            |\n| BEFORE_DRAW              | `beforedraw`             | Triggered before drawing starts                |\n| AFTER_DRAW               | `afterdraw`              | Triggered after drawing ends                   |\n| BEFORE_RENDER            | `beforerender`           | Triggered before rendering starts              |\n| AFTER_RENDER             | `afterrender`            | Triggered after rendering completes            |\n| BEFORE_ANIMATE           | `beforeanimate`          | Triggered before animation starts              |\n| AFTER_ANIMATE            | `afteranimate`           | Triggered after animation ends                 |\n| BEFORE_LAYOUT            | `beforelayout`           | Triggered before layout starts                 |\n| AFTER_LAYOUT             | `afterlayout`            | Triggered after layout ends                    |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | Triggered before each stage in pipeline layout |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | Triggered after each stage in pipeline layout  |\n| BEFORE_TRANSFORM         | `beforetransform`        | Triggered before viewport transformation       |\n| AFTER_TRANSFORM          | `aftertransform`         | Triggered after viewport transformation        |\n| BATCH_START              | `batchstart`             | Triggered when batch operation starts          |\n| BATCH_END                | `batchend`               | Triggered when batch operation ends            |\n| BEFORE_DESTROY           | `beforedestroy`          | Triggered before chart destruction             |\n| AFTER_DESTROY            | `afterdestroy`           | Triggered after chart destruction              |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | Triggered before renderer change               |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | Triggered after renderer change                |\n\n### Container Events (ContainerEvent)\n\n| Constant Name | Event Name | Description                                   |\n| ------------- | ---------- | --------------------------------------------- |\n| KEY_DOWN      | `keydown`  | Triggered when a keyboard key is pressed down |\n| KEY_UP        | `keyup`    | Triggered when a keyboard key is released     |\n\n### Common Events (CommonEvent)\n\nThese are events without prefixes and can be used to listen to global events:\n\n| Constant Name | Event Name     | Description                                                                        |\n| ------------- | -------------- | ---------------------------------------------------------------------------------- |\n| CLICK         | `click`        | Triggered when any element is clicked                                              |\n| DBLCLICK      | `dblclick`     | Triggered when any element is double-clicked                                       |\n| POINTER_OVER  | `pointerover`  | Triggered when the pointer enters any element                                      |\n| POINTER_LEAVE | `pointerleave` | Triggered when the pointer leaves any element                                      |\n| POINTER_ENTER | `pointerenter` | Triggered when the pointer enters any element or its child elements (non-bubbling) |\n| POINTER_MOVE  | `pointermove`  | Triggered when the pointer moves over any element                                  |\n| POINTER_OUT   | `pointerout`   | Triggered when the pointer leaves any element                                      |\n| POINTER_DOWN  | `pointerdown`  | Triggered when the pointer is pressed down on any element                          |\n| POINTER_UP    | `pointerup`    | Triggered when the pointer is released on any element                              |\n| CONTEXT_MENU  | `contextmenu`  | Triggered when the context menu is opened on any element                           |\n| DRAG_START    | `dragstart`    | Triggered when dragging any element starts                                         |\n| DRAG          | `drag`         | Triggered during any element dragging                                              |\n| DRAG_END      | `dragend`      | Triggered when any element dragging ends                                           |\n| DRAG_ENTER    | `dragenter`    | Triggered when a draggable item enters any element                                 |\n| DRAG_OVER     | `dragover`     | Triggered when a draggable item is over any element                                |\n| DRAG_LEAVE    | `dragleave`    | Triggered when a draggable item leaves any element                                 |\n| DROP          | `drop`         | Triggered when a draggable item is dropped on any element                          |\n| KEY_DOWN      | `keydown`      | Triggered when a keyboard key is pressed down                                      |\n| KEY_UP        | `keyup`        | Triggered when a keyboard key is released                                          |\n| WHEEL         | `wheel`        | Triggered when scrolling the mouse wheel                                           |\n| PINCH         | `pinch`        | Triggered when pinching or spreading fingers on a multi-touch screen               |\n\n## Tips for Use\n\n### Chain Calls\n\nG6's event API supports chain calls, allowing you to register multiple events consecutively:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Use constant enums + chain calls\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### Event Delegation\n\nYou can use the event bubbling mechanism to listen to all child element events on the parent element:\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// Handle all element click events uniformly\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('Clicked on node:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('Clicked on edge:', target.id);\n  } else {\n    console.log('Clicked on canvas blank area');\n  }\n});\n```\n\n### Event Object Properties\n\nMost event callback functions receive an event object containing the following common properties:\n\n- `target` - The element that triggered the event\n- `targetType` - The type of the element that triggered the event (node/edge/combo/canvas)\n- `originalTarget` - The original graphic that triggered the event\n- `currentTarget` - The current object that triggered the event\n- `originalEvent` - The original browser event object\n\nWith these properties, you can precisely control interactive behavior.\n","frontmatter":{"title":"Event Listening","order":"11"},"isInternal":false,"tokens":6148,"sizeBytes":24603},{"name":"event.zh.md","path":"packages/site/docs/api/event.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/event.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 事件监听\norder: 11\n---\n\n## 事件系统概述\n\nG6 提供了强大的事件机制，允许你响应图表中发生的各种交互行为。例如节点点击、边悬停、画布拖拽等。通过事件系统，你可以实现复杂的交互逻辑，提升用户体验。\n\n### 事件分类\n\nG6 中的事件大致可分为以下几类：\n\n1. **元素事件**：与节点、边、Combo 相关的事件，如 `node:click`, `edge:mouseenter`\n2. **画布事件**：与整个画布相关的事件，如 `canvas:drag`, `canvas:wheel`\n3. **生命周期事件**：与图表生命周期相关的事件，如 `beforerender`, `afterrender`\n\n### 事件命名规则\n\nG6 的事件命名遵循 `[对象]:[事件]` 的格式，例如：\n\n- `node:click` - 节点点击事件\n- `edge:mouseenter` - 鼠标进入边的事件\n- `canvas:drag` - 画布拖拽事件\n\n## 最佳实践：使用常量枚举\n\nG6 提供了完整的事件常量枚举，**强烈建议**使用这些常量而非直接使用字符串事件名：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// 使用常量枚举监听事件\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**优势**：\n\n- 类型安全，避免字符串拼写错误\n- 提供智能代码提示和自动完成\n\n## API 参考\n\n### Graph.on(eventName, callback, once)\n\n监听指定的事件，当事件触发时执行回调函数。\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n| once      | 是否只监听一次           | boolean            | -      |      |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 监听节点点击事件\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // 获取被点击节点的 ID\n  console.log(`节点 ${target.id} 被点击了`);\n\n  // 获取节点数据\n  const nodeData = graph.getNodeData(target.id);\n  console.log('节点数据:', nodeData);\n\n  // 修改节点状态\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边的鼠标进入事件\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// 监听画布拖拽事件\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('画布正在被拖拽');\n});\n```\n\n### Graph.once(eventName, callback)\n\n一次性监听事件，事件触发一次后自动移除监听器。\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// 监听图表首次加载完成事件，仅执行一次\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('图表首次渲染完成');\n  // 执行一次性的初始化操作\n  highlightImportantNodes();\n});\n\n// 等待用户第一次点击某个节点后执行操作\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('用户首次点击了节点:', evt.target.id);\n  showTutorialTip('您可以拖拽节点改变位置');\n});\n```\n\n### Graph.off()\n\n移除全部事件监听器。\n\n```typescript\noff(): this;\n```\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\n// 移除所有事件监听器\ngraph.off();\nconsole.log('已移除所有事件监听器');\n```\n\n### Graph.off(eventName)\n\n移除指定事件类型的所有监听器。\n\n```typescript\noff(eventName: string): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型   | 默认值 | 必选 |\n| --------- | ---------------- | ------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 移除所有节点点击事件的监听器\ngraph.off(NodeEvent.CLICK);\nconsole.log('已移除所有节点点击事件监听器');\n\n// 在某个操作模式结束后，移除相关的临时事件监听\nfunction exitEditMode() {\n  // 移除编辑模式下的所有监听器\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('已退出编辑模式');\n}\n```\n\n### Graph.off(eventName, callback)\n\n移除特定事件的特定回调函数。\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型                     | 默认值 | 必选 |\n| --------- | ---------------- | ------------------------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string                   | -      | ✓    |\n| callback  | 要移除的回调函数 | (...args: any[]) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 定义回调函数\nconst handleNodeClick = (evt) => {\n  console.log('节点被点击:', evt.target.id);\n};\n\n// 添加监听器\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// 之后在某个时机移除这个特定的监听器\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('已移除特定的节点点击事件监听器');\n```\n\n## 事件常量枚举\n\nG6 提供了多种事件常量枚举，便于开发者使用规范的事件名称。以下是所有事件常量的详细说明：\n\n### 节点事件 (NodeEvent)\n\n| 常量名        | 事件名              | 描述                                 |\n| ------------- | ------------------- | ------------------------------------ |\n| CLICK         | `node:click`        | 点击节点时触发                       |\n| DBLCLICK      | `node:dblclick`     | 双击节点时触发                       |\n| POINTER_OVER  | `node:pointerover`  | 指针移入节点时触发                   |\n| POINTER_LEAVE | `node:pointerleave` | 指针离开节点时触发                   |\n| POINTER_ENTER | `node:pointerenter` | 指针进入节点或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `node:pointermove`  | 指针在节点上移动时触发               |\n| POINTER_OUT   | `node:pointerout`   | 指针离开节点时触发                   |\n| POINTER_DOWN  | `node:pointerdown`  | 指针在节点上按下时触发               |\n| POINTER_UP    | `node:pointerup`    | 指针在节点上抬起时触发               |\n| CONTEXT_MENU  | `node:contextmenu`  | 节点上打开上下文菜单时触发           |\n| DRAG_START    | `node:dragstart`    | 开始拖拽节点时触发                   |\n| DRAG          | `node:drag`         | 拖拽节点过程中触发                   |\n| DRAG_END      | `node:dragend`      | 拖拽节点结束时触发                   |\n| DRAG_ENTER    | `node:dragenter`    | 拖拽物进入节点时触发                 |\n| DRAG_OVER     | `node:dragover`     | 拖拽物在节点上方时触发               |\n| DRAG_LEAVE    | `node:dragleave`    | 拖拽物离开节点时触发                 |\n| DROP          | `node:drop`         | 在节点上放置拖拽物时触发             |\n\n### 边事件 (EdgeEvent)\n\n| 常量名        | 事件名              | 描述                               |\n| ------------- | ------------------- | ---------------------------------- |\n| CLICK         | `edge:click`        | 点击边时触发                       |\n| DBLCLICK      | `edge:dblclick`     | 双击边时触发                       |\n| POINTER_OVER  | `edge:pointerover`  | 指针移入边时触发                   |\n| POINTER_LEAVE | `edge:pointerleave` | 指针离开边时触发                   |\n| POINTER_ENTER | `edge:pointerenter` | 指针进入边或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `edge:pointermove`  | 指针在边上移动时触发               |\n| POINTER_OUT   | `edge:pointerout`   | 指针离开边时触发                   |\n| POINTER_DOWN  | `edge:pointerdown`  | 指针在边上按下时触发               |\n| POINTER_UP    | `edge:pointerup`    | 指针在边上抬起时触发               |\n| CONTEXT_MENU  | `edge:contextmenu`  | 边上打开上下文菜单时触发           |\n| DRAG_ENTER    | `edge:dragenter`    | 拖拽物进入边时触发                 |\n| DRAG_OVER     | `edge:dragover`     | 拖拽物在边上方时触发               |\n| DRAG_LEAVE    | `edge:dragleave`    | 拖拽物离开边时触发                 |\n| DROP          | `edge:drop`         | 在边上放置拖拽物时触发             |\n\n### Combo事件 (ComboEvent)\n\n| 常量名        | 事件名               | 描述                                  |\n| ------------- | -------------------- | ------------------------------------- |\n| CLICK         | `combo:click`        | 点击Combo时触发                       |\n| DBLCLICK      | `combo:dblclick`     | 双击Combo时触发                       |\n| POINTER_OVER  | `combo:pointerover`  | 指针移入Combo时触发                   |\n| POINTER_LEAVE | `combo:pointerleave` | 指针离开Combo时触发                   |\n| POINTER_ENTER | `combo:pointerenter` | 指针进入Combo或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `combo:pointermove`  | 指针在Combo上移动时触发               |\n| POINTER_OUT   | `combo:pointerout`   | 指针离开Combo时触发                   |\n| POINTER_DOWN  | `combo:pointerdown`  | 指针在Combo上按下时触发               |\n| POINTER_UP    | `combo:pointerup`    | 指针在Combo上抬起时触发               |\n| CONTEXT_MENU  | `combo:contextmenu`  | Combo上打开上下文菜单时触发           |\n| DRAG_START    | `combo:dragstart`    | 开始拖拽Combo时触发                   |\n| DRAG          | `combo:drag`         | 拖拽Combo过程中触发                   |\n| DRAG_END      | `combo:dragend`      | 拖拽Combo结束时触发                   |\n| DRAG_ENTER    | `combo:dragenter`    | 拖拽物进入Combo时触发                 |\n| DRAG_OVER     | `combo:dragover`     | 拖拽物在Combo上方时触发               |\n| DRAG_LEAVE    | `combo:dragleave`    | 拖拽物离开Combo时触发                 |\n| DROP          | `combo:drop`         | 在Combo上放置拖拽物时触发             |\n\n### 画布事件 (CanvasEvent)\n\n| 常量名        | 事件名                | 描述                                 |\n| ------------- | --------------------- | ------------------------------------ |\n| CLICK         | `canvas:click`        | 点击画布空白处时触发                 |\n| DBLCLICK      | `canvas:dblclick`     | 双击画布空白处时触发                 |\n| POINTER_OVER  | `canvas:pointerover`  | 指针移入画布时触发                   |\n| POINTER_LEAVE | `canvas:pointerleave` | 指针离开画布时触发                   |\n| POINTER_ENTER | `canvas:pointerenter` | 指针进入画布或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `canvas:pointermove`  | 指针在画布上移动时触发               |\n| POINTER_OUT   | `canvas:pointerout`   | 指针离开画布时触发                   |\n| POINTER_DOWN  | `canvas:pointerdown`  | 指针在画布上按下时触发               |\n| POINTER_UP    | `canvas:pointerup`    | 指针在画布上抬起时触发               |\n| CONTEXT_MENU  | `canvas:contextmenu`  | 画布上打开上下文菜单时触发           |\n| DRAG_START    | `canvas:dragstart`    | 开始拖拽画布时触发                   |\n| DRAG          | `canvas:drag`         | 拖拽画布过程中触发                   |\n| DRAG_END      | `canvas:dragend`      | 拖拽画布结束时触发                   |\n| DRAG_ENTER    | `canvas:dragenter`    | 拖拽物进入画布时触发                 |\n| DRAG_OVER     | `canvas:dragover`     | 拖拽物在画布上方时触发               |\n| DRAG_LEAVE    | `canvas:dragleave`    | 拖拽物离开画布时触发                 |\n| DROP          | `canvas:drop`         | 在画布上放置拖拽物时触发             |\n| WHEEL         | `canvas:wheel`        | 在画布上滚动鼠标滚轮时触发           |\n\n### 图表生命周期事件 (GraphEvent)\n\n| 常量名                   | 事件名                   | 描述                               |\n| ------------------------ | ------------------------ | ---------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | 画布初始化之前触发                 |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | 画布初始化之后触发                 |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | 视口尺寸变更之前触发               |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | 视口尺寸变更之后触发               |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | 元素创建之前触发                   |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | 元素创建之后触发                   |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | 元素更新之前触发                   |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | 元素更新之后触发                   |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | 元素销毁之前触发                   |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | 元素销毁之后触发                   |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | 元素平移之前触发                   |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | 元素平移之后触发                   |\n| BEFORE_DRAW              | `beforedraw`             | 绘制开始之前触发                   |\n| AFTER_DRAW               | `afterdraw`              | 绘制结束之后触发                   |\n| BEFORE_RENDER            | `beforerender`           | 渲染开始之前触发                   |\n| AFTER_RENDER             | `afterrender`            | 渲染完成之后触发                   |\n| BEFORE_ANIMATE           | `beforeanimate`          | 动画开始之前触发                   |\n| AFTER_ANIMATE            | `afteranimate`           | 动画结束之后触发                   |\n| BEFORE_LAYOUT            | `beforelayout`           | 布局开始之前触发                   |\n| AFTER_LAYOUT             | `afterlayout`            | 布局结束之后触发                   |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | 流水线布局过程中每个阶段开始前触发 |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | 流水线布局过程中每个阶段结束后触发 |\n| BEFORE_TRANSFORM         | `beforetransform`        | 可视区域变化之前触发               |\n| AFTER_TRANSFORM          | `aftertransform`         | 可视区域变化之后触发               |\n| BATCH_START              | `batchstart`             | 批处理操作开始时触发               |\n| BATCH_END                | `batchend`               | 批处理操作结束时触发               |\n| BEFORE_DESTROY           | `beforedestroy`          | 图表销毁前触发                     |\n| AFTER_DESTROY            | `afterdestroy`           | 图表销毁后触发                     |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | 渲染器变更之前触发                 |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | 渲染器变更之后触发                 |\n\n### 容器事件 (ContainerEvent)\n\n| 常量名   | 事件名    | 描述               |\n| -------- | --------- | ------------------ |\n| KEY_DOWN | `keydown` | 键盘按键按下时触发 |\n| KEY_UP   | `keyup`   | 键盘按键抬起时触发 |\n\n### 通用事件 (CommonEvent)\n\n这些是不带前缀的事件，可用于监听全局事件：\n\n| 常量名        | 事件名         | 描述                                     |\n| ------------- | -------------- | ---------------------------------------- |\n| CLICK         | `click`        | 点击任何元素时触发                       |\n| DBLCLICK      | `dblclick`     | 双击任何元素时触发                       |\n| POINTER_OVER  | `pointerover`  | 指针移入任何元素时触发                   |\n| POINTER_LEAVE | `pointerleave` | 指针离开任何元素时触发                   |\n| POINTER_ENTER | `pointerenter` | 指针进入任何元素或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `pointermove`  | 指针在任何元素上移动时触发               |\n| POINTER_OUT   | `pointerout`   | 指针离开任何元素时触发                   |\n| POINTER_DOWN  | `pointerdown`  | 指针在任何元素上按下时触发               |\n| POINTER_UP    | `pointerup`    | 指针在任何元素上抬起时触发               |\n| CONTEXT_MENU  | `contextmenu`  | 任何元素上打开上下文菜单时触发           |\n| DRAG_START    | `dragstart`    | 开始拖拽任何元素时触发                   |\n| DRAG          | `drag`         | 拖拽任何元素过程中触发                   |\n| DRAG_END      | `dragend`      | 拖拽任何元素结束时触发                   |\n| DRAG_ENTER    | `dragenter`    | 拖拽物进入任何元素时触发                 |\n| DRAG_OVER     | `dragover`     | 拖拽物在任何元素上方时触发               |\n| DRAG_LEAVE    | `dragleave`    | 拖拽物离开任何元素时触发                 |\n| DROP          | `drop`         | 在任何元素上放置拖拽物时触发             |\n| KEY_DOWN      | `keydown`      | 键盘按键按下时触发                       |\n| KEY_UP        | `keyup`        | 键盘按键抬起时触发                       |\n| WHEEL         | `wheel`        | 滚动鼠标滚轮时触发                       |\n| PINCH         | `pinch`        | 多点触控屏幕上双指捏合或张开时触发       |\n\n## 使用技巧\n\n### 链式调用\n\nG6 的事件 API 支持链式调用，可以连续注册多个事件：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 使用常量枚举+链式调用\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### 事件代理\n\n你可以利用事件冒泡机制，在父元素上监听所有子元素的事件：\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// 统一处理所有元素的点击事件\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('点击了节点:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('点击了边:', target.id);\n  } else {\n    console.log('点击了画布空白处');\n  }\n});\n```\n\n### 事件对象属性\n\n大多数事件的回调函数会接收一个事件对象，包含以下常用属性：\n\n- `target` - 触发事件的元素\n- `targetType` - 触发事件的元素类型（node/edge/combo/canvas）\n- `originalTarget` - 原始的触发事件的图形\n- `currentTarget` - 当前触发事件的对象\n- `originalEvent` - 原始的浏览器事件对象\n\n通过这些属性，你可以精确地控制交互行为。\n","frontmatter":{"title":"事件监听","order":"11"},"isInternal":false,"tokens":3835,"sizeBytes":20261},{"name":"export-image.en.md","path":"packages/site/docs/api/export-image.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/export-image.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Export Image\norder: 12\n---\n\n## Overview of Image Export\n\nG6 provides the functionality to export the graph as an image, allowing you to export the current canvas content as a DataURL format. This is convenient for saving, sharing, or further processing. The exported image will retain all visible elements on the canvas, including nodes, edges, combos, and other custom graphics.\n\n## API Reference\n\n### Graph.toDataURL(options)\n\nExport the current canvas as an image in DataURL format.\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**Parameters**\n\n| Parameter | Description                | Type                      | Default | Required |\n| --------- | -------------------------- | ------------------------- | ------- | -------- |\n| options   | Export image configuration | Partial\\<DataURLOptions\\> | -       |          |\n\n**Return Value**\n\nReturns a Promise that resolves to a DataURL string representing the image.\n\n**DataURLOptions Type Definition**\n\n| Parameter      | Type                                        | Required | Description                                                                                              |\n| -------------- | ------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |\n| mode           | 'viewport' \\| 'overall'                     | No       | Export mode <br/> - viewport: Export viewport content <br/> - overall: Export entire canvas              |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | No       | Image type <br/> - image/png: PNG format <br/> - image/jpeg: JPEG format <br/> - image/webp: WebP format |\n| encoderOptions | number                                      | No       | Image quality, only effective for image/jpeg and image/webp, range 0 ~ 1                                 |\n\n## Download Image\n\nG6 5.0 only provides an API to export the canvas as a Base64 image ([toDataURL](#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=Note}\nThe exported image content may not include the complete canvas content. The export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., which will not appear in the exported image.\n:::\n","frontmatter":{"title":"Export Image","order":"12"},"isInternal":false,"tokens":737,"sizeBytes":2947},{"name":"export-image.zh.md","path":"packages/site/docs/api/export-image.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/export-image.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 导出图片\norder: 12\n---\n\n## 图片导出概述\n\nG6 提供了将图导出为图片的功能，可以将当前画布内容导出为 DataURL 格式，方便保存、分享或进一步处理。导出的图片会保留画布上的所有可见元素，包括节点、边、组合以及其他自定义图形。\n\n## API 参考\n\n### Graph.toDataURL(options)\n\n将当前画布导出为 DataURL 格式的图片。\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**参数**\n\n| 参数    | 描述         | 类型                      | 默认值 | 必选 |\n| ------- | ------------ | ------------------------- | ------ | ---- |\n| options | 导出图片配置 | Partial\\<DataURLOptions\\> | -      |      |\n\n**返回值**\n\n返回一个 Promise，解析为表示图片的 DataURL 字符串。\n\n**DataURLOptions 类型定义**\n\n| 参数           | 类型                                        | 必选 | 描述                                                                                             |\n| -------------- | ------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------ |\n| mode           | 'viewport' \\| 'overall'                     | 否   | 导出模式 <br/> - viewport: 导出视口内容 <br/> - overall: 导出整个画布                            |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | 否   | 图片类型 <br/> - image/png: PNG 格式 <br/> - image/jpeg: JPEG 格式 <br/> - image/webp: WebP 格式 |\n| encoderOptions | number                                      | 否   | 图片质量，仅对 image/jpeg 和 image/webp 有效，取值范围 0 ~ 1                                     |\n\n## 下载图片\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","frontmatter":{"title":"导出图片","order":"12"},"isInternal":false,"tokens":533,"sizeBytes":2748},{"name":"graph.en.md","path":"packages/site/docs/api/graph.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/graph.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Graph Instance\norder: 2\n---\n\n## API Reference\n\n### Graph.destroy()\n\nDestroy the current graph instance and release all resources related to it.\n\n⚠️ **Note**: After destruction, no operations can be performed. If you need to use it again, you must create a new graph instance.\n\n```typescript\ndestroy(): void;\n```\n\n**Usage Scenarios**:\n\n- When the user closes the chart or switches to another view, this method can be called to release resources.\n- When needing to recreate a graph instance, ensure the old instance is destroyed first to avoid memory leaks.\n","frontmatter":{"title":"Graph Instance","order":"2"},"isInternal":false,"tokens":142,"sizeBytes":571},{"name":"graph.zh.md","path":"packages/site/docs/api/graph.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/graph.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 图实例\norder: 2\n---\n\n## API 参考\n\n### Graph.destroy()\n\n销毁当前图实例，释放与图实例相关的所有资源。\n\n⚠️ **注意**: 销毁后无法进行任何操作，如果需要重新使用，需要重新创建一个新的图实例。\n\n```typescript\ndestroy(): void;\n```\n\n**使用场景**:\n\n- 当用户关闭图表或切换到其他视图时，可以调用此方法来释放资源。\n- 在需要重新创建图实例时，确保先销毁旧的实例，以避免内存泄漏。\n","frontmatter":{"title":"图实例","order":"2"},"isInternal":false,"tokens":62,"sizeBytes":506},{"name":"layout.en.md","path":"packages/site/docs/api/layout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/layout.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Layout\norder: 6\n---\n\n## Overview of Layout\n\n[Layout](/en/manual/layout/overview) is a crucial part of graph visualization, determining the positioning of nodes on the canvas. G6 offers a variety of layout algorithms to meet different data structures and visualization needs. Through the layout API, you can:\n\n- Set and update the graph's layout configuration\n- Execute or stop layout calculations\n- Combine multiple layout strategies\n- Customize layout algorithms\n\nA suitable layout can clearly display the relationship patterns between nodes, enhancing the graph's readability and aesthetics.\n\n## API Reference\n\n### Graph.setLayout(layout)\n\nSet the graph's layout algorithm and configuration.\n\n⚠️ **Note**: Calling this function won't automatically re-layout, so there's need to call `graph.layout()` separately.\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                        | Type                                                                        | Default | Required |\n| --------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layout    | Layout configuration object, or a function returning a new configuration based on the previous one | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       | ✓        |\n\n**Example 1**: Set a force-directed layout\n\n```typescript\n// Set a simple force-directed layout\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // Prevent node overlap\n  nodeStrength: -50, // Repulsion between nodes, negative value for repulsion\n  edgeStrength: 0.5, // Edge strength, affects edge length\n});\n```\n\n**Example 2**: Update layout using a function\n\n```typescript\n// Update based on the current layout configuration\ngraph.setLayout((prevLayout) => {\n  // If the previous layout was force-directed, adjust its parameters\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // Increase repulsion\n      alphaDecay: 0.01, // Lower decay rate for more iteration time\n    };\n  }\n\n  // Otherwise, switch to radial layout\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**Example 3**: Set a combined layout\n\n```typescript\n// Set a combined layout - different nodes use different layout algorithms\ngraph.setLayout([\n  {\n    type: 'grid',\n    // Filter function: only nodes with type 'main' participate in the layout\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\nGet the current layout configuration.\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**Return Value**\n\n- **Type**: [LayoutOptions](#layoutoptions)\n- **Description**: The current layout configuration object\n\n**Example**\n\n```typescript\n// Get the current layout configuration\nconst currentLayout = graph.getLayout();\nconsole.log('Current layout type:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\nExecute layout calculations. When graph data changes, call this method to trigger the layout algorithm to recalculate node positions.\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter     | Description                 | Type                                                                        | Default | Required |\n| ------------- | --------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layoutOptions | Layout configuration object | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       |          |\n\nIf `layoutOptions` is provided, it takes precedence over the graph's current layout configuration.\n\n**Note**\n\nLayout calculation is an asynchronous process, especially for complex layout algorithms like force-directed layout. This method returns a Promise, which can be used to perform subsequent operations after the layout is complete.\n\n**Example 1**: Basic usage\n\n```typescript\n// Execute layout\nawait graph.layout();\nconsole.log('Layout calculation complete');\n```\n\n**Example 2**: Re-layout after adding data\n\n```typescript\n// Add new nodes and edges\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// Draw new nodes and edges\nawait graph.draw();\n\n// Recalculate layout\nawait graph.layout();\n```\n\n**Example 3**: Listen to layout events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before layout starts\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('Layout calculation starting...');\n});\n\n// After layout completes\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('Layout calculation complete');\n});\n\n// Execute layout\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\nStop an ongoing layout calculation. Mainly used to stop iterative layout algorithms like force-directed layout.\n\n```typescript\nstopLayout(): void;\n```\n\n**Note**\n\nApplicable to layouts with iterative animations, currently `force` belongs to this category. If the layout calculation takes too long, you can manually stop the iteration.\n\n**Example 1**: Basic usage\n\n```typescript\n// Stop layout after 5 seconds\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('Layout manually stopped');\n}, 5000);\n```\n\n**Example 2**: Stop layout with user interaction\n\n```typescript\n// Stop layout when the user clicks the canvas\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('User clicked canvas, layout stopped');\n});\n```\n\n## Type Definitions\n\n### LayoutOptions\n\nLayout configuration type, can be a single layout configuration or an array of layout configurations.\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\nSingle layout configuration, can be a built-in layout configuration or a custom base layout configuration.\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\nBasic configuration items common to all layout types.\n\n```typescript\ninterface BaseLayoutOptions {\n  // Layout type\n  type: string;\n\n  // Node filter function for participating in the layout\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // Whether to calculate the layout before initializing elements\n  preLayout?: boolean;\n\n  // Whether invisible nodes participate in the layout (effective when preLayout is true)\n  isLayoutInvisibleNodes?: boolean;\n\n  // Enable layout animation, for iterative layouts, animation transitions occur between iterations\n  animation?: boolean;\n\n  // Whether to run the layout in a WebWorker\n  enableWorker?: boolean;\n\n  // Number of iterations for iterative layouts\n  iterations?: number;\n\n  // Other specific layout configuration items\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nConfiguration for G6's built-in layout types, see [API - Built-in Layouts](/en/manual/layout/antv-dagre-layout) for details.\n","frontmatter":{"title":"Layout","order":"6"},"isInternal":false,"tokens":1852,"sizeBytes":7413},{"name":"layout.zh.md","path":"packages/site/docs/api/layout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/layout.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 布局\norder: 6\n---\n\n## 布局概述\n\n[布局](/manual/layout/overview) 是图可视化中至关重要的一环，它决定了节点在画布上的位置排布。G6 提供了多种布局算法，以满足不同数据结构和可视化需求。通过布局 API，你可以：\n\n- 设置和更新图的布局配置\n- 执行或停止布局计算\n- 组合多种布局策略\n- 自定义布局算法\n\n合适的布局可以清晰地展示节点间的关系模式，提高图的可读性和美观度。\n\n## API 参考\n\n### Graph.setLayout(layout)\n\n设置图的布局算法及配置。\n\n⚠️ **注意**: 调用此函数不会自动重新布局，需要单独调用 `graph.layout()`。\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**参数**\n\n| 参数   | 描述                                               | 类型                                                                        | 默认值 | 必选 |\n| ------ | -------------------------------------------------- | --------------------------------------------------------------------------- | ------ | ---- |\n| layout | 布局配置对象，或者一个基于之前配置返回新配置的函数 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      | ✓    |\n\n**示例 1**: 设置力导向布局\n\n```typescript\n// 设置简单的力导向布局\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // 防止节点重叠\n  nodeStrength: -50, // 节点间斥力，负值为斥力\n  edgeStrength: 0.5, // 边的强度，会影响边的长度\n});\n```\n\n**示例 2**: 使用函数式更新布局\n\n```typescript\n// 基于当前布局配置进行更新\ngraph.setLayout((prevLayout) => {\n  // 如果之前是力导向布局，调整其参数\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // 增加斥力\n      alphaDecay: 0.01, // 降低衰减率，让布局有更多迭代时间\n    };\n  }\n\n  // 否则切换到放射状布局\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**示例 3**: 设置组合布局\n\n```typescript\n// 设置组合布局 - 不同的节点使用不同的布局算法\ngraph.setLayout([\n  {\n    type: 'grid',\n    // 过滤函数：只有type为'main'的节点参与布局\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\n获取当前的布局配置。\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**返回值**\n\n- **类型**: [LayoutOptions](#layoutoptions)\n- **描述**: 当前的布局配置对象\n\n**示例**\n\n```typescript\n// 获取当前布局配置\nconst currentLayout = graph.getLayout();\nconsole.log('当前布局类型:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\n执行布局计算。当图数据发生变化后，调用此方法可触发布局算法重新计算节点位置。\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**参数**\n\n| 参数          | 描述         | 类型                                                                        | 默认值 | 必选 |\n| ------------- | ------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| layoutOptions | 布局配置对象 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      |      |\n\n如果传入 `layoutOptions`，则优先考虑传入的布局配置，否则使用图的当前布局配置进行布局。\n\n**说明**\n\n布局计算是一个异步过程，特别是对于复杂的布局算法（如力导向布局）。此方法返回一个 Promise，可以用于在布局完成后执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 执行布局\nawait graph.layout();\nconsole.log('布局计算完成');\n```\n\n**示例 2**: 添加数据后重新布局\n\n```typescript\n// 添加新节点和边\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// 绘制新节点和边\nawait graph.draw();\n\n// 重新计算布局\nawait graph.layout();\n```\n\n**示例 3**: 监听布局事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 布局开始前\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('布局计算开始...');\n});\n\n// 布局完成后\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('布局计算完成');\n});\n\n// 执行布局\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\n停止正在进行中的布局计算。主要用于停止迭代类型的布局算法，如力导向布局。\n\n```typescript\nstopLayout(): void;\n```\n\n**说明**\n\n适用于带有迭代动画的布局，目前有 `force` 属于此类布局。当布局计算时间过长时，可以手动停止迭代。\n\n**示例 1**: 基本使用\n\n```typescript\n// 5秒后停止布局\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('布局已手动停止');\n}, 5000);\n```\n\n**示例 2**: 结合用户交互停止布局\n\n```typescript\n// 当用户点击画布时停止布局\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('用户点击画布，布局已停止');\n});\n```\n\n## 类型定义\n\n### LayoutOptions\n\n布局配置类型，可以是单一布局配置或布局配置数组。\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\n单一布局配置，可以是内置布局配置或自定义基础布局配置。\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\n所有布局类型共有的基础配置项。\n\n```typescript\ninterface BaseLayoutOptions {\n  // 布局类型\n  type: string;\n\n  // 参与该布局的节点过滤函数\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // 是否在初始化元素前计算布局\n  preLayout?: boolean;\n\n  // 不可见节点是否参与布局（当 preLayout 为 true 时生效）\n  isLayoutInvisibleNodes?: boolean;\n\n  // 启用布局动画，对于迭代布局，会在两次迭代之间进行动画过渡\n  animation?: boolean;\n\n  // 是否在 WebWorker 中运行布局\n  enableWorker?: boolean;\n\n  // 迭代布局的迭代次数\n  iterations?: number;\n\n  // 其他特定布局的配置项\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nG6 内置的布局类型配置，具体请查看 [API - 内置布局](/manual/layout/antv-dagre-layout)。\n","frontmatter":{"title":"布局","order":"6"},"isInternal":false,"tokens":1168,"sizeBytes":6636},{"name":"option.en.md","path":"packages/site/docs/api/option.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/option.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Graph Options\norder: 7\n---\n\n## Overview of Graph Options\n\nThe [options](/en/manual/graph/option) of a G6 graph instance control various aspects of the graph, including canvas settings, viewport properties, data, layout, styles, interaction behaviors, plugins, and more. By configuring these options appropriately, you can flexibly customize the appearance and behavior of the graph.\n\nOptions can be specified when creating a graph instance or dynamically modified at runtime through the API. Some basic configurations (such as devicePixelRatio, container) require destroying and recreating the graph instance to take effect after modification.\n\n## API Reference\n\n### Graph.getOptions()\n\nRetrieve all configuration options of the current graph.\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**Return Value**\n\n- **Type**: [GraphOptions](/en/manual/graph/option)\n- **Description**: Complete configuration options of the current graph\n\n**Example**\n\n```typescript\n// Retrieve the current graph's options\nconst options = graph.getOptions();\nconsole.log('Current graph options:', options);\n\n// Retrieve specific options\nconsole.log('Current canvas width:', options.width);\nconsole.log('Current layout options:', options.layout);\n```\n\n### Graph.setOptions(options)\n\nUpdate the graph's configuration options.\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                    | Default | Required |\n| --------- | ------------------------- | --------------------------------------- | ------- | -------- |\n| options   | New configuration options | [GraphOptions](/en/manual/graph/option) | -       | ✓        |\n\n**Note**\n\n⚠️ **Attention**: To update basic properties like devicePixelRatio, container, etc., you need to destroy the current graph instance and recreate it. Most other configurations can be dynamically updated.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Update graph configuration\ngraph.setOptions({\n  width: 1000, // Update width\n  height: 800, // Update height\n  autoFit: 'view', // Enable auto-fit\n  animation: true, // Enable animation\n});\n```\n\n**Example 2**: Update Theme\n\n```typescript\n// Update graph theme configuration\ngraph.setOptions({\n  theme: {\n    type: 'dark', // Switch to dark theme\n    // Custom theme configuration\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**Example 3**: Update Layout Configuration\n\n```typescript\n// Update layout configuration\ngraph.setOptions({\n  layout: {\n    type: 'force', // Switch to force-directed layout\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**Example 4**: Update Default Node and Edge Configuration\n\n```typescript\n// Update default style configuration for nodes and edges\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n\n## Type Definitions\n\n### GraphOptions\n\n```typescript\ntype GraphOptions = {\n  // Whether to enable zooming\n  enableZoom?: boolean;\n\n  // Whether to enable dragging\n  enableDrag?: boolean;\n\n  // Default style for nodes\n  defaultNodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Additional configuration options for the graph\n  [configKey: string]: any;\n};\n```\n","frontmatter":{"title":"Graph Options","order":"7"},"isInternal":false,"tokens":883,"sizeBytes":3538},{"name":"option.zh.md","path":"packages/site/docs/api/option.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/option.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 图配置项\norder: 7\n---\n\n## 图配置项概述\n\nG6 图实例的 [配置项](/manual/graph/option) 控制着图的各个方面，包括画布设置、视口属性、数据、布局、样式、交互行为、插件等。通过合理配置这些选项，可以灵活定制图的外观和行为。\n\n配置项可以在图实例创建时指定，也可以通过 API 在运行时动态修改。某些基础配置（如 devicePixelRatio、container）修改后需要销毁并重新创建图实例才能生效。\n\n## API 参考\n\n### Graph.getOptions()\n\n获取当前图表的所有配置项。\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**返回值**\n\n- **类型**: [GraphOptions](/manual/graph/option)\n- **描述**: 当前图表的完整配置项\n\n**示例**\n\n```typescript\n// 获取当前图表的配置项\nconst options = graph.getOptions();\nconsole.log('当前图表配置:', options);\n\n// 获取特定配置\nconsole.log('当前画布宽度:', options.width);\nconsole.log('当前布局配置:', options.layout);\n```\n\n### Graph.setOptions(options)\n\n更新图表的配置项。\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**参数**\n\n| 参数    | 描述       | 类型                                 | 默认值 | 必选 |\n| ------- | ---------- | ------------------------------------ | ------ | ---- |\n| options | 新的配置项 | [GraphOptions](/manual/graph/option) | -      | ✓    |\n\n**说明**\n\n⚠️ **注意**: 要更新 devicePixelRatio、container 等基础属性，需要销毁当前图实例后重新创建。其他大部分配置可以动态更新。\n\n**示例 1**: 基本用法\n\n```typescript\n// 更新图表配置\ngraph.setOptions({\n  width: 1000, // 更新宽度\n  height: 800, // 更新高度\n  autoFit: 'view', // 开启自适应\n  animation: true, // 启用动画\n});\n```\n\n**示例 2**: 更新主题\n\n```typescript\n// 更新图表主题配置\ngraph.setOptions({\n  theme: {\n    type: 'dark', // 切换到暗色主题\n    // 自定义主题配置\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**示例 3**: 更新布局配置\n\n```typescript\n// 更新布局配置\ngraph.setOptions({\n  layout: {\n    type: 'force', // 切换到力导向布局\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**示例 4**: 更新节点和边的默认配置\n\n```typescript\n// 更新节点和边的默认样式配置\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n","frontmatter":{"title":"图配置项","order":"7"},"isInternal":false,"tokens":497,"sizeBytes":2760},{"name":"plugin.en.md","path":"packages/site/docs/api/plugin.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/plugin.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Plugin\norder: 8\n---\n\n## Overview of Plugins\n\n[Plugins](/en/manual/plugin/overview) are an important mechanism in G6 for extending functionality and enhancing the interactive experience of graphs. Plugins typically provide independent functional modules, such as thumbnails, toolbars, context menus, etc. They integrate well with the main graph while maintaining modular and maintainable code.\n\nThe plugin system is designed to follow the \"plug and play\" principle, allowing dynamic addition or removal as needed.\n\n## API Reference\n\n### Graph.getPluginInstance(key)\n\nRetrieve the plugin instance specified by the key, used to access and operate the methods provided by the plugin.\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**Parameters**\n\n| Parameter | Description                     | Type   | Default | Required |\n| --------- | ------------------------------- | ------ | ------- | -------- |\n| key       | Unique identifier of the plugin | string | -       | ✓        |\n\n**Return Value**\n\n- **Type**: Plugin instance\n- **Description**: The plugin instance corresponding to the specified key\n\n**Note**\n\nMany plugins provide specific API methods, which can be directly called by obtaining the plugin instance. For example, the fullscreen plugin provides `request()` and `exit()` methods to control fullscreen status.\n\n**Example**: Operate the fullscreen plugin\n\n```typescript\n// Get the fullscreen plugin instance\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// Request to enter fullscreen\nfullscreen.request();\n\n// Exit fullscreen later\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\nRetrieve all configured plugins in the current graph.\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**Return Value**\n\n- **Type**: [PluginOptions](#pluginoptions)\n- **Description**: All configured plugins in the current graph\n\n**Example**\n\n```typescript\n// Get all plugin configurations\nconst plugins = graph.getPlugins();\n\n// View currently active plugins\nconsole.log('Current graph plugin configurations:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\nSet the graph's plugins, replacing all existing plugin configurations.\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                     | Type                                                                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| plugins   | New plugin configurations, or a function returning new configurations based on the current ones | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -       | ✓        |\n\n**Note**\n\nThe set plugins will completely replace the original plugin configurations. To add new plugins based on existing ones, you can use functional updates:\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**Example 1**: Set basic plugins\n\n```typescript\n// Set multiple basic plugins\ngraph.setPlugins([\n  // String form (using default configuration)\n  'minimap',\n\n  // Object form (custom configuration)\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**Example 2**: Use functional updates\n\n```typescript\n// Add new plugins to existing configurations\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// Replace specific plugins\ngraph.setPlugins((currentPlugins) => {\n  // Filter out existing grid plugins\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // Add new grid plugin configuration\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\nUpdate the configuration of a specified plugin, identified by the `key` of the plugin to be updated.\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                               | Type                                      | Default | Required |\n| --------- | ----------------------------------------- | ----------------------------------------- | ------- | -------- |\n| plugin    | Configuration of the plugin to be updated | [UpdatePluginOption](#updatepluginoption) | -       | ✓        |\n\n**Note**\n\nTo update a plugin, the `key` field must be specified in the original plugin configuration to accurately locate and update the plugin.\n\n**Example 1**: Update plugin configuration\n\n```typescript\n// Specify key when initially setting plugins\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// Update grid plugin configuration\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## Type Definitions\n\n### PluginOptions\n\nPlugin configuration type, representing an array of plugin configurations.\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\nCustom plugin configuration interface, used to configure plugin parameters.\n\n```typescript\ntype CustomPluginOption = {\n  // Plugin type\n  type: string;\n\n  // Plugin key, i.e., unique identifier\n  // Used to identify the plugin for further operations\n  key?: string;\n\n  // Other configuration items for different types of plugins\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\nConfiguration interface for updating plugins, used to dynamically modify plugin parameters.\n\n```typescript\ntype UpdatePluginOption = {\n  // Unique identifier of the plugin to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"Plugin","order":"8"},"isInternal":false,"tokens":1554,"sizeBytes":6221},{"name":"plugin.zh.md","path":"packages/site/docs/api/plugin.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/plugin.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 插件\norder: 8\n---\n\n## 插件概述\n\n[插件](/manual/plugin/overview)（Plugin）是 G6 中扩展功能的重要机制，用于增强图表的功能和交互体验。插件通常提供一些独立的功能模块，如缩略图、工具栏、上下文菜单等，它们可以与图表主体良好集成，同时又保持代码的模块化和可维护性。\n\n插件系统设计遵循\"即插即用\"的原则，可以根据需要动态添加或移除。\n\n## API 参考\n\n### Graph.getPluginInstance(key)\n\n获取指定 key 的插件实例，用于访问和操作插件提供的方法。\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**参数**\n\n| 参数 | 描述             | 类型   | 默认值 | 必选 |\n| ---- | ---------------- | ------ | ------ | ---- |\n| key  | 插件的唯一标识符 | string | -      | ✓    |\n\n**返回值**\n\n- **类型**: 插件实例\n- **描述**: 指定 key 对应的插件实例\n\n**说明**\n\n许多插件提供了特定的API方法，通过获取插件实例可以直接调用这些方法。例如，全屏插件提供了 `request()` 和 `exit()` 方法来控制全屏状态。\n\n**示例**: 操作全屏插件\n\n```typescript\n// 获取全屏插件实例\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// 请求进入全屏\nfullscreen.request();\n\n// 稍后退出全屏\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\n获取当前图表中所有已配置的插件。\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**返回值**\n\n- **类型**: [PluginOptions](#pluginoptions)\n- **描述**: 当前图表中已配置的所有插件\n\n**示例**\n\n```typescript\n// 获取所有插件配置\nconst plugins = graph.getPlugins();\n\n// 查看当前激活的插件\nconsole.log('当前图表的插件配置:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\n设置图表的插件，将替换所有现有的插件配置。\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**参数**\n\n| 参数    | 描述                                             | 类型                                                                        | 默认值 | 必选 |\n| ------- | ------------------------------------------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| plugins | 新的插件配置，或一个基于当前配置返回新配置的函数 | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -      | ✓    |\n\n**说明**\n\n设置的插件会全量替换原有的插件配置。如果需要在现有插件基础上添加新插件，可以使用函数式更新方式：\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**示例 1**: 设置基本插件\n\n```typescript\n// 设置多个基本插件\ngraph.setPlugins([\n  // 字符串形式（使用默认配置）\n  'minimap',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**示例 2**: 使用函数式更新\n\n```typescript\n// 添加新插件到现有配置\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// 替换特定插件\ngraph.setPlugins((currentPlugins) => {\n  // 过滤掉现有的网格插件\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // 添加新的网格插件配置\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\n更新指定的插件配置，需要通过 `key` 标识要更新的插件。\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**参数**\n\n| 参数   | 描述           | 类型                                      | 默认值 | 必选 |\n| ------ | -------------- | ----------------------------------------- | ------ | ---- |\n| plugin | 更新的插件配置 | [UpdatePluginOption](#updatepluginoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个插件，必须在原始插件配置中指定 `key` 字段，以便能够准确找到并更新该插件。\n\n**示例 1**: 更新插件配置\n\n```typescript\n// 初始设置插件时指定 key\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// 更新网格插件配置\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## 类型定义\n\n### PluginOptions\n\n插件配置类型，表示一组插件配置的数组。\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\n自定义插件配置接口，用于配置插件参数。\n\n```typescript\ntype CustomPluginOption = {\n  // 插件类型\n  type: string;\n\n  // 插件 key，即唯一标识\n  // 用于标识插件，从而进一步操作此插件\n  key?: string;\n\n  // 针对不同类型的插件，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\n更新插件的配置接口，用于动态修改插件参数。\n\n```typescript\ntype UpdatePluginOption = {\n  // 要更新的插件的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"插件","order":"8"},"isInternal":false,"tokens":991,"sizeBytes":5527},{"name":"render.en.md","path":"packages/site/docs/api/render.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/render.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Drawing and Rendering\norder: 3\n---\n\n## Overview of Drawing and Rendering\n\nG6 provides a series of drawing and rendering-related APIs to control the display process of graphical elements. In G6, drawing and rendering are two different concepts:\n\n- **Drawing (draw)**: Responsible only for drawing graphical elements onto the canvas, without involving layout calculations.\n- **Rendering (render)**: A complete rendering process, including data processing, layout calculations, and final drawing.\n\nUnderstanding the differences between these APIs is crucial for optimizing performance and achieving specific effects.\n\n## API Reference\n\n### Graph.draw()\n\nDraw elements without performing layout calculations.\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**Note**\n\nThe `draw` method only executes the drawing process of elements and does not recalculate the layout.\n\n⚠️ **Attention**: `draw` is an asynchronous method, requiring the use of `await` or Promise chaining to ensure subsequent operations are executed after drawing is complete.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.draw();\n```\n\n**Example 2**: Redraw after modifying node styles\n\n```javascript\n// Redraw after modifying node styles\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// Only draw the updated styles without re-layout\nawait graph.draw();\n```\n\n**Example 3**: Batch update multiple elements and draw once\n\n```javascript\n// Update multiple nodes\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// Update edges\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// Draw after batch operations\nawait graph.draw();\n```\n\n**Example 4**: Use event listener to detect drawing completion\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('Drawing complete');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\nExecute the complete rendering process, including data processing, layout calculations, and drawing.\n\n```typescript\nrender(): Promise<void>;\n```\n\n**Note**\n\nThe `render` method executes the complete rendering process:\n\n1. Process data updates\n2. Draw elements onto the canvas\n3. Execute layout algorithms\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.render();\n```\n\n**Example 2**: Render after adding new data\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**Example 3**: Listen to rendering events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before rendering starts\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('Rendering starts...');\n  // Show loading indicator\n  showLoadingIndicator();\n});\n\n// After rendering completes\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('Rendering complete');\n  // Hide loading indicator\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\nClear all elements on the canvas, including nodes, edges, and other graphical elements.\n\n```typescript\nclear(): Promise<void>;\n```\n\n**Note**\n\nThis method deletes all elements in the graph but retains the canvas configuration and styles. It is an asynchronous method that returns a Promise.\n\n**Example**\n\n```typescript\n// Basic usage\nawait graph.clear();\n```\n\n## Usage Tips\n\n### Choosing between draw and render\n\n- Use `draw()` when:\n  - Only the styles or states of elements are modified, without needing to recalculate positions.\n  - Performance-sensitive, aiming to avoid unnecessary layout calculations.\n- Use `render()` when:\n  - Initializing the graph.\n  - Changing layout configurations.\n  - Adding or removing a large number of nodes/edges.\n  - Need to recalculate positions of all elements.\n","frontmatter":{"title":"Drawing and Rendering","order":"3"},"isInternal":false,"tokens":983,"sizeBytes":3933},{"name":"render.zh.md","path":"packages/site/docs/api/render.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/render.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 绘制与渲染\norder: 3\n---\n\n## 绘制与渲染概述\n\nG6 提供了一系列绘制和渲染相关的 API，用于控制图形元素的显示过程。在 G6 中，绘制和渲染是两个不同的概念：\n\n- **绘制(draw)**: 仅负责将图形元素绘制到画布上，不涉及布局计算\n- **渲染(render)**: 完整的渲染流程，包括数据处理、布局计算和最终绘制\n\n理解这些 API 的区别对于优化性能和实现特定效果至关重要。\n\n## API 参考\n\n### Graph.draw()\n\n绘制元素，但不执行布局计算。\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**说明**\n\n`draw` 方法仅执行元素的绘制过程，不会重新计算布局。\n\n⚠️ **注意**: `draw` 为异步方法，需要使用 `await` 或 Promise 链式调用来确保绘制完成后再执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 基本用法\nawait graph.draw();\n```\n\n**示例 2**: 修改节点样式后重新绘制\n\n```javascript\n// 修改节点样式后重新绘制\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 仅绘制更新后的样式，不重新布局\nawait graph.draw();\n```\n\n**示例 3**: 批量更新多个元素后一次性绘制\n\n```javascript\n// 更新多个节点\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// 更新边\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// 批量操作完成后绘制\nawait graph.draw();\n```\n\n**示例 4**: 使用事件监听绘制完成\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('绘制完成');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\n执行完整的渲染流程，包括数据处理、布局计算和绘制。\n\n```typescript\nrender(): Promise<void>;\n```\n\n**说明**\n\n`render` 方法会执行完整的渲染流程：\n\n1. 处理数据更新\n2. 绘制元素到画布上\n3. 执行布局算法\n\n**示例 1**: 基本用法\n\n```typescript\n// 基本用法\nawait graph.render();\n```\n\n**示例 2**: 添加新数据后渲染\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**示例 3**: 监听渲染事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 渲染开始前\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('渲染开始...');\n  // 显示加载指示器\n  showLoadingIndicator();\n});\n\n// 渲染完成后\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('渲染完成');\n  // 隐藏加载指示器\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\n清空画布上的所有元素，包括节点、边和其他图形元素。\n\n```typescript\nclear(): Promise<void>;\n```\n\n**说明**\n\n此方法会删除图中的所有元素，但保留画布配置和样式。这是一个异步方法，返回一个 Promise。\n\n**示例**\n\n```typescript\n// 基本用法\nawait graph.clear();\n```\n\n## 使用技巧\n\n### draw 与 render 的选择\n\n- 使用 `draw()` 当:\n  - 仅修改了元素样式或状态，不需要重新计算位置\n  - 性能敏感，希望避免不必要的布局计算\n- 使用 `render()` 当:\n  - 初始化图表\n  - 更改了布局配置\n  - 添加或删除了大量节点/边\n  - 需要重新计算所有元素位置\n","frontmatter":{"title":"绘制与渲染","order":"3"},"isInternal":false,"tokens":572,"sizeBytes":3460},{"name":"theme.en.md","path":"packages/site/docs/api/theme.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/theme.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Theme\norder: 9\n---\n\n## Overview of Theme\n\nG6 allows users to customize the appearance of graphs through themes. Themes can be used to define colors, shapes, and styles for nodes, edges, and other graph elements.\n\n## API Reference\n\n### Graph.getTheme()\n\nGet the theme\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>Related Parameters</summary>\n\n**Return Value**:\n\n- **Type:** false \\| 'light' \\| 'dark' \\| string\n\n- **Description:** Current theme\n\n</details>\n\n### Graph.setTheme(theme)\n\nSet the theme\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**Example**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>Related Parameters</summary>\n\n<table><thead><tr><th>\n\nParameter\n\n</th><th>\n\nType\n\n</th><th>\n\nDescription\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) => false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\nTheme name\n\n</td></tr>\n</tbody></table>\n\n**Return Value**:\n\n- **Type:** void\n\n</details>\n\n## Type Definitions\n\n### ThemeOptions\n\n```typescript\ntype ThemeOptions = {\n  // Colors used in the theme\n  colors: string[];\n\n  // Node style settings\n  nodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Edge style settings\n  edgeStyle?: {\n    stroke: string;\n  };\n\n  // Additional configuration options for the theme\n  [configKey: string]: any;\n};\n```\n","frontmatter":{"title":"Theme","order":"9"},"isInternal":false,"tokens":362,"sizeBytes":1446},{"name":"theme.zh.md","path":"packages/site/docs/api/theme.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/theme.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 主题\norder: 9\n---\n\n## API 参考\n\n### Graph.getTheme()\n\n获取主题\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>相关参数</summary>\n\n**返回值**：\n\n- **类型：** false \\| 'light' \\| 'dark' \\| string\n\n- **描述：** 当前主题\n\n</details>\n\n### Graph.setTheme(theme)\n\n设置主题\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**示例**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>相关参数</summary>\n\n<table><thead><tr><th>\n\n参数\n\n</th><th>\n\n类型\n\n</th><th>\n\n描述\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) =&gt; false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\n主题名\n\n</td></tr>\n</tbody></table>\n\n**返回值**：\n\n- **类型：** void\n\n</details>\n","frontmatter":{"title":"主题","order":"9"},"isInternal":false,"tokens":191,"sizeBytes":868},{"name":"transform.en.md","path":"packages/site/docs/api/transform.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/transform.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Data Transformation\norder: 10\n---\n\n## Overview of Data Transformation\n\n[Data Transformation](/en/manual/transform/overview) is a powerful feature in G6 that allows for processing and transforming data during the graph rendering process. With data transformers, you can achieve various data processing needs, such as:\n\n- Data Filtering: Filter nodes and edges to be displayed based on conditions\n- Data Calculation: Generate new attributes based on original data, such as calculating node size based on the number of connections, without polluting the original data\n- Data Aggregation: Aggregate a large number of nodes into fewer nodes to improve the performance of large-scale graphs\n\nData transformation occurs at specific stages of the rendering process, allowing flexible changes to the final presentation without modifying the original data source.\n\n## API Reference\n\n### Graph.getTransforms()\n\nRetrieve all configured data transformers in the current graph.\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**Return Value**\n\n- **Type**: [TransformOptions](#transformoptions)\n- **Description**: All configured data transformers in the current graph\n\n**Example**\n\n```typescript\n// Retrieve all data transformers\nconst transforms = graph.getTransforms();\nconsole.log('Data transformers in the current graph:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\nSet the data transformers for the graph, replacing all existing transformers.\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**Parameters**\n\n| Parameter  | Description                                                                                               | Type                                                                                  | Default | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------- | -------- |\n| transforms | New data transformer configurations, or a function returning new configurations based on the current ones | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -       | ✓        |\n\n**Note**\n\nData transformers can process data at different stages of the graph rendering process. The set data transformations will completely replace the original ones. To add new data transformations based on existing ones, you can use functional updates.\n\n**Example 1**: Set basic data transformations\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**Example 2**: Set data transformations with configurations\n\n```typescript\ngraph.setTransforms([\n  // String form (using default configuration)\n  'process-parallel-edges',\n\n  // Object form (custom configuration)\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // Distance between parallel edges\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new data transformations to existing configurations\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\nUpdate the configuration of a specified data transformer, identified by the `key` of the transformer to be updated.\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                         | Type                                            | Default | Required |\n| --------- | --------------------------------------------------- | ----------------------------------------------- | ------- | -------- |\n| transform | Configuration of the data transformer to be updated | [UpdateTransformOption](#updatetransformoption) | -       | ✓        |\n\n**Note**\n\nTo update a data transformer, the `key` field must be specified in the original data transformer configuration to accurately locate and update the transformer.\n\n**Example**: Update data transformer configuration\n\n```typescript\n// Specify key when initially setting data transformers\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// Update distance between parallel edges\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## Type Definitions\n\n### TransformOptions\n\nData transformer configuration type, representing an array of data transformer configurations.\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\nCustom data transformer configuration interface, used to configure data processing parameters.\n\n```typescript\ntype CustomTransformOption = {\n  // Data processing type\n  type: string;\n\n  // Unique identifier for the data transformer\n  key?: string;\n\n  // Other configuration items for different types of data processing\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\nConfiguration interface for updating data transformers, used to dynamically modify data processing parameters.\n\n```typescript\ntype UpdateTransformOption = {\n  // Unique identifier of the data transformer to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"Data Transformation","order":"10"},"isInternal":false,"tokens":1382,"sizeBytes":5530},{"name":"transform.zh.md","path":"packages/site/docs/api/transform.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/transform.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 数据处理\norder: 10\n---\n\n## 数据处理概述\n\n[数据处理](/manual/transform/overview)（Transform）是 G6 中一项强大的功能，允许在图渲染过程中对数据进行处理和转换。通过数据处理器，您可以实现各种数据处理需求，比如：\n\n- 数据过滤：根据条件筛选需要显示的节点和边\n- 数据计算：基于原始数据生成新的属性，如根据节点连接数计算节点大小，但不污染原始数据\n- 数据聚合：将大量节点聚合为少量节点，提高大规模图表的性能\n\n数据处理发生在渲染流程的特定阶段，可以灵活地改变最终呈现的结果，而无需修改原始数据源。\n\n## API 参考\n\n### Graph.getTransforms()\n\n获取当前图表中所有已配置的数据处理器。\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**返回值**\n\n- **类型**: [TransformOptions](#transformoptions)\n- **描述**: 当前图表中已配置的所有数据处理器\n\n**示例**\n\n```typescript\n// 获取当前所有数据处理器\nconst transforms = graph.getTransforms();\nconsole.log('当前图表的数据处理器:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\n设置图表的数据处理器，将替换所有现有的数据处理器。\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**参数**\n\n| 参数       | 描述                                                   | 类型                                                                                  | 默认值 | 必选 |\n| ---------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------ | ---- |\n| transforms | 新的数据处理器配置，或一个基于当前配置返回新配置的函数 | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -      | ✓    |\n\n**说明**\n\n数据处理器能够在图渲染过程的不同阶段对数据进行处理。设置的数据处理会全量替换原有的数据处理，如果需要在现有数据处理基础上添加新的数据处理，可以使用函数式更新方式。\n\n**示例 1**: 设置基本数据处理\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**示例 2**: 设置带配置的数据处理\n\n```typescript\ngraph.setTransforms([\n  // 字符串形式（使用默认配置）\n  'process-parallel-edges',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // 平行边之间的距离\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的数据处理到现有配置\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\n更新指定的数据处理器配置，需要通过 `key` 标识要更新的数据处理。\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**参数**\n\n| 参数      | 描述               | 类型                                            | 默认值 | 必选 |\n| --------- | ------------------ | ----------------------------------------------- | ------ | ---- |\n| transform | 更新的数据处理配置 | [UpdateTransformOption](#updatetransformoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个数据处理器，必须在原始数据处理配置中指定 `key` 字段，以便能够准确找到并更新该数据处理。\n\n**示例**: 更新数据处理配置\n\n```typescript\n// 初始设置数据处理时指定 key\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// 更新平行边距离\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## 类型定义\n\n### TransformOptions\n\n数据处理器配置类型，表示一组数据处理配置的数组。\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\n自定义数据处理配置接口，用于配置数据处理参数。\n\n```typescript\ntype CustomTransformOption = {\n  // 数据处理类型\n  type: string;\n\n  // 数据处理唯一标识\n  key?: string;\n\n  // 针对不同类型的数据处理，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\n更新数据处理的配置接口，用于动态修改数据处理参数。\n\n```typescript\ntype UpdateTransformOption = {\n  // 要更新的数据处理的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n","frontmatter":{"title":"数据处理","order":"10"},"isInternal":false,"tokens":832,"sizeBytes":4837},{"name":"viewport.en.md","path":"packages/site/docs/api/viewport.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/viewport.en.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Viewport Operations\norder: 4\n---\n\n## Overview of Viewport Operations\n\nG6 provides a series of viewport operation APIs to control the zooming, panning, and rotating of the canvas. These operations help users better view and interact with graphical content. Through viewport operations, you can achieve the following functions:\n\n- Zoom the canvas to view details or the global view\n- Pan the canvas to view different areas\n- Rotate the canvas to get different perspectives\n- Automatically fit content to the viewport\n\n### Categories of Viewport Operations\n\nViewport operations in G6 are mainly divided into the following categories:\n\n1. **Zoom Operations**: such as `zoomTo`, `zoomBy`\n2. **Pan Operations**: such as `translateTo`, `translateBy`\n3. **Rotate Operations**: such as `rotateTo`, `rotateBy`\n4. **Fit Operations**: such as `fitView`, `fitCenter`\n5. **Viewport Information Retrieval**: such as `getZoom`, `getPosition`\n\n## API Reference\n\n### Graph.zoomTo(zoom, animation, origin)\n\nZoom the canvas to a specified scale (absolute zoom).\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                                    | Type                                                            | Default | Required |\n| --------- | -------------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| zoom      | Target zoom scale (1 = original size, >1 zoom in, <1 zoom out) | number                                                          | -       | ✓        |\n| animation | Animation configuration                                        | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates)                       | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in to 2x\ngraph.zoomTo(2);\n\n// Zoom out to 0.5x with animation\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// Zoom in with the viewport center as the origin\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\nZoom based on the current zoom scale (relative zoom).\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                              | Type                                                            | Default | Required |\n| --------- | ---------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ratio     | Zoom ratio (>1 zoom in, <1 zoom out)     | number                                                          | -       | ✓        |\n| animation | Animation configuration                  | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in by 1.2x based on the current scale\ngraph.zoomBy(1.2);\n\n// Zoom out to 0.8x based on the current scale with animation\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\nPan the graph to a specified position (absolute pan).\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                 | Type                                                            | Default | Required |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| position  | Target position coordinates | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan to a specified position\ngraph.translateTo([100, 100]);\n\n// Pan with animation\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\nPan the graph by a specified distance relative to the current position (relative pan).\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| offset    | Pan offset              | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan right by 100 pixels and down by 50 pixels\ngraph.translateBy([100, 50]);\n\n// Relative pan with animation\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\nRotate the canvas to a specified angle (absolute rotation).\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Target rotation angle (radians)              | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate to 45 degrees\ngraph.rotateTo(Math.PI / 4);\n\n// Rotate to 90 degrees with animation\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\nRotate based on the current angle (relative rotation).\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Rotation angle increment (radians)           | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate clockwise by 30 degrees relative to the current angle\ngraph.rotateBy(Math.PI / 6);\n\n// Relative rotation with animation\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\nScale the graph to fit the appropriate size and pan to the center of the viewport.\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| options   | Fit options             | FitViewOptions                                                  | -       |          |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**FitViewOptions Type Description**\n\n| Property  | Type                   | Default    | Description                                       |\n| --------- | ---------------------- | ---------- | ------------------------------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | Fit timing: only when overflow or always          |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | Fit direction: x-axis, y-axis, or both directions |\n\n**Example**\n\n```typescript\n// Basic usage\ngraph.fitView();\n\n// Configure fit options\ngraph.fitView(\n  {\n    when: 'always', // Always fit\n    direction: 'both', // Fit in both directions\n  },\n  {\n    duration: 1000, // With animation\n  },\n);\n\n// Fit in the x direction only when content overflows\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\nPan the graph to the center of the viewport.\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Center the graph\ngraph.fitCenter();\n\n// Center with animation\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\nGet the current zoom scale.\n\n```typescript\ngetZoom(): number;\n```\n\n**Example**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('Current zoom scale:', currentZoom);\n```\n\n### Graph.getPosition()\n\nGet the position of the graph (position of the canvas origin in the viewport coordinate system).\n\n```typescript\ngetPosition(): Point;\n```\n\n**Example**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('Current position:', position);\n```\n\n### Graph.getRotation()\n\nGet the current rotation angle.\n\n```typescript\ngetRotation(): number;\n```\n\n**Example**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('Current rotation angle (radians):', rotation);\nconsole.log('Current rotation angle (degrees):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\nGet the viewport coordinates of the viewport center.\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('Viewport center coordinates:', center);\n```\n\n### Graph.getViewportCenter()\n\nGet the canvas coordinates of the viewport center.\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('Canvas coordinates of the viewport center:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\nSet the zoom range of the current graph.\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**Parameters**\n\n| Parameter | Description | Type                          | Default | Required |\n| --------- | ----------- | ----------------------------- | ------- | -------- |\n| zoomRange | Zoom range  | [number, number] \\| undefined | -       | ✓        |\n\n**Example**\n\n```typescript\n// Limit the zoom range between 0.5x and 2x\ngraph.setZoomRange([0.5, 2]);\n\n// Remove zoom restrictions\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\nGet the zoom range of the current graph.\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**Example**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('Current zoom range:', range);\n```\n\n### Graph.resize()\n\nResize the canvas to the size of the graph container.\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\nResize the canvas to the specified width and height.\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description   | Type   | Default | Required |\n| --------- | ------------- | ------ | ------- | -------- |\n| width     | Target width  | number | -       | ✓        |\n| height    | Target height | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set the canvas size to 800x600\ngraph.resize(800, 600);\n```\n\n## Type Definitions\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Whether to enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### Point\n\nCoordinate point type.\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\nView fit options.\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // Fit timing\n  direction?: 'x' | 'y' | 'both'; // Fit direction\n}\n```\n","frontmatter":{"title":"Viewport Operations","order":"4"},"isInternal":false,"tokens":3341,"sizeBytes":13380},{"name":"viewport.zh.md","path":"packages/site/docs/api/viewport.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/api/viewport.zh.md","title":"Api Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 视口操作\norder: 4\n---\n\n## 视口操作概述\n\nG6 提供了一系列视口操作 API，用于控制画布的缩放、平移和旋转。这些操作可以帮助用户更好地查看和交互图形内容。通过视口操作，你可以实现以下功能：\n\n- 缩放画布以查看细节或全局视图\n- 平移画布以查看不同区域\n- 旋转画布以获得不同视角\n- 自动适配内容到视口\n\n### 视口操作分类\n\nG6 的视口操作主要分为以下几类：\n\n1. **缩放操作**：如 `zoomTo`、`zoomBy`\n2. **平移操作**：如 `translateTo`、`translateBy`\n3. **旋转操作**：如 `rotateTo`、`rotateBy`\n4. **自适应操作**：如 `fitView`、`fitCenter`\n5. **视口信息获取**：如 `getZoom`、`getPosition`\n\n## API 参考\n\n### Graph.zoomTo(zoom, animation, origin)\n\n缩放画布至指定比例（绝对缩放）。\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                                          | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| zoom      | 目标缩放比例 (1 = 原始大小, >1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)                          | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 放大到2倍\ngraph.zoomTo(2);\n\n// 带动画效果的缩小到0.5倍\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// 以视口中心点为原点放大\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\n基于当前缩放比例进行缩放（相对缩放）。\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                        | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ratio     | 缩放比例 (>1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)        | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 在当前比例基础上放大1.2倍\ngraph.zoomBy(1.2);\n\n// 在当前比例基础上缩小到0.8倍，带动画\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\n将图平移至指定位置（绝对平移）。\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述         | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------ | --------------------------------------------------------------- | ------ | ---- |\n| position  | 目标位置坐标 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 平移到指定位置\ngraph.translateTo([100, 100]);\n\n// 带动画效果的平移\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\n将图相对当前位置平移指定距离（相对平移）。\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述       | 类型                                                            | 默认值 | 必选 |\n| --------- | ---------- | --------------------------------------------------------------- | ------ | ---- |\n| offset    | 平移偏移量 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置   | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 向右平移100像素，向下平移50像素\ngraph.translateBy([100, 50]);\n\n// 带动画效果的相对平移\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\n旋转画布至指定角度（绝对旋转）。\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 目标旋转角度(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 旋转到45度\ngraph.rotateTo(Math.PI / 4);\n\n// 带动画效果的旋转到90度\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\n基于当前角度进行旋转（相对旋转）。\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 旋转角度增量(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 相对当前角度顺时针旋转30度\ngraph.rotateBy(Math.PI / 6);\n\n// 带动画效果的相对旋转\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\n将图缩放至合适大小并平移至视口中心。\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| options   | 适配选项 | FitViewOptions                                                  | -      |      |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**FitViewOptions 类型说明**\n\n| 属性      | 类型                   | 默认值     | 描述                         |\n| --------- | ---------------------- | ---------- | ---------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | 适配时机：仅溢出时或始终适配 |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | 适配方向：x轴、y轴或两个方向 |\n\n**示例**\n\n```typescript\n// 基本使用\ngraph.fitView();\n\n// 配置适配选项\ngraph.fitView(\n  {\n    when: 'always', // 始终进行适配\n    direction: 'both', // 在两个方向上适配\n  },\n  {\n    duration: 1000, // 带动画效果\n  },\n);\n\n// 仅在内容溢出时适配x方向\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\n将图平移至视口中心。\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 居中显示\ngraph.fitCenter();\n\n// 带动画效果的居中\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\n获取当前缩放比例。\n\n```typescript\ngetZoom(): number;\n```\n\n**示例**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('当前缩放比例:', currentZoom);\n```\n\n### Graph.getPosition()\n\n获取图的位置（画布原点在视口坐标系下的位置）。\n\n```typescript\ngetPosition(): Point;\n```\n\n**示例**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('当前位置:', position);\n```\n\n### Graph.getRotation()\n\n获取当前旋转角度。\n\n```typescript\ngetRotation(): number;\n```\n\n**示例**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('当前旋转角度(弧度):', rotation);\nconsole.log('当前旋转角度(度):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\n获取视口中心的视口坐标。\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('视口中心坐标:', center);\n```\n\n### Graph.getViewportCenter()\n\n获取视口中心的画布坐标。\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('视口中心的画布坐标:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\n设置当前图的缩放区间。\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                          | 默认值 | 必选 |\n| --------- | -------- | ----------------------------- | ------ | ---- |\n| zoomRange | 缩放区间 | [number, number] \\| undefined | -      | ✓    |\n\n**示例**\n\n```typescript\n// 限制缩放范围在0.5到2倍之间\ngraph.setZoomRange([0.5, 2]);\n\n// 移除缩放限制\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\n获取当前图的缩放区间。\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**示例**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('当前缩放区间:', range);\n```\n\n### Graph.resize()\n\n调整画布大小为图容器大小。\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\n调整画布大小为指定宽高。\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述     | 类型   | 默认值 | 必选 |\n| ------ | -------- | ------ | ------ | ---- |\n| width  | 目标宽度 | number | -      | ✓    |\n| height | 目标高度 | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置画布大小为800x600\ngraph.resize(800, 600);\n```\n\n## 类型定义\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### Point\n\n坐标点类型。\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\n视图适配选项。\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // 适配时机\n  direction?: 'x' | 'y' | 'both'; // 适配方向\n}\n```\n","frontmatter":{"title":"视口操作","order":"4"},"isInternal":false,"tokens":2500,"sizeBytes":12139},{"name":"CameraSetting.en.md","path":"packages/site/docs/backup/CameraSetting.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/backup/CameraSetting.en.md","title":"Backup Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CameraSetting\n---\n\n## Options\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _string_\n\nPlugin type\n\n### aspect\n\n> _number \\| 'auto'_\n\nCamera viewport aspect ratio, only valid in perspective camera.\n\n- number : Specific aspect ratio\n\n- `'auto'` : Automatically set to the aspect ratio of the canvas\n\n### azimuth\n\n> _number_\n\nAzimuth\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\nCamera type\n\n- `'orbiting'`: Fixed viewpoint, change camera position\n\n- `'exploring'`: Similar to orbiting, but allows the camera to rotate between the North Pole and the South Pole\n\n- `'tracking'`: Fixed camera position, change viewpoint\n\n### distance\n\n> _number_ **Default:** `500`\n\nThe distance from the camera to the target\n\n### elevation\n\n> _number_\n\nElevation\n\n### far\n\n> _number_\n\nThe position of the far plane\n\n### fov\n\n> _number_\n\nCamera field of view, only valid in perspective camera\n\n### maxDistance\n\n> _number_\n\nMaximum distance\n\n### minDistance\n\n> _number_\n\nMinimum distance\n\n### near\n\n> _number_\n\nThe position of the near plane\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\nProjection mode, perspective projection is only valid in 3D scenes\n\n- `'perspective'` : perspective projection\n\n- `'orthographic'` : Orthogonal projection\n\n### roll\n\n> _number_\n\nRoll\n\n## API\n","frontmatter":{"title":"CameraSetting"},"isInternal":false,"tokens":326,"sizeBytes":1302},{"name":"CameraSetting.zh.md","path":"packages/site/docs/backup/CameraSetting.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/backup/CameraSetting.zh.md","title":"Backup Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CameraSetting 相机设置\n---\n\n## 配置项\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _`camera-setting` \\| string_\n\n⚠️ **注意**：\n\n- 相机设置插件必须在 3D 场景下使用\n- 此插件在使用前需要自行注册：\n\n```javascript\nimport { register, CameraSetting, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting); // type: 'camera-setting'\n```\n\n### aspect\n\n> _number \\| `'auto'`_\n\n相机视口宽高比，仅在透视相机下有效\n\n- number : 具体的宽高比\n\n- `'auto'` : 自动设置为画布的宽高比\n\n### azimuth\n\n> _number_\n\n方位角\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\n相机类型\n\n- `'orbiting'`: 固定视点，改变相机位置\n- `'exploring'`: 类似 orbiting，但允许相机在北极和南极之间旋转\n- `'tracking'`: 固定相机位置，改变视点\n\n### distance\n\n> _number_ **Default:** `500`\n\n相机距离目标的距离\n\n### elevation\n\n> _number_\n\n仰角\n\n### far\n\n> _number_\n\n远平面位置\n\n### fov\n\n> _number_\n\n相机视角，仅在透视相机下有效\n\n### maxDistance\n\n> _number_\n\n最大视距\n\n### minDistance\n\n> _number_\n\n最小视距\n\n### near\n\n> _number_\n\n近平面位置\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\n投影模式，透视投影仅在 3D 场景下有效\n\n- `'perspective'` : 透视投影\n- `'orthographic'` : 正交投影\n\n### roll\n\n> _number_\n\n滚转角\n\n## API\n","frontmatter":{"title":"CameraSetting 相机设置"},"isInternal":false,"tokens":269,"sizeBytes":1458},{"name":"animation.en.md","path":"packages/site/docs/manual/animation/animation.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/animation/animation.en.md","title":"Animation Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Animation Overview\norder: 1\n---\n\n## Overview\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nAnimation refers to the state changes of elements over a period of time, such as the position, size, and color of nodes. In G6, animations are often used to enhance user experience and improve the coherence and smoothness of the graph update process.\n\nG6 provides a set of animation paradigms to describe element animations and has built-in some common animation effects. Users can achieve different animation effects by configuring animation parameters.\n\nThe implementation of an animation paradigm is as follows:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\nThe aforementioned animation paradigm indicates that when the `x` and `y` attributes of an element change, an animation will be executed.\n\n## Configure Animation\n\nIn G6, animation configuration is divided into global configuration and local configuration. Global configuration is mainly used to set whether animations are enabled globally, the duration of animations, and other parameters. Local configuration is primarily used to set the animation effects for elements.\n\n### Disabled Global Animation\n\nTo disable global animations, you can pass the `animation` option when instantiating the `Graph`:\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### Configure Global Animation\n\nIf you want to enable animations and also configure the default duration for the animations, you can pass the `animation` option:\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### Configure Element Animation\n\nFor individual elements, you can configure animations at different stages. For example, if you want an element to have a fade-in and fade-out effect when it enters and exits, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\nIf you want to update the position of an element with a translation transition, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\nIf you wish to disable animations for an element, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## Animation Paradigm\n\nThe animation configuration mentioned in the previous section actually used the built-in animation paradigm. This section introduces how to customize the animation paradigm.\n\n:::info{title=Tip}\nBefore writing an animation paradigm, it is necessary to understand the compositional structure of an element. For details, please refer to the [Element](/en/manual/element/overview) section.\n:::\n\nThe [Element](/en/manual/element/overview) section mentioned that elements in G6 are composed of one or more atomic graphics. Therefore, the animation of an element is essentially a combination of these atomic shape animations.\n\nThus, the animation paradigm is an array that describes the animation effects of each atomic shape within the element. For the element itself, it is also a special composite shape and thus has basic shape attributes such as `x`, `y`, etc.\n\nTherefore, you can directly write an animation paradigm for the element itself:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## Custom Animation\n\nIf the built-in animations do not meet your requirements, you can create custom animations. For details, please refer to [Custom Animation](/en/manual/animation/custom-animation).\n\n## Animation Priority\n\nAnimation priority refers to the precedence between global animation configuration and element-specific animation configuration. It can be summarized as follows:\n\n| Global Animation Config | Local Animation Config | Whether to Execute Animation                                                                     |\n| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------ |\n| ✅ true                 | ✅ true                | ✅ Execute animation with default configuration                                                  |\n| ✅ true                 | ❌ false               | ❌ Won't execute animation                                                                       |\n| ✅ true                 | ✅ Custom Animation    | ✅ Execute animation with local animation configuration                                          |\n| ❌ false                | ✅ true                | ❌ Won't execute animation                                                                       |\n| ❌ false                | ❌ false               | ❌ Won't execute animation                                                                       |\n| ❌ false                | ✅ Custom Animation    | ❌ Won't execute animation                                                                       |\n| ✅ Custom Animation     | ✅ true                | ✅ Execute animation with global animation configuration                                         |\n| ✅ Custom Animation     | ✅ Custom Animation    | ✅ Execute animation, local animation configuration overrides the global animation configuration |\n| ✅ Custom Animation     | ❌ false               | ❌ Won't execute animation                                                                       |\n\n## Persistent Animation\n\nIf you want elements to have persistent animations, such as the undulating effect of nodes or the ant line effect of edges, this can be achieved by customizing the elements. Below is an implementation of an edge with an Ant Line animation provided:\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\nThe `onCreate` is a lifecycle hook used to execute animations when an element is created.\n\nConfigure the edge style in the options as follows:\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\nThe `lineDash` is an array for `lineDashOffset`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\nThe `lineDashOffset` is the offset for `lineDash`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\nNode Style Configuration:\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","frontmatter":{"title":"Animation Overview","order":"1"},"isInternal":false,"tokens":1805,"sizeBytes":7271},{"name":"animation.zh.md","path":"packages/site/docs/manual/animation/animation.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/animation/animation.zh.md","title":"Animation Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 动画总览\norder: 1\n---\n\n## 概述\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n动画是指元素在一段时间内的状态变化，例如节点的位置、大小、颜色等。在 G6 中，动画通常用于增强用户体验，提升图更新过程的连贯性和流畅度。\n\nG6 提供了一套动画范式来描述元素动画，并内置了一些常用的动画效果，用户可以通过配置动画参数来实现不同的动画效果。\n\n一个动画范式的实现如下：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n上述动画范式表示当元素的 `x` 和 `y` 属性发生变化时，会执行动画。\n\n## 配置动画\n\nG6 中动画配置分为全局配置和局部配置，全局配置主要用于配置全局是否开启动画、动画时长等参数，局部配置主要用于配置元素的动画效果。\n\n### 关闭全局动画\n\n若要关闭全局动画，可以在实例化 `Graph` 时传入 `animation` 配置项：\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### 配置全局动画\n\n如果要启用动画且同时配置动画的默认播放时长，可以传入 `animation` 配置项：\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### 配置元素动画\n\n对于单个元素，可以配置其在不同阶段的动画。例如希望元素在进场和退场时具有淡入淡出效果，可以以如下方式配置：\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\n如果希望更新元素位置时是以平移过渡的方式，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\n如果希望关闭元素的动画，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## 动画范式\n\n上一节中提到的动画配置实际上使用了内置的动画范式，本节介绍如何自定义动画范式。\n\n:::info{title=提示}\n在编写动画范式之前需要了解元素的组成结构，具体请参考[元素](/manual/element/overview)一节\n:::\n\n[元素](/manual/element/overview)一节中提到：G6 中的元素是由一个或多个原子图形组合而成。因此元素的动画本质上是这些原子图形动画的组合。\n\n因此动画范式是一个数组，用于描述元素中各原子图形的动画效果。对于元素本身来说，其也是一个特殊的复合图形，因此具有基本的图形属性，如 `x`、`y` 等。\n\n因此可以直接为元素本身编写动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## 自定义动画\n\n如果内置动画无法满足需求，可以自定义动画，具体请参考[自定义动画](/manual/animation/custom-animation)。\n\n## 动画优先级\n\n动画优先级是指全局动画配置和元素动画配置之前的优先级，可以归纳如下：\n\n| 全局动画配置 | 局部动画配置 | 是否执行动画                                      |\n| ------------ | ------------ | ------------------------------------------------- |\n| ✅ true      | ✅ true      | ✅ 执行动画，以默认动画配置执行                   |\n| ✅ true      | ❌ false     | ❌ 不执行该类元素动画                             |\n| ✅ true      | ✅ 配置动画  | ✅ 执行动画，以局部动画配置执行                   |\n| ❌ false     | ✅ true      | ❌ 不执行任何动画                                 |\n| ❌ false     | ❌ false     | ❌ 不执行任何动画                                 |\n| ❌ false     | ✅ 配置动画  | ❌ 不执行任何动画                                 |\n| ✅ 配置动画  | ✅ true      | ✅ 执行动画，以全局动画配置执行                   |\n| ✅ 配置动画  | ✅ 配置动画  | ✅ 执行动画，将局部动画配置覆盖全局动画配置后执行 |\n| ✅ 配置动画  | ❌ false     | ❌ 不执行该类元素动画                             |\n\n## 持续动画\n\n如果希望元素具有持续动画，例如节点的波动效果、边的蚂蚁线效果等，可以通过自定义元素方式实现，下面提供一个具有蚂蚁线(Ant Line)动画的边的实现：\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\n其中 `onCreate` 是一个生命周期钩子，用于在元素创建时执行动画。\n\n在 options 中配置边样式：\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\n其中 `lineDash` 是 `lineDashOffset` 的数组，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\n其中 `lineDashOffset` 是 `lineDash` 的偏移量，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\n节点样式配置：\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n","frontmatter":{"title":"动画总览","order":"1"},"isInternal":false,"tokens":916,"sizeBytes":5758},{"name":"custom-animation.en.md","path":"packages/site/docs/manual/animation/custom-animation.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/animation/custom-animation.en.md","title":"Animation Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Animation\norder: 2\n---\n\n## Overview\n\n## Implement Animation\n\nFor circular node (Circle) elements, the main shape is a circle. Now, let's create an animation for it so that when the size of the node changes, it transitions with a scaling animation:\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nNow let's create a graph instance and update the element size to trigger the update animation:\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### Principle Analysis\n\nWhen animating an element, the element converts its animation frame parameters into animation frame parameters for its individual sub-graphics and executes the corresponding animations.\n\nIn the example above, by updating the node size, an animation was performed on the node, and its animation frame parameters were:\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\nAfter obtaining the attribute, the node element converts it into animation frame parameters for the main shape (circle):\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\nTherefore, what is ultimately happening here is that a transition animation is being performed on the circle, changing its radius from 10 to 20.\n\n#### Composite Animation\n\nBy directly combining the position change animation with the size change animation into a single animation paradigm, you can obtain a composite animation paradigm:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nAnd update both the position and size of the node simultaneously:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\nAdd color transition:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\nExecute node update:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","frontmatter":{"title":"Custom Animation","order":"2"},"isInternal":false,"tokens":698,"sizeBytes":2804},{"name":"custom-animation.zh.md","path":"packages/site/docs/manual/animation/custom-animation.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/animation/custom-animation.zh.md","title":"Animation Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义动画\norder: 2\n---\n\n## 概述\n\n## 实现动画\n\n对于圆形节点（Circle）元素，其主图形是一个圆形，现在为其编写一个动画，当节点的尺寸发生变化时，能够以缩放的方式进行过渡动画：\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n下面我们创建一个图实例并更新元素尺寸来触发更新动画：\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### 原理分析\n\n当对一个元素执行动画时，该元素会将其动画帧参数转化为其各个子图形上的动画帧参数，并执行对应的动画。\n\n在上面的例子中，通过更新节点尺寸(size)，对该节点执行了动画，其动画帧参数为：\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\n节点元素拿到该属性后，将其转化为主图形（圆形）的动画帧参数：\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\n因此这里最终是对圆形执行了半径从 10 到 20 的过渡动画。\n\n#### 复合动画\n\n直接将位置变化动画和尺寸变化动画合并到一个动画范式即可得到复合动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n并同时更新该节点的位置和尺寸：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\n加入颜色过渡：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\n执行节点更新：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n","frontmatter":{"title":"自定义动画","order":"2"},"isInternal":false,"tokens":435,"sizeBytes":2511},{"name":"AutoAdaptLabel.en.md","path":"packages/site/docs/manual/behavior/AutoAdaptLabel.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/AutoAdaptLabel.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: AutoAdaptLabel\norder: 1\n---\n\n## Overview\n\nAuto-adapt label display is a dynamic label management strategy designed to intelligently adjust which labels should be displayed or hidden based on factors such as spatial allocation of the current visible range and node importance. By analyzing the visible area in real-time, it ensures that users receive the most relevant and clear information display in different interaction scenarios, while avoiding visual overload and information redundancy.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Node size changes\n- Graph scaling\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // Throttle time\n      padding: 10, // Extra spacing when detecting overlap\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                      | Type                                                                                                                              | Default            | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- |\n| type      | Interaction type name                                                                                                                                                                                                                                                                            | string                                                                                                                            | `auto-adapt-label` | √        |\n| enable    | Whether to enable this interaction                                                                                                                                                                                                                                                               | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                                                   | true               |          |\n| throttle  | Label update throttle time (ms)                                                                                                                                                                                                                                                                  | number                                                                                                                            | 100                |          |\n| padding   | Extra spacing when detecting label overlap                                                                                                                                                                                                                                                       | number \\| number[]                                                                                                                | 0                  |          |\n| sort      | Custom sorting function, sorting elements from high to low importance, with higher importance elements having higher label display priority. Generally, combo > node > edge                                                                                                                      | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                |                    |          |\n| sortNode  | Sort nodes from high to low importance, with higher importance nodes having higher label display priority. Several built-in [centrality algorithms](#nodecentralityoptions) are available, or a custom sorting function can be used. Note that if `sort` is set, `sortNode` will not take effect | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/en/manual/data#nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |          |\n| sortEdge  | Sort edges from high to low importance, with higher importance edges having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortEdge` will not take effect                                                                  | (edgeA: [EdgeData](/en/manual/data#edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                    |                    |          |\n| sortCombo | Sort groups from high to low importance, with higher importance groups having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortCombo` will not take effect                                                               | (comboA: [ComboData](/en/manual/data#combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |          |\n\n### NodeCentralityOptions\n\nMethods for measuring node centrality\n\n- `'degree'`: Degree centrality, measured by the degree of the node (number of connected edges). Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measured by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measured by the reciprocal of the sum of the shortest path lengths from the node to all other nodes. Nodes with high closeness centrality can usually reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measured by the degree of connection of the node to other central nodes. Nodes with high eigenvector centrality are usually connected to other important nodes\n- `'pagerank'`: PageRank centrality, measured by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to webpage ranking algorithms\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"AutoAdaptLabel","order":"1"},"isInternal":false,"tokens":2139,"sizeBytes":8616},{"name":"AutoAdaptLabel.zh.md","path":"packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 标签自适应显示 AutoAdaptLabel\norder: 1\n---\n\n## 概述\n\n标签自适应显示是一种动态标签管理策略，旨在根据当前可视范围的空间分配、节点重要性等因素，智能调整哪些标签应显示或隐藏。通过对可视区域的实时分析，确保用户在不同的交互场景下获得最相关最清晰的信息展示，同时避免视觉过载和信息冗余。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 节点尺寸变化\n- 图形缩放\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // 节流时间\n      padding: 10, // 检测重叠时的额外间距\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                        | 类型                                                                                                                                   | 默认值             | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ---- |\n| type      | 交互类型名称                                                                                                                                                                                | string                                                                                                                                 | `auto-adapt-label` | √    |\n| enable    | 是否启用该交互                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                                      | true               |      |\n| throttle  | 标签更新节流时间（ms）                                                                                                                                                                      | number                                                                                                                                 | 100                |      |\n| padding   | 标签检测重叠时的额外间距                                                                                                                                                                    | number \\| number[]                                                                                                                     | 0                  |      |\n| sort      | 自定义排序函数，根据元素的重要性从高到低排序，重要性越高的元素其标签显示优先级越高。一般情况下 combo > node > edge                                                                          | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                     |                    |      |\n| sortNode  | 根据节点的重要性从高到低排序，重要性越高的节点其标签显示优先级越高。内置几种[中心性算法](#nodecentralityoptions)，也可以自定义排序函数。需要注意，如果设置了 `sort`，则 `sortNode` 不会生效 | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/manual/data#节点数据nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |      |\n| sortEdge  | 根据边的重要性从高到低排序，重要性越高的边其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortEdge` 不会生效                                               | (edgeA: [EdgeData](/manual/data#边数据edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                      |                    |      |\n| sortCombo | 根据群组的重要性从高到低排序，重要性越高的群组其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortCombo` 不会生效                                          | (comboA: [ComboData](/manual/data#组合数据combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |      |\n\n### NodeCentralityOptions\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"标签自适应显示 AutoAdaptLabel","order":"1"},"isInternal":false,"tokens":1425,"sizeBytes":7574},{"name":"BrushSelect.en.md","path":"packages/site/docs/manual/behavior/BrushSelect.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/BrushSelect.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: BrushSelect\norder: 2\n---\n\n## Overview\n\nBrush select allows users to click and drag a box to enclose elements, selecting the elements within the box.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Quickly selecting a batch of elements\n- Quickly deselecting a batch of elements\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Type                                                                             | Default                   | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | -------- |\n| type           | Interaction type name. This plugin is built-in, and you can use it with `type: 'brush-select'`.                                                                                                                                                                                                                                                                                                                                                                                                                              | `brush-select` \\| string                                                         | `brush-select`            | ✓        |\n| animation      | Whether to enable animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | boolean                                                                          | false                     |          |\n| enable         | Whether to enable brush select functionality                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)  | true                      |          |\n| enableElements | Types of elements that can be selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |          |\n| immediately    | Whether to select immediately, only effective when [selection mode](#mode) is `default`, [example](#immediately)                                                                                                                                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |          |\n| mode           | Selection mode, [example](#mode)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |          |\n| onSelect       | Callback for selected element state                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |          |\n| state          | Switch to this state when selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |          |\n| style          | Specify the style of the selection box, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                  | See below                 |          |\n| trigger        | Press this shortcut key in combination with a mouse click to perform selection **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means selection can be performed with a mouse click without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: [], // No need to press other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nFour selection modes are built-in:\n\n- `union`: Retain the current state of selected elements and add the specified state.\n- `intersect`: If the selected elements already have the specified state, retain it; otherwise, clear the state.\n- `diff`: Invert the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Attribute         | Description               | Type                                     | Default   |\n| ----------------- | ------------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style               | string                                   |           |\n| fill              | Fill color                | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity              | number \\| string                         | 0.1       |\n| isBillboard       | Enable billboard mode     | boolean                                  |           |\n| isSizeAttenuation | Enable size attenuation   | boolean                                  |           |\n| lineCap           | Line end style            | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash configuration        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash offset               | number                                   |           |\n| lineJoin          | Line join style           | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width                | number \\| string                         | 1         |\n| opacity           | Overall opacity           | number \\| string                         |           |\n| radius            | Rectangle corner radius   | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur degree        | number                                   |           |\n| shadowColor       | Shadow color              | string                                   |           |\n| shadowOffsetX     | Shadow X direction offset | number                                   |           |\n| shadowOffsetY     | Shadow Y direction offset | number                                   |           |\n| stroke            | Stroke color              | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity            | number \\| string                         |           |\n| visibility        | Visibility                | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level           | number                                   | 2         |\n\n**Example**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"BrushSelect","order":"2"},"isInternal":false,"tokens":4542,"sizeBytes":18176},{"name":"BrushSelect.zh.md","path":"packages/site/docs/manual/behavior/BrushSelect.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/BrushSelect.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 框选 BrushSelect\norder: 2\n---\n\n## 概述\n\n鼠标点击拖一个框笼罩元素，框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素\n- 快速取消选中一批元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                                                                                                                                                                                                                                                                                                                                            | 类型                                                                             | 默认值                    | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | ---- |\n| type           | 交互类型名称。此插件已内置，你可以通过 `type: 'brush-select'` 来使用它。                                                                                                                                                                                                                                                                                                        | `brush-select` \\| string                                                         | `brush-select`            | ✓    |\n| animation      | 是否启用动画                                                                                                                                                                                                                                                                                                                                                                    | boolean                                                                          | false                     |      |\n| enable         | 是否启用框选功能                                                                                                                                                                                                                                                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                | true                      |      |\n| enableElements | 可框选的元素类型                                                                                                                                                                                                                                                                                                                                                                | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |      |\n| immediately    | 是否及时框选, 仅在 [框选模式 mode](#mode) 为 `default` 时生效，[示例](#immediately)                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |      |\n| mode           | 框选的选择模式，[示例](#mode)                                                                                                                                                                                                                                                                                                                                                   | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |      |\n| onSelect       | 框选元素状态回调                                                                                                                                                                                                                                                                                                                                                                | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |      |\n| state          | 被选中时切换到该状态                                                                                                                                                                                                                                                                                                                                                            | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |      |\n| style          | 指定框选时的框样式，[配置项](#style)                                                                                                                                                                                                                                                                                                                                            |                                                                                  | 见下文                    |      |\n| trigger        | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n内置支持四种框选的选择模式：\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"框选 BrushSelect","order":"2"},"isInternal":false,"tokens":3729,"sizeBytes":16372},{"name":"ClickSelect.en.md","path":"packages/site/docs/manual/behavior/ClickSelect.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ClickSelect.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ClickSelect\norder: 3\n---\n\n## Overview\n\nWhen an element is clicked, it will be highlighted.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Focusing on elements\n- Viewing element details\n- Viewing element relationships\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['click-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // Selection spread range\n      state: 'active', // Selected state\n      neighborState: 'neighborActive', // Neighbor node attached state\n      unselectedState: 'inactive', // Unselected node state\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option          | Description                                                                                                                                                                                                                                                        | Type                                                                            | Default        | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | -------------- | -------- |\n| type            | Behavior type name. This behavior is built-in, and you can use it with `type: 'click-select'`.                                                                                                                                                                     | `click-select` \\| string                                                        | `click-select` | ✓        |\n| animation       | Whether to enable animation effects when switching element states                                                                                                                                                                                                  | boolean                                                                         | true           |          |\n| degree          | Controls the highlight spread range, [example](#degree)                                                                                                                                                                                                            | number \\| (event:[Event](/en/api/event#event-object-properties)) => number      | 0              |          |\n| enable          | Whether to enable the click element function, supports dynamic control through functions, [example](#enable)                                                                                                                                                       | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean) | true           |          |\n| multiple        | Whether to allow multiple selections                                                                                                                                                                                                                               | boolean                                                                         | false          |          |\n| state           | The state applied when an element is selected                                                                                                                                                                                                                      | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| neighborState   | The state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements, [example](#neighborstate)                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| unselectedState | The state applied to all other elements except the selected element and its affected neighbor elements when an element is selected, [example](#unselectedState)                                                                                                    | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        |                |          |\n| onClick         | Callback when an element is clicked                                                                                                                                                                                                                                | (event: [Event](/en/api/event#event-object-properties)) => void                 |                |          |\n| trigger         | Press this shortcut key in combination with a mouse click to perform multi-selection, key reference: _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                        | `['shift']`    |          |\n\n### degree\n\nControls the highlight spread range\n\n- For nodes, `0` means only the current node is selected, `1` means the current node and its directly adjacent nodes and edges are selected, and so on.\n- For edges, `0` means only the current edge is selected, `1` means the current edge and its directly adjacent nodes are selected, and so on.\n\n> In the following example, when `degree: 0` only the <span style='color:#E4504D'>red</span> point is highlighted;\n> When `degree: 1` the <span style='color:#E4504D'>red</span> and <span style='color:#FFC40C'>orange</span> points are highlighted.\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\nWhether to enable the click element function\n\nIt can be dynamically controlled through functions, for example, only enabled when a node is selected.\n\n```js\n{\n  //⚠️ Note, you need to set both the node and the canvas, otherwise the user will not listen to the event when clicking the canvas\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\nSimilarly, if you only want edges to be selected:\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\nThe state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // State attached to the directly clicked node\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\nWhen an element is selected, the state applied to all other elements except the selected element and the spread neighbor elements.\n\nBuilt-in states: `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Example\n\n### Click to select nodes and their directly connected nodes\n\n**Clicking a node** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#0f0'>active</span>\n<br>\n**Adjacent nodes** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // Selected node state\n      active: {\n        fill: '#0f0',\n      },\n      // Adjacent node state\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n      // Unselected node state\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"ClickSelect","order":"3"},"isInternal":false,"tokens":3303,"sizeBytes":13215},{"name":"ClickSelect.zh.md","path":"packages/site/docs/manual/behavior/ClickSelect.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ClickSelect.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 点击选中 ClickSelect\norder: 3\n---\n\n## 概述\n\n当鼠标点击元素时，会使元素高亮。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 聚焦元素\n- 查看元素详情\n- 查看元素关系\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['click-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // 选中扩散范围\n      state: 'active', // 选中的状态\n      neighborState: 'neighborActive', // 相邻节点附着状态\n      unselectedState: 'inactive', // 未选中节点状态\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项          | 说明                                                                                                                                                                                                       | 类型                                                                     | 默认值         | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------- | ---- |\n| type            | 交互类型名称。此交互已内置，你可以通过 `type: 'click-select'` 来使用它。                                                                                                                                   | `click-select` \\| string                                                 | `click-select` | ✓    |\n| animation       | 是否在元素状态切换时启用动画效果                                                                                                                                                                           | boolean                                                                  | true           |      |\n| degree          | 控制了高亮扩散范围，[示例](#degree)                                                                                                                                                                        | number \\| (event:[Event](/api/event#事件对象属性)) => number             | 0              |      |\n| enable          | 是否启用点击元素的功能，支持通过函数的方式动态控制是否启用，[示例](#enable)                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)        | true           |      |\n| multiple        | 是否允许多选                                                                                                                                                                                               | boolean                                                                  | false          |      |\n| state           | 当元素被选中时应用的状态                                                                                                                                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| neighborState   | 当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素，[示例](#neighborstate)                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| unselectedState | 当有元素被选中时，除了选中元素及其受影响的邻居元素外，其他所有元素应用的状态，[示例](#unselectedState)                                                                                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` |                |      |\n| onClick         | 点击元素时的回调                                                                                                                                                                                           | (event: [Event](/api/event#事件对象属性)) => void                        |                |      |\n| trigger         | 按下该快捷键配合鼠标点击进行多选，按键参考： _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                 | `['shift']`    |      |\n\n### degree\n\n控制了高亮扩散范围\n\n- 对于节点来说，`0` 表示只选中当前节点，`1` 表示选中当前节点及其直接相邻的节点和边，以此类推。\n- 对于边来说，`0` 表示只选中当前边，`1` 表示选中当前边及其直接相邻的节点，以此类推。\n\n> 如下示例，当 `degree: 0` 仅高亮<span style='color:#E4504D'>红色</span>点;\n> 当 `degree: 1` 高亮<span style='color:#E4504D'>红色</span>和<span style='color:#FFC40C'>橙色</span>点。\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\n是否启用点击元素的功能\n\n可以通过函数的方式动态控制是否启用，例如只有节点被选中时才启用。\n\n```js\n{\n  //⚠️ 注意，这里需要同时设置节点和画布，否则用户点击画布时将不会监听到事件\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\n同理，如果只希望边能被选中：\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\n当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // 被直接点击的节点附着的状态\n      state: 'active',\n      // 相邻的节点附着的状态\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\n当有元素被选中时，除了被选中元素和扩散的邻居元素外，其他所有元素应用的状态。\n\n内置状态： `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 示例\n\n### 点击选中节点及其直接相连的节点\n\n**点击节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#0f0'>active</span>\n<br>\n**相邻节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // 选中节点状态\n      active: {\n        fill: '#0f0',\n      },\n      // 相邻节点状态\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // 相邻节点附着状态\n      neighborState: 'neighborActive',\n      // 未选中节点状态\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"点击选中 ClickSelect","order":"3"},"isInternal":false,"tokens":2654,"sizeBytes":12280},{"name":"CollapseExpand.en.md","path":"packages/site/docs/manual/behavior/CollapseExpand.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/CollapseExpand.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CollapseExpand\norder: 4\n---\n\n## Overview\n\nCollapseExpand is a built-in behavior in G6 used to implement the expand/collapse functionality for nodes or combos. Through double-click (default) or single-click actions, users can flexibly control the expand and collapse states of graph elements, effectively managing the visualization hierarchy of the graph structure and reducing visual complexity.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Managing large hierarchical graphs, enabling layered browsing of tree or network graphs\n- Simplifying the display of complex graphs, expanding areas of interest as needed\n- Hiding branch nodes that are temporarily not needed, focusing on important information\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates to the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // Change the trigger method to single-click\n      animation: true, // Enable animation effects\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                         | Type                                                                     | Default Value     | Required |\n| ---------- | --------------------------------------------------- | ------------------------------------------------------------------------ | ----------------- | -------- |\n| type       | Behavior type name                                  | `collapse-expand` \\| string                                              | `collapse-expand` | ✓        |\n| animation  | Enable expand/collapse animation effects            | boolean                                                                  | true              |          |\n| enable     | Enable expand/collapse functionality                | boolean \\| ((event: [/en/api/event#event-object-properties]) => boolean) | true              |          |\n| trigger    | Trigger method, can be single-click or double-click | `click` \\| `dblclick`                                                    | `dblclick`        |          |\n| onCollapse | Callback function when collapse is completed        | (id: string) => void                                                     | -                 |          |\n| onExpand   | Callback function when expand is completed          | (id: string) => void                                                     | -                 |          |\n| align      | Align with the target element to avoid view offset  | boolean                                                                  | true              |          |\n\n## Code Examples\n\n### Basic Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // other configurations...\n});\n```\n\n### Use Single-Click to Trigger Expand/Collapse\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // Change the default double-click trigger to single-click\n    },\n  ],\n});\n```\n\n### Custom Expand/Collapse Callback\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`Node ${id} has collapsed`);\n        // Execute custom logic\n      },\n      onExpand: (id) => {\n        console.log(`Node ${id} has expanded`);\n        // Execute custom logic\n      },\n    },\n  ],\n});\n```\n\n### Conditional Enablement of Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // Enable expand/collapse functionality only when the target is a node type\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Disable Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // Disable expand/collapse animation effects\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. How to determine if a node is collapsed?\n\nYou can check the `collapsed` property in the node data:\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. How to programmatically expand or collapse a node?\n\nIn addition to being triggered by user interaction, you can also directly control using [collapseElement](/en/api/element#graphcollapseelementid-options) or [expandElement](/en/api/element#graphexpandelementid-options):\n\n```javascript\n// Collapse node\ngraph.collapseElement('nodeId', { animation: true });\n\n// Expand node\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"CollapseExpand","order":"4"},"isInternal":false,"tokens":1652,"sizeBytes":6626},{"name":"CollapseExpand.zh.md","path":"packages/site/docs/manual/behavior/CollapseExpand.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/CollapseExpand.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 展开/收起元素 CollapseExpand\norder: 4\n---\n\n## 概述\n\nCollapseExpand 是 G6 中用于实现节点或组合（Combo）展开/收起功能的内置交互。通过双击（默认）或单击操作，用户可以灵活控制图元素的展开与收起状态，有效管理图结构的可视化层次，降低视觉复杂度。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 管理大型层次结构图，实现树状图或网络图的分层浏览\n- 简化复杂图的展示，按需展开关注区域\n- 隐藏暂时不需要查看的分支节点，聚焦于重要信息\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一 behavior：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // 修改触发方式为单击\n      animation: true, // 启用动画效果\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                           | 类型                                                                      | 默认值            | 必选 |\n| ---------- | ------------------------------ | ------------------------------------------------------------------------- | ----------------- | ---- |\n| type       | 交互类型名称                   | `collapse-expand` \\| string                                               | `collapse-expand` | ✓    |\n| animation  | 是否启用展开/收起动画效果      | boolean                                                                   | true              |      |\n| enable     | 是否启用展开/收起功能          | boolean \\| ((event: [IPointerEvent](/api/event#事件对象属性)) => boolean) | true              |      |\n| trigger    | 触发方式，可选单击或双击       | `click` \\| `dblclick`                                                     | `dblclick`        |      |\n| onCollapse | 完成收起时的回调函数           | (id: string) => void                                                      | -                 |      |\n| onExpand   | 完成展开时的回调函数           | (id: string) => void                                                      | -                 |      |\n| align      | 是否对准目标元素，避免视图偏移 | boolean                                                                   | true              |      |\n\n## 代码示例\n\n### 基础展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // 其他配置...\n});\n```\n\n### 使用单击触发展开/收起\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // 将默认的双击触发改为单击触发\n    },\n  ],\n});\n```\n\n### 自定义展开/收起回调\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`节点 ${id} 已收起`);\n        // 执行自定义逻辑\n      },\n      onExpand: (id) => {\n        console.log(`节点 ${id} 已展开`);\n        // 执行自定义逻辑\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // 只有当目标是节点类型时才启用展开/收起功能\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 关闭动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // 关闭展开/收起动画效果\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 如何判断一个节点是否处于收起状态？\n\n可以通过检查节点数据中的 `collapsed` 属性：\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. 如何以编程方式展开或收起节点？\n\n除了通过用户交互触发，你还可以使用 [collapseElement](/api/element#graphcollapseelementid-options) 或 [expandElement](/api/element#graphexpandelementid-options) 直接控制：\n\n```javascript\n// 收起节点\ngraph.collapseElement('nodeId', { animation: true });\n\n// 展开节点\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"展开/收起元素 CollapseExpand","order":"4"},"isInternal":false,"tokens":1214,"sizeBytes":6095},{"name":"CreateEdge.en.md","path":"packages/site/docs/manual/behavior/CreateEdge.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/CreateEdge.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CreateEdge\norder: 5\n---\n\n## Overview\n\nCreateEdge is a built-in behavior in G6 for interactively creating edges on the canvas. After the user triggers the behavior (click or drag), the edge will follow the mouse movement and connect to the target node to complete the creation. If canceled, it will be automatically removed.\n\nAdditionally, this behavior supports customizing the style of the edge, such as color, line style, arrow, etc., to meet different visualization needs.\n\nThe elements that can be connected by this behavior are `node` and `combo`.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Visualization scenarios that require interactive creation of connections between nodes, such as flowcharts, knowledge graphs, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration\n\n```javascript\n// Use default configuration\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['create-edge'], // Directly add, use default configuration\n});\n\n// Or use custom configuration\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // Behavior configuration, create edge by clicking\n      style: {}, // Custom edge style\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                 | Type                                                                                                     | Default       | Required |\n| -------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type     | Behavior type name                                                                                          | string                                                                                                   | `create-edge` | √        |\n| trigger  | The way to trigger the creation of a new edge: `click` means click to trigger; `drag` means drag to trigger | `click` \\| `drag`                                                                                        | `drag`        |          |\n| enable   | Whether to enable this behavior                                                                             | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                          | true          |          |\n| onCreate | Callback function for creating an edge, returns edge data                                                   | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => [EdgeData](/en/manual/data#edge-data-edgedata) | -             |          |\n| onFinish | Callback function for successfully creating an edge                                                         | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => void                                           | -             |          |\n| style    | Style of the newly created edge, [configuration options](#style)                                            | See below                                                                                                | -             |          |\n\n### style\n\nConfigure the style of the newly created edge, for detailed configuration options, please refer to [Element - Edge - General Edge Properties - Style](/en/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## Code Examples\n\n### Basic Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### Custom Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  // Other configurations,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: 'red',\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### Create Edge by Clicking\n\n```javascript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"CreateEdge","order":"5"},"isInternal":false,"tokens":1265,"sizeBytes":5060},{"name":"CreateEdge.zh.md","path":"packages/site/docs/manual/behavior/CreateEdge.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/CreateEdge.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 创建边 CreateEdge\norder: 5\n---\n\n## 概述\n\nCreateEdge 是 G6 中用于实现画布中交互式创建边（Edge）的内置交互。用户触发交互（点击或拖拽）后，边会随鼠标移动，连接到目标节点即完成创建，若取消则自动移除。\n\n此外，该交互支持自定义边的样式，如颜色、线条样式、箭头等，以适应不同的可视化需求。\n\n该交互支持连接的元素为 `node` 和 `combo`。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要交互式创建节点间连接关系的可视化场景，如流程图、知识图谱等\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n```javascript\n// 使用默认配置\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['create-edge'], // 直接添加，使用默认配置\n});\n\n// 或使用自定义配置\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // 交互配置，通过点击创建边\n      style: {}, // 边自定义样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                        | 类型                                                                                       | 默认值        | 必选 |\n| -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------- | ---- |\n| type     | 交互类型名称                                                | string                                                                                     | `create-edge` | √    |\n| trigger  | 触发新建边的方式：`click` 表示点击触发；`drag` 表示拖拽触发 | `click` \\| `drag`                                                                          | `drag`        |      |\n| enable   | 是否启用该交互                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                          | true          |      |\n| onCreate | 创建边回调函数，返回边数据                                  | (edge: [EdgeData](/manual/data#边数据edgedata)) => [EdgeData](/manual/data#边数据edgedata) | -             |      |\n| onFinish | 成功创建边回调函数                                          | (edge: [EdgeData](/manual/data#边数据edgedata)) => void                                    | -             |      |\n| style    | 新建边的样式，[配置项](#style)                              | 见下面                                                                                     | -             |      |\n\n### style\n\n配置新创建边的样式，详细配置项请参考 [元素 - 边 - 通用边属性 - 样式](/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## 代码示例\n\n### 基础创建边功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### 自定义创建边功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: red,\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### 使用点击创建边\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"创建边 CreateEdge","order":"5"},"isInternal":false,"tokens":876,"sizeBytes":4319},{"name":"custom-behavior.en.md","path":"packages/site/docs/manual/behavior/custom-behavior.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/custom-behavior.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Behavior\norder: 16\n---\n\n## Overview\n\nCustom behavior allows users to define one or more related interaction behaviors as a complete interaction based on the comprehensive [event mechanism](/en/api/event) provided by G6, thereby achieving interaction logic that fits business scenarios.\n\n### Execution Logic of Behavior\n\nTypically:\n\n1. Listen for user interaction events\n\n2. Update the canvas or perform other operations based on the events\n\nFor example, the `DragCanvas` behavior listens for pointer drag events and updates the camera position based on the drag distance.\n\n### Difference Between Behavior and Plugin\n\n- Both behavior and plugin base classes are derived from the [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) base class within G6, so the implementation methods for behavior and plugin are basically the same.\n- However, based on the concept of visualization, behavior is usually used to handle user interaction events, while plugins are usually used to handle canvas rendering logic, additional component rendering, etc.\n\n:::info{title=Tip}\nDue to conceptual distinctions, behavior instances cannot be obtained, while plugin instances can be obtained ([getPluginInstance](/en/api/plugin#graphgetplugininstancekey)).\n:::\n\n## When to Use Custom Behavior?\n\n- **Purpose**:\n\n  When users need to implement interaction logic that fits business scenarios, we usually need to cooperate with G6's event system to respond to related events and execute the required interaction logic.\n\n- **Without Custom Behavior**:\n\n  If custom behavior is not used, users need to perform a series of event listening and response processing through `graph.on` after creating a Graph instance, making code logic processing and orchestration extremely difficult.\n\n- **Advantages of Behavior**:\n\n  Each behavior is an independent code module, and the existence of the behavior system facilitates users to decouple business logic, avoid code bloat, and facilitate subsequent maintenance.\n\n- **Conclusion**:\n\n  > 1. When users need to implement any interaction logic, they should first consider custom behavior.\n  > 2. When built-in behavior cannot fully meet business needs, users can also adjust and modify through custom behavior (inheriting built-in behavior).\n  >\n  > _(If the features supported by built-in behavior are more general, or if there are bugs in built-in behavior, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Implementing Behavior\n\nThe implementation of a behavior is quite flexible, and you can implement your behavior in your preferred style.\n\nBelow is a simple custom behavior implementation. When the user clicks on the canvas, a node is added to the canvas (the fill color of the added node can be defined through behavior configuration):\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // Unbind events when destroyed\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In the example code, we implemented a `ClickAddNode` behavior, which adds an event listener to the Graph in the constructor. When the user clicks on the canvas, a node is added at the click position, and the fill color of the added node can be configured.\n- `BaseBehavior` is the base class for all behaviors, and each custom behavior needs to inherit this base class.\n\n> Click on the blank area of the canvas below to add a node, and switch the right panel to configure the node color.\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=Tip}\nThe above example is the simplest behavior implementation. In actual development, you may also need to handle logic such as enabling and disabling behaviors.\n\nIn addition, there may be event conflicts between multiple behaviors, and you need to handle these conflicts carefully.\n:::\n\n## Registering Behavior\n\nRegister through the register method provided by G6\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## Configuring Behavior\n\nYou can pass in the behavior type name or configuration parameter object in `behaviors`, such as the above ClickAddNode. See [Configuring Behavior](/en/manual/behavior/overview#配置和使用) for details.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","frontmatter":{"title":"Custom Behavior","order":"16"},"isInternal":false,"tokens":1406,"sizeBytes":5634},{"name":"custom-behavior.zh.md","path":"packages/site/docs/manual/behavior/custom-behavior.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/custom-behavior.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义交互\norder: 16\n---\n\n## 概述\n\n自定义交互允许用户基于 G6 提供的完善的[事件机制](/api/event)，把一个或多个相关的交互行为定义为一个完整的交互，以此实现符合业务场景的交互逻辑。\n\n### 交互的执行逻辑\n\n通常为：\n\n1. 监听用户交互事件\n\n2. 根据事件更新画布或执行其他操作\n\n例如 `DragCanvas` 交互监听指针拖拽事件，根据拖拽的距离更新相机的位置。\n\n### 交互与插件的区别\n\n- 交互和插件的基类都是由 G6 内部的 [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) 基类派生而来，因此交互和插件的实现方式基本相同\n- 但基于可视化的概念区分，交互通常用于处理用户交互事件，而插件通常用于处理画布的渲染逻辑、额外组件渲染等\n\n:::info{title=提示}\n因概念上的区分，交互实例不可获取，插件实例可获取（ [getPluginInstance](/api/plugin#graphgetplugininstancekey) ）\n:::\n\n## 什么时候需要自定义交互？\n\n- **目的**：\n\n  当用户在实现符合业务场景的交互逻辑时，我们通常需要配合 G6 的事件系统，对相关事件作出响应，执行需要的交互逻辑。\n\n- **不使用自定义交互**：\n\n  如果不使用自定义交互，用户需要在创建 Graph 实例后，通过 `graph.on` 进行一系列的事件监听和响应处理，代码逻辑处理和编排会显得异常艰难。\n\n- **交互的优势**：\n\n  每个交互行为都是独立的代码模块，交互系统的存在方便用户解耦业务逻辑、避免代码臃肿以及方便用户后续维护等。\n\n- **结论**：\n\n  > 1、当用户需要实现任何交互逻辑时，应当首先考虑自定义交互。\n  >\n  > 2、当内置交互无法完全满足业务需求时，用户也可以通过自定义交互（继承内置交互）进行调整和修改。\n  >\n  > _（如果需要内置交互支持的特性是较通用的，或者内置交互存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 实现交互\n\n一个交互的实现相当灵活，你可以以你喜欢的风格实现你的交互。\n\n下面是一个简单的自定义交互实现，当用户点击画布时，会在画布上添加一个节点（可通过交互配置定义所添加节点的填充颜色）：\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // 销毁时解绑事件\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在示例代码中，我们实现了一个 `ClickAddNode` 交互，该交互在构造函数中添加了 Graph 的事件监听，当用户点击画布时，会在点击位置添加一个节点，并且支持配置所添加节点的填充颜色。\n- `BaseBehavior` 是所有交互的基类，每个自定义交互都需要继承这个基类实现。\n\n> 点击下面画布中的空白位置以添加一个节点，可切换右侧面板配置节点颜色\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=提示}\n上述示例是一个最简单的交互实现，实际开发过程中，你可能还需要处理交互的启用与禁用等逻辑。\n\n此外，多个交互之间可能会有事件冲突，你需要小心处理这些冲突。\n:::\n\n## 注册交互\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## 配置交互\n\n可在 `behaviors` 中传入交互类型名称或配置参数对象，比如上面的 ClickAddNode ，详见[配置交互](/manual/behavior/overview#配置和使用)\n\n```typescript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n","frontmatter":{"title":"自定义交互","order":"16"},"isInternal":false,"tokens":791,"sizeBytes":5030},{"name":"DragCanvas.en.md","path":"packages/site/docs/manual/behavior/DragCanvas.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragCanvas.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: DragCanvas\norder: 6\n---\n\n## Overview\n\nDragCanvas is a built-in behavior in G6 for implementing canvas dragging functionality, supporting panning the entire canvas by dragging with a mouse or touching the screen. This is the most basic and commonly used navigation behavior in graph visualization, allowing users to freely explore graph content beyond the current viewport.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Navigating and browsing large charts to view content outside the current viewport\n- Adjusting the view focus to move areas of interest to the center of the viewport\n- Combining with zoom interactions to achieve a complete canvas navigation experience\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // Only allow horizontal dragging\n      key: 'drag-behavior', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                          | Type                                                                                                                                                               | Default                                                                                                           | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | -------- |\n| type        | Behavior type name                                                                                                                                                                                                   | string                                                                                                                                                             | `drag-canvas`                                                                                                     | ✓        |\n| enable      | Whether to enable this behavior                                                                                                                                                                                      | boolean \\| ((event: [Event](/en/api/event#event-object-properties) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(Only enabled when clicking on the canvas) |          |\n| animation   | Drag animation configuration, only effective when using keyboard movement                                                                                                                                            | [ViewportAnimationEffectTiming](/en/api/graph#viewportanimationeffecttiming)                                                                                       | -                                                                                                                 |          |\n| direction   | Allowed drag direction, optional values are: <br/>- Set to `'both'` (default): Allow dragging in any direction <br/>- Set to `'x'`: Only allow horizontal dragging <br/>- Set to `'y'`: Only allow vertical dragging | `'x'` \\| `'y'` \\| `'both'`                                                                                                                                         | `'both'` (no direction restriction)                                                                               |          |\n| range       | Draggable viewport range (in viewport size units), [example](#range)                                                                                                                                                 | number \\| number[]                                                                                                                                                 | Infinity                                                                                                          |          |\n| sensitivity | Distance to trigger a single keyboard movement                                                                                                                                                                       | number                                                                                                                                                             | 10                                                                                                                |          |\n| trigger     | Keyboard keys to trigger dragging, [example](#trigger)                                                                                                                                                               | object                                                                                                                                                             | -                                                                                                                 |          |\n| onFinish    | Callback function when dragging is completed                                                                                                                                                                         | () => void                                                                                                                                                         | -                                                                                                                 |          |\n\n### range\n\n`range` is used to control the draggable range of the canvas:\n\n- Set as a single number: Use the same value for all four directions\n- Set as an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can drag 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can drag 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], 0 means no dragging, Infinity means unlimited dragging.\n\n### trigger\n\n`trigger` allows you to configure keyboard keys to control canvas movement:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for moving up\n    down: ['ArrowDown'], // Shortcut key for moving down\n    left: ['ArrowLeft'], // Shortcut key for moving left\n    right: ['ArrowRight'] // Shortcut key for moving right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Dragging Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### Only Allow Horizontal Dragging\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // Only allow horizontal dragging\n    },\n  ],\n});\n```\n\n### Limit Dragging Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // Limit dragging range to 1.5 viewport sizes\n    },\n  ],\n});\n```\n\n### Control Movement with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // Add smooth animation effect\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. Difference between DragCanvas and other behaviors\n\n- `DragCanvas` is used for dragging the entire canvas view\n- `DragElement` is used for dragging individual graph elements (nodes/edges/combinations)\n- `ScrollCanvas` is used for scrolling the canvas with the mouse wheel without changing the zoom ratio\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"DragCanvas","order":"6"},"isInternal":false,"tokens":2514,"sizeBytes":10056},{"name":"DragCanvas.zh.md","path":"packages/site/docs/manual/behavior/DragCanvas.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragCanvas.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 拖拽画布 DragCanvas\norder: 6\n---\n\n## 概述\n\nDragCanvas 是 G6 中用于实现画布拖拽功能的内置交互，支持通过鼠标或触摸屏幕拖动来平移整个画布。这是图可视化中最基础且常用的导航交互，让用户能够自由探索超出当前视口的图内容。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 导航和浏览大型图表，查看当前视口外的内容\n- 调整视图焦点，将感兴趣的区域移动到视口中心\n- 与缩放交互结合，实现完整的画布导航体验\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // 只允许水平方向拖拽\n      key: 'drag-behavior', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                                                                   | 类型                                                                                                                                                 | 默认值                                                                                      | 必选 |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                                                           | string                                                                                                                                               | `drag-canvas`                                                                               | ✓    |\n| enable      | 是否启用该交互                                                                                                                                         | boolean \\| ((event: [Event](/api/event#事件对象属性) \\| [KeyboardEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(仅在点击画布时启用) |      |\n| animation   | 拖拽动画配置，仅在使用按键移动时有效                                                                                                                   | [ViewportAnimationEffectTiming](/api/graph#viewportanimationeffecttiming)                                                                            | -                                                                                           |      |\n| direction   | 允许的拖拽方向，可选值有：<br/>- 设为 `'both'`（默认）：允许在任意方向拖拽 <br/>- 设为 `'x'`：只允许水平方向拖拽 <br/>- 设为 `'y'`：只允许垂直方向拖拽 | `'x'` \\| `'y'` \\| `'both'`                                                                                                                           | `'both'` (不限制方向)                                                                       |      |\n| range       | 可拖拽的视口范围(以视口大小为单位)，[示例](#range)                                                                                                     | number \\| number[]                                                                                                                                   | Infinity                                                                                    |      |\n| sensitivity | 触发一次按键移动的距离                                                                                                                                 | number                                                                                                                                               | 10                                                                                          |      |\n| trigger     | 触发拖拽的键盘按键，[示例](#trigger)                                                                                                                   | object                                                                                                                                               | -                                                                                           |      |\n| onFinish    | 拖拽完成时的回调函数                                                                                                                                   | () => void                                                                                                                                           | -                                                                                           |      |\n\n### range\n\n`range` 用于控制画布可拖拽的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以拖拽2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可拖拽1个视口，左右方向可拖拽2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能拖拽，Infinity表示无限拖拽。\n\n### trigger\n\n`trigger` 允许你配置键盘按键来控制画布移动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上移动的快捷键\n    down: ['ArrowDown'], // 向下移动的快捷键\n    left: ['ArrowLeft'], // 向左移动的快捷键\n    right: ['ArrowRight'] // 向右移动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础拖拽功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### 只允许水平拖拽\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // 只允许水平拖拽\n    },\n  ],\n});\n```\n\n### 限制拖拽范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // 限制拖拽范围为1.5个视口大小\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制移动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // 添加平滑动画效果\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. DragCanvas与其他交互的区别\n\n- `DragCanvas` 用于拖拽整个画布视图\n- `DragElement` 用于拖拽单个图元素（节点/边/组合）\n- `ScrollCanvas` 用于滚轮滚动画布，不改变缩放比例\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"拖拽画布 DragCanvas","order":"6"},"isInternal":false,"tokens":1780,"sizeBytes":8693},{"name":"DragElement.en.md","path":"packages/site/docs/manual/behavior/DragElement.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragElement.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: DragElement\norder: 7\n---\n\n## Overview\n\nDragElement is a built-in behavior in G6 for implementing **element dragging** functionality. It has the following core features:\n\n1. **Support for multiple element types**: Supports dragging of both nodes and combos simultaneously\n2. **Intelligent multi-selection**: Supports dragging multiple selected elements at the same time\n3. **Visual feedback**: Provides various visual feedback mechanisms such as ghost nodes, edge visibility, mouse styles, etc.\n4. **Flexible drag effects**: Supports various drag operation effects such as move, link, free drag, etc.\n5. **Parent-child relationship handling**: Automatically handles element hierarchy during dragging, especially when dealing with combo structures\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // Enable ghost node\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type       | Behavior type name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | `drag-element`                                 | ✓        |\n| key        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| enable     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| animation  | Whether to enable drag animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | boolean                                                  | true                                           |          |\n| 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`                                     |          |\n| dropEffect | Defines the operation effect after dragging ends, optional values are: <br/>- `link`: Set the dragged element as a child of the target element <br/>- `move`: Move the element and automatically update the size of the parent element (such as combo) <br/>- `none`: Only update the position of the drag target without performing other operations                                                                                                                                                           | `link` \\| `move` \\| `none`                               | `move`                                         |          |\n| hideEdge   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |          |\n| shadow     | Whether to enable ghost nodes, which use a shape to follow the mouse movement. [Customize ghost node style](#shadow-style-configuration) ⚠️Note: React nodes do not support enabling                                                                                                                                                                                                                                                                                                                            | boolean                                                  | false                                          |          |\n| cursor     | Customize the mouse style during dragging, [configuration options](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                     | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n### shadow Style Configuration\n\nWhen `shadow: true` is enabled, you can customize the style of the ghost node with the following properties:\n\n| Option               | Description                       | Type                                | Default                                     |\n| -------------------- | --------------------------------- | ----------------------------------- | ------------------------------------------- |\n| shadowFill           | Ghost node fill color             | string                              | `#F3F9FF`                                   |\n| shadowFillOpacity    | Ghost node fill color opacity     | number                              | 0.5                                         |\n| shadowStroke         | Ghost node stroke color           | string                              | `#1890FF`                                   |\n| shadowStrokeOpacity  | Ghost node stroke opacity         | number                              | 0.9                                         |\n| shadowLineDash       | Ghost node dash configuration     | number[]                            | [5, 5]                                      |\n| shadowZIndex         | Ghost node rendering level        | number                              | 100                                         |\n| shadowWidth          | Ghost node width                  | number                              | Width of the target element's bounding box  |\n| shadowHeight         | Ghost node height                 | number                              | Height of the target element's bounding box |\n| shadowOpacity        | Overall opacity of the ghost node | number                              |                                             |\n| shadowLineWidth      | Ghost node line width             | number                              |                                             |\n| shadowLineCap        | Ghost node line cap style         | `'butt'` \\| `'round'` \\| `'square'` |                                             |\n| shadowLineJoin       | Ghost node line join style        | `'miter'` \\| `'round'` \\| `'bevel'` |                                             |\n| shadowLineDashOffset | Ghost node dash offset            | number                              |                                             |\n| shadowCursor         | Ghost node mouse style            | string                              |                                             |\n| shadowVisibility     | Ghost node visibility             | `'visible'` \\| `'hidden'`           |                                             |\n\nExample configuration:\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // Customize ghost node style\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> Note: The ghost node style inherits from [BaseStyleProps](/en/manual/element/shape/properties#baseshapestyle), the above configuration items are obtained by adding the `shadow` prefix to the property name.\n\n## Code Examples\n\n### Multi-selection Dragging\n\nNeed to cooperate with the `click-select` behavior to achieve multi-selection, and then associate the selected state through the `state` parameter:\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // All nodes in the selected state will be moved simultaneously during dragging\n    },\n  ],\n});\n```\n","frontmatter":{"title":"DragElement","order":"7"},"isInternal":false,"tokens":3443,"sizeBytes":13784},{"name":"DragElement.zh.md","path":"packages/site/docs/manual/behavior/DragElement.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragElement.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 拖拽元素 DragElement\norder: 7\n---\n\n## 概述\n\nDragElement 是 G6 中用于实现 **元素拖拽** 功能的内置交互。它具有以下核心特性：\n\n1. **多元素类型支持**：可以同时支持节点（Node）和组合（Combo）的拖拽\n2. **智能多选**：支持同时拖拽多个选中状态的元素\n3. **视觉反馈**：提供幽灵节点、边的显隐、鼠标样式等多种视觉反馈机制\n4. **灵活的拖拽效果**：支持移动、链接、自由拖拽等多种拖拽操作效果\n5. **父子关系处理**：自动处理拖拽过程中的元素层级关系，特别是在处理 Combo 结构时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // 启用拖拽幽灵节点\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type       | 交互类型名称                                                                                                                                                                                                                                                                                                                                            | string                                                   | `drag-element`                                 | ✓    |\n| key        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| enable     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| animation  | 是否启用拖拽动画                                                                                                                                                                                                                                                                                                                                        | boolean                                                  | true                                           |      |\n| state      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| dropEffect | 定义拖拽结束后的操作效果，可选值有：<br/>- `link`: 将拖拽元素设置为目标元素的子元素 <br/>- `move`: 移动元素并自动更新父元素（如 Combo）的尺寸 <br/>- `none`: 仅更新拖拽目标的位置，不执行其他操作                                                                                                                                                       | `link` \\| `move` \\| `none`                               | `move`                                         |      |\n| hideEdge   | 控制拖拽过程中边的显示状态，可选值有： <br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                     | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |      |\n| shadow     | 是否启用幽灵节点，即用一个图形代替节点跟随鼠标移动。[自定义幽灵节点样式](#shadow-样式配置) ⚠️注意：React 节点不支持启用                                                                                                                                                                                                                                 | boolean                                                  | false                                          |      |\n| cursor     | 自定义鼠标样式，[配置项](#cursor)                                                                                                                                                                                                                                                                                                                       | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n### shadow 样式配置\n\n当启用 `shadow: true` 时，可以通过以下属性自定义幽灵节点的样式：\n\n| 配置项               | 说明                   | 类型                                | 默认值               |\n| -------------------- | ---------------------- | ----------------------------------- | -------------------- |\n| shadowFill           | 幽灵节点填充色         | string                              | `#F3F9FF`            |\n| shadowFillOpacity    | 幽灵节点填充色透明度   | number                              | 0.5                  |\n| shadowStroke         | 幽灵节点描边颜色       | string                              | `#1890FF`            |\n| shadowStrokeOpacity  | 幽灵节点描边透明度     | number                              | 0.9                  |\n| shadowLineDash       | 幽灵节点虚线配置       | number[]                            | [5, 5]               |\n| shadowZIndex         | 幽灵节点渲染层级       | number                              | 100                  |\n| shadowWidth          | 幽灵节点宽度           | number                              | 目标元素的包围盒宽度 |\n| shadowHeight         | 幽灵节点高度           | number                              | 目标元素的包围盒高度 |\n| shadowOpacity        | 幽灵节点整体透明度     | number                              |                      |\n| shadowLineWidth      | 幽灵节点线宽度         | number                              |                      |\n| shadowLineCap        | 幽灵节点线段端点样式   | `'butt'` \\| `'round'` \\| `'square'` |                      |\n| shadowLineJoin       | 幽灵节点线段连接处样式 | `'miter'` \\| `'round'` \\| `'bevel'` |                      |\n| shadowLineDashOffset | 幽灵节点虚线偏移量     | number                              |                      |\n| shadowCursor         | 幽灵节点鼠标样式       | string                              |                      |\n| shadowVisibility     | 幽灵节点可见性         | `'visible'` \\| `'hidden'`           |                      |\n\n示例配置：\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // 自定义幽灵节点样式\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> 注意：幽灵节点样式继承自 [BaseStyleProps](/manual/element/shape/properties#baseshapestyle)，上述配置项是在属性名前添加 `shadow` 前缀得到的。\n\n## 代码示例\n\n### 多选推拽\n\n需要配合 `click-select` 行为实现多选，然后通过 `state` 参数关联选中状态：\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // 拖拽时会同时移动所有 selected 状态的节点\n    },\n  ],\n});\n```\n","frontmatter":{"title":"拖拽元素 DragElement","order":"7"},"isInternal":false,"tokens":2341,"sizeBytes":11456},{"name":"DragElementForce.en.md","path":"packages/site/docs/manual/behavior/DragElementForce.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragElementForce.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: DragElementForce\norder: 8\n---\n\n## Overview\n\nDragElementForce 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.\n\n<img alt=\"Effect of DragElementForce\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // Fix node position after dragging\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type                                       | Behavior type name, set `type: 'drag-element-force'` to enable this behavior                                                                                                                                                                                                                                                                                                                                                                                                                                    | string                                                   | `drag-element-force`                           | ✓        |\n| key                                        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| fixed                                      | Whether to keep the node position fixed after dragging ends, boolean values represent: <br/>- true: After dragging ends, the node's position will remain fixed and not be affected by the layout algorithm <br/>- false: After dragging ends, the node's position will continue to be affected by the layout algorithm                                                                                                                                                                                          | boolean                                                  | false                                          |          |\n| enable                                     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| 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`                                     |          |\n| hideEdge                                   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                          |\n| cursor                                     | Customize the mouse style during dragging, [example](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                                   | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger                                    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n## FAQ\n\n### 1. What is the difference between DragElementForce and DragElement?\n\n- `DragElementForce` is specifically used for `d3-force` or `d3-force-3d` layouts, and recalculates the layout in real-time during dragging\n- `DragElement` is a general drag interaction and does not trigger layout recalculation\n\n## Practical Example\n\n### Mesh Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### Fix Dragged Nodes\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Shadow Style\n\n### shadow{[BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#%E7%BB%98%E5%9B%BE%E5%B1%9E%E6%80%A7)}\n\n<details><summary>An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.</summary>\n\nTextStyleProps includes the following properties:\n\n- fill\n- fontSize\n- fontWeight\n- ...\n\nicon{TextStyleProps} means you need to use the following property names:\n\n- iconFill\n- iconFontSize\n- iconFontWeight\n- ...\n\n</details>\n","frontmatter":{"title":"DragElementForce","order":"8"},"isInternal":false,"tokens":3072,"sizeBytes":12297},{"name":"DragElementForce.zh.md","path":"packages/site/docs/manual/behavior/DragElementForce.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/DragElementForce.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 力导向拖拽元素 DragElementForce\norder: 8\n---\n\n## 概述\n\nDragElementForce 是 G6 中用于实现 `d3-force` 和 `d3-force-3d` 布局下节点拖拽的内置交互。在拖拽过程中会 **实时重新计算布局**，使得图的布局能够动态调整以适应节点的新位置。\n\n<img alt=\"力导向拖拽元素效果图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // 拖拽后固定节点位置\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                                     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type                                       | 交互类型名称，这里设置 `type: 'drag-element-force'` 启用此交互                                                                                                                                                                                                                                                                                          | string                                                   | `drag-element-force`                           | ✓    |\n| key                                        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| fixed                                      | 在拖拽结束后，节点是否保持固定位置，布尔值代表：<br/>- true: 在拖拽结束后，节点的位置将保持固定，不受布局算法的影响 <br/>- false: 在拖拽结束后，节点的位置将继续受到布局算法的影响                                                                                                                                                                      | boolean                                                  | false                                          |      |\n| enable                                     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| state                                      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| hideEdge                                   | 控制拖拽过程中边的显示状态，可选值有：<br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                      | `none` \\| `all` \\| `in` \\| `out` \\| `both`                                      | `none`                                                                                                                                                                                                                                                                                                                                                  |                                                          |\n| cursor                                     | 自定义鼠标样式，[示例](#cursor)                                                                                                                                                                                                                                                                                                                         | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger                                    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n## 常见问题\n\n### 1. DragElementForce 和 DragElement 有什么区别？\n\n- `DragElementForce` 专门用于 `d3-force` 或 `d3-force-3d` 布局，拖拽时会实时重新计算布局\n- `DragElement` 是通用的拖拽交互，不会触发布局重新计算\n\n## 实际案例\n\n### 网格效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### 固定被拖拽的节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"力导向拖拽元素 DragElementForce","order":"8"},"isInternal":false,"tokens":2202,"sizeBytes":10199},{"name":"FixElementSize.en.md","path":"packages/site/docs/manual/behavior/FixElementSize.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/FixElementSize.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: FixElementSize\norder: 9\n---\n\n## Overview\n\nFixElementSize is a built-in interaction provided by G6, used to **maintain the size of certain elements within nodes unchanged during the zooming process.** It enhances visual consistency and operability during zooming.\nBy listening to viewport changes, it automatically scales elements marked as \"fixed size\" to ensure they maintain a relatively constant display size at different zoom levels. It supports global enablement and also allows control over specific elements or nodes as needed.\n\n## Use Cases\n\nThis interaction is mainly used for:\n\n- Graphical elements or embedded components (buttons, labels, etc.) that need to maintain a fixed visual size\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // Enable this interaction\n      state: 'selected', // State of elements to fix size\n      reset: true, // Restore style when elements are redrawn\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                    | Type                                                                         | Default                                                                                             | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------- |\n| type        | Interaction type name                                                                                                                                                                                          | string                                                                       | `fix-element-size`                                                                                  | ✓        |\n| enable      | Whether to enable this interaction, [example](#enable)                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean) | true                                                                                                |          |\n| reset       | Whether to restore style when elements are redrawn                                                                                                                                                             | boolean                                                                      | `false`                                                                                             |          |\n| state       | Specify the state of elements to fix size                                                                                                                                                                      | string                                                                       | \"\"                                                                                                  |          |\n| node        | Node configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed, [example](#node)                                     | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| nodeFilter  | Node filter, used to filter which nodes maintain a fixed size during zooming                                                                                                                                   | (datum: [NodeData](/manual/data#nodedata)) => boolean                        | `() => true`                                                                                        |          |\n| edge        | Edge configuration item, used to define which attributes maintain a fixed visual size. By default, the lineWidth and labelFontSize attributes are fixed, usage is the same as [node configuration item](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |          |\n| edgeFilter  | Edge filter, used to filter which edges maintain a fixed size during zooming                                                                                                                                   | (datum: [EdgeData](/manual/data#edgedata)) => boolean                        | `() => true`                                                                                        |          |\n| combo       | Combo configuration item, used to define which attributes maintain a fixed visual size. By default, the entire Combo will be fixed, usage is the same as [node configuration item](#node)                      | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| comboFilter | Combo filter, used to filter which Combos maintain a fixed size during zooming                                                                                                                                 | (datum: [ComboData](/manual/data#combodata)) => boolean                      | `() => true`                                                                                        |          |\n\n### enable\n\nWhether to enable the fixed element size interaction. By default, it is enabled when zooming out the canvas\n\nBy default, it is enabled when zooming out the canvas, set `enable: (event) => event.data.scale < 1`; if you want to enable it when zooming in, set `enable: (event) => event.data.scale > 1`; if you want to enable it when both zooming in and out, set `enable: true`\n\n### node\n\nNode configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed\n\n**Example**\n\nIf you want to fix the lineWidth of the main shape of the node during zooming, you can configure it like this:\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\nIf you want to keep the size of the element label unchanged during zooming, you can configure it like this:\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| Parameter | Description                                                                                                                                                        | Type                                                   | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | ------- | -------- |\n| shape     | Specify the shape to fix size, it can be the class name of the shape, or a function that receives all shapes constituting the element and returns the target shape | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -       | ✓        |\n| fields    | Specify the fields of the shape to fix size. If not specified, the entire shape size is fixed by default                                                           | string[]                                               | -       | ✘        |\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"FixElementSize","order":"9"},"isInternal":false,"tokens":2872,"sizeBytes":11492},{"name":"FixElementSize.zh.md","path":"packages/site/docs/manual/behavior/FixElementSize.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/FixElementSize.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 缩放画布时固定元素大小 FixElementSize\norder: 9\n---\n\n## 概述\n\nFixElementSize 是 G6 提供的一种内置交互，用于在视图缩放过程中，**保持节点中某些元素的尺寸不随缩放变化。** 提升缩放过程中的视觉一致性与可操作性。\n通过监听视口变化，自动对标记为“固定尺寸”的元素进行缩放补偿，确保它们在不同缩放级别下保持相对恒定的显示尺寸。支持全局启用，也支持按需控制具体元素或节点的适配行为。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要固定视觉大小的图形元素或嵌入式组件（按钮、标签等）\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // 开启该交互\n      state: 'selected', // 要固定大小的元素状态\n      reset: true, // 元素重绘时还原样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                              | 类型                                                              | 默认值                                                                                              | 必选 |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                      | string                                                            | `fix-element-size`                                                                                  | √    |\n| enable      | 是否启用该交互，[示例](#enable)                                                                                   | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean) | true                                                                                                |      |\n| reset       | 元素重绘时是否还原样式                                                                                            | boolean                                                           | `false`                                                                                             |      |\n| state       | 指定要固定大小的元素状态                                                                                          | string                                                            | \"\"                                                                                                  |      |\n| node        | 节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定，[示例](#node)   | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| nodeFilter  | 节点过滤器，用于过滤哪些节点在缩放过程中保持固定大小                                                              | (datum: [NodeData](/manual/data#节点数据nodedata)) => boolean     | `() => true`                                                                                        |      |\n| edge        | 边配置项，用于定义哪些属性在视觉上保持固定大小。默认固定 lineWidth、labelFontSize 属性，用法同[node配置项](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |      |\n| edgeFilter  | 边过滤器，用于过滤哪些边在缩放过程中保持固定大小                                                                  | (datum: [EdgeData](/manual/data#边数据edgedata)) => boolean       | `() => true`                                                                                        |      |\n| combo       | Combo 配置项，用于定义哪些属性在视觉上保持固定大小。默认整个 Combo 将被固定，用法同[node配置项](#node)            | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| comboFilter | Combo 过滤器，用于过滤哪些 Combo 在缩放过程中保持固定大小                                                         | (datum: [ComboData](/manual/data#组合数据combodata)) => boolean   | `() => true`                                                                                        |      |\n\n### enable\n\n是否启用固定元素大小交互。默认在缩小画布时启用\n\n默认在缩小画布时启用，设置 `enable: (event) => event.data.scale < 1`；如果希望在放大画布时启用，设置 `enable: (event) => event.data.scale > 1`；如果希望在放大缩小画布时都启用，设置 `enable: true`\n\n### node\n\n节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定\n\n**示例**\n\n如果在缩放过程中希望固定节点主图形的 lineWidth，可以这样配置：\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\n如果在缩放过程中想保持元素标签大小不变，可以这样配置：\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| 参数   | 描述                                                                                                 | 类型                                                   | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------ | ---- |\n| shape  | 指定要固定大小的图形，可以是图形的类名字，或者是一个函数，该函数接收构成元素的所有图形并返回目标图形 | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -      | ✓    |\n| fields | 指定要固定大小的图形属性字段。如果未指定，则默认固定整个图形的大小                                   | string[]                                               | -      | ✘    |\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"缩放画布时固定元素大小 FixElementSize","order":"9"},"isInternal":false,"tokens":2058,"sizeBytes":9966},{"name":"FocusElement.en.md","path":"packages/site/docs/manual/behavior/FocusElement.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/FocusElement.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: FocusElement\norder: 10\n---\n\n## Overview\n\nFocusElement is a built-in behavior in G6 used to implement the element focusing feature, allowing elements to be focused to the center of the view by clicking on them. This behavior helps users quickly locate and focus on specific graph elements.\n\n## Use Cases\n\n- Quickly center the focused nodes or edges in the display\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                                                                                                 | Type                                                            | Default                                | Required |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | -------- |\n| type      | Behavior type name                                                                                                                                                                                                                                                                                                                                                          | string                                                          | `focus-element`                        | ✓        |\n| animation | Focus animation settings                                                                                                                                                                                                                                                                                                                                                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |          |\n| enable    | Whether to enable the focus feature                                                                                                                                                                                                                                                                                                                                         | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |          |\n| trigger   | Press this shortcut key in combination with mouse perform foucs element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | [`shift`]                              |          |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## Code Examples\n\n### Basic Focus Feature\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### Custom Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### Conditional Focus Enablement\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // Enable focus only for nodes, not edges\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"FocusElement","order":"10"},"isInternal":false,"tokens":1437,"sizeBytes":5747},{"name":"FocusElement.zh.md","path":"packages/site/docs/manual/behavior/FocusElement.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/FocusElement.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 聚焦元素 FocusElement\norder: 10\n---\n\n## 概述\n\nFocusElement 是 G6 中用于实现元素聚焦功能的内置交互，支持通过点击元素将其聚焦到视图中心。这个交互可以帮助用户快速定位和关注特定的图元素。\n\n## 使用场景\n\n- 快速将关注的节点或边居中显示\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                                                                                           | 类型                                                            | 默认值                                 | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | ---- |\n| type      | 交互类型名称                                                                                                                                                                                                                                                   | string                                                          | `focus-element`                        | ✓    |\n| animation | 聚焦动画效果设置                                                                                                                                                                                                                                               | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |      |\n| enable    | 是否启用聚焦功能                                                                                                                                                                                                                                               | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |      |\n| trigger   | 同时按下快捷键才能聚焦元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | []                                     |      |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## 代码示例\n\n### 基础聚焦功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### 自定义动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用聚焦\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // 只对节点启用聚焦，边不聚焦\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"聚焦元素 FocusElement","order":"10"},"isInternal":false,"tokens":1087,"sizeBytes":4975},{"name":"HoverActivate.en.md","path":"packages/site/docs/manual/behavior/HoverActivate.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/HoverActivate.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: HoverActivate\norder: 11\n---\n\n## Overview\n\nHoverActivate is a built-in behavior in G6 used to implement the hover activation effect on elements. When the mouse hovers over nodes or edges, it automatically triggers visual feedback such as highlighting and displaying. This behavior is an important means of enhancing data exploration in graph visualization, helping users quickly focus on target elements and obtain related information.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly locating elements of interest in complex relationship graphs\n- Displaying additional information of nodes through hover\n- Highlighting connection paths by activating edges when analyzing relationships between nodes\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option        | Description                                 | Type                                           | Default          | Required |\n| ------------- | ------------------------------------------- | ---------------------------------------------- | ---------------- | -------- |\n| type          | Behavior type name                          | string                                         | `hover-activate` | ✓        |\n| animation     | Whether to enable animation                 | boolean                                        | true             |          |\n| enable        | Whether to enable hover feature             | boolean \\| ((event: IPointerEvent) => boolean) | true             |          |\n| degree        | Degree of relationship to activate elements | number \\| ((event: IPointerEvent) => number);  | 0                |          |\n| direction     | Specify edge direction                      | `both` \\| `in` \\| `out`                        | `both`           |          |\n| state         | State of activated elements                 | string                                         | `active`         |          |\n| inactiveState | State of inactive elements                  | string                                         | -                |          |\n| onHover       | Callback when element is hovered            | (event: IPointerEvent) => void                 | -                |          |\n| onHoverEnd    | Callback when hover ends                    | (event: IPointerEvent) => void                 | -                |          |\n\n### enable\n\n`enable` is used to control whether to enable hover highlighting of elements, and can receive a function for dynamic control\n\nFor example: Enable hover highlighting only for nodes\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hover Usage\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n### Node Trigger Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### Flowchart Node Hover Next Node Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"HoverActivate","order":"11"},"isInternal":false,"tokens":1299,"sizeBytes":5195},{"name":"HoverActivate.zh.md","path":"packages/site/docs/manual/behavior/HoverActivate.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/HoverActivate.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 悬停激活 HoverActivate\norder: 11\n---\n\n## 概述\n\nHoverActivate 是 G6 中用于实现元素悬停激活效果的内置交互，当鼠标悬停在节点或边上时，会自动触发高亮、显示等视觉反馈。该交互是图可视化中增强数据探索的重要手段，有助于用户快速聚焦目标元素并获取相关信息。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 在复杂关系图中快速定位关注元素\n- 通过悬停信息展示节点额外信息\n- 分析节点间关联关系时，通过激活边凸显连接路径\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项        | 说明                 | 类型                                           | 默认值           | 必选 |\n| ------------- | -------------------- | ---------------------------------------------- | ---------------- | ---- |\n| type          | 交互类型名称         | string                                         | `hover-activate` | ✓    |\n| animation     | 是否开启动画效果     | boolean                                        | true             |      |\n| enable        | 是否开启悬浮元素功能 | boolean \\| ((event: IPointerEvent) => boolean) | true             |      |\n| degree        | 激活元素的n度关系    | number \\| ((event: IPointerEvent) => number);  | 0                |      |\n| direction     | 指定边方向           | `both` \\| `in` \\| `out`                        | `both`           |      |\n| state         | 激活元素的状态       | string                                         | `active`         |      |\n| inactiveState | 不激活元素的状态     | string                                         | -                |      |\n| onHover       | 当元素被悬停时的回调 | (event: IPointerEvent) => void                 | -                |      |\n| onHoverEnd    | 当悬停结束时的回调   | (event: IPointerEvent) => void                 | -                |      |\n\n### enable\n\n`enable` 用于控制是否开启元素的悬浮高亮，可接收一个函数来动态控制\n\n例如：只有节点开启悬浮高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础悬浮用法\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n### 节点触发高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### 流程图移入节点 下一步节点高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"悬停激活 HoverActivate","order":"11"},"isInternal":false,"tokens":919,"sizeBytes":4614},{"name":"LassoSelect.en.md","path":"packages/site/docs/manual/behavior/LassoSelect.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/LassoSelect.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: LassoSelect\norder: 12\n---\n\n## Overview\n\nClick and drag the mouse to draw an **irregular** box to enclose elements, and the elements within the selected range will be selected.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly selecting a batch of elements, making it easier to avoid elements you don't want to select\n- Quickly deselecting a batch of elements, making it easier to avoid elements you want to keep\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                      | Description                                                                                                                                                                                                                               | Type                                                                                                                           | Default                   | Required |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | -------- |\n| type                        | Behavior type name. This plugin is built-in, you can use it by `type: 'lasso-select'`.                                                                                                                                                    | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓        |\n| animation                   | Whether to enable animation                                                                                                                                                                                                               | boolean                                                                                                                        | false                     |          |\n| enable                      | Whether to enable lasso selection                                                                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean)                                                   | true                      |          |\n| enableElements              | Types of elements that can be selected                                                                                                                                                                                                    | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |          |\n| [immediately](#immediately) | Whether to select immediately, only effective when [selection mode](#mode) is `default`                                                                                                                                                   | boolean                                                                                                                        | false                     |          |\n| [mode](#mode)               | Selection mode                                                                                                                                                                                                                            | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |          |\n| onSelect                    | Callback for selected element state                                                                                                                                                                                                       | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |          |\n| state                       | State to switch to when selected                                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |          |\n| [style](#style)             | Style of the box during selection                                                                                                                                                                                                         | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [Default](#style)         |          |\n| trigger                     | Press this shortcut key along with mouse click to select **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: [], // No need for other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nSelection mode\n\n- `union`: Keep the current state of selected elements and add the specified state.\n- `intersect`: Retain the specified state if the selected elements already have it; otherwise, clear the state.\n- `diff`: Toggle the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Property          | Description             | Type                                     | Default   |\n| ----------------- | ----------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style             | string                                   |           |\n| fill              | Fill color              | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity            | number \\| string                         | 0.1       |\n| isBillboard       | Billboard mode          | boolean                                  |           |\n| isSizeAttenuation | Size attenuation        | boolean                                  |           |\n| lineCap           | Line cap style          | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash line config        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash line offset        | number                                   |           |\n| lineJoin          | Line join style         | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width              | number \\| string                         | 1         |\n| opacity           | Overall opacity         | number \\| string                         |           |\n| radius            | Rectangle corner radius | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur level       | number                                   |           |\n| shadowColor       | Shadow color            | string                                   |           |\n| shadowOffsetX     | Shadow X offset         | number                                   |           |\n| shadowOffsetY     | Shadow Y offset         | number                                   |           |\n| stroke            | Stroke color            | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity          | number \\| string                         |           |\n| visibility        | Visibility              | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level         | number                                   | 2         |\n\n**Example**:\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\nPress this shortcut key along with mouse click to select, if set to an **empty array**, it means mouse click to select without needing to press other keys.\n\nNote that setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to be disabled. They cannot be configured simultaneously.\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"LassoSelect","order":"12"},"isInternal":false,"tokens":3986,"sizeBytes":15946},{"name":"LassoSelect.zh.md","path":"packages/site/docs/manual/behavior/LassoSelect.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/LassoSelect.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 套索选择 LassoSelect\norder: 12\n---\n\n## 概述\n\n鼠标点击拖出一个 **不规则的** 框框笼罩元素，精准框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素，并且更容易的避开不想选的元素\n- 快速取消选中一批元素，并且更容易的避开想保留的元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                      | 说明                                                                                                                                                                                                          | 类型                                                                                                                           | 默认值                    | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---- |\n| type                        | 交互类型名称。此插件已内置，你可以通过 `type: 'lasso-select'` 来使用它。                                                                                                                                      | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓    |\n| animation                   | 是否启用动画                                                                                                                                                                                                  | boolean                                                                                                                        | false                     |      |\n| enable                      | 是否启用框选功能                                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                              | true                      |      |\n| enableElements              | 可框选的元素类型                                                                                                                                                                                              | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |      |\n| [immediately](#immediately) | 是否及时框选, 仅在[框选模式 mode](#mode)为 `default` 时生效                                                                                                                                                   | boolean                                                                                                                        | false                     |      |\n| [mode](#mode)               | 框选的选择模式                                                                                                                                                                                                | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |      |\n| onSelect                    | 框选元素状态回调                                                                                                                                                                                              | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |      |\n| state                       | 被选中时切换到该状态                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |      |\n| [style](#style)             | 框选时的 框样式                                                                                                                                                                                               | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [默认值](#style)          |      |\n| trigger                     | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n框选的选择模式\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\n按下该快捷键配合鼠标点击进行框选，若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合。\n\n注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"套索选择 LassoSelect","order":"12"},"isInternal":false,"tokens":3479,"sizeBytes":15443},{"name":"OptimizeViewportTransform.en.md","path":"packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: OptimizeViewportTransform\norder: 13\n---\n\n## Overview\n\nOptimizeViewportTransform is a built-in behavior in G6 used to enhance the performance of large-scale graph behaviors.\n\nThis behavior implements a **selective rendering strategy**, temporarily hiding non-critical visual elements during viewport transformations (such as dragging, zooming, scrolling, etc.) to significantly reduce rendering computation load, improve frame rate, and response speed. After the viewport transformation operation ends, the system automatically restores the visibility of all elements after a set delay to ensure complete visual presentation.\n\nThis behavior is implemented based on the [event system](/en/api/event) by listening to the `GraphEvent.BEFORE_TRANSFORM` and `GraphEvent.AFTER_TRANSFORM` events, precisely capturing the start and end timing of viewport transformations, and dynamically controlling element visibility. Therefore, it must be used in conjunction with viewport operation behaviors (such as `drag-canvas`, `zoom-canvas`, or `scroll-canvas`) to be effective.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Smooth behavior of large-scale graphs (thousands of nodes/edges)\n- Performance-sensitive application scenarios\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // Specify an identifier for the behavior for dynamic updates\n      debounce: 300, // Set a longer debounce time\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                          | Type                                   | Default                       | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | -------- |\n| type     | Behavior type name                                                                                                   | string                                 | `optimize-viewport-transform` | ✓        |\n| enable   | Whether to enable this behavior                                                                                      | boolean \\| ((event: Event) => boolean) | true                          |          |\n| debounce | How long after the operation ends to restore the visibility of all elements (milliseconds)                           | number                                 | 200                           |          |\n| shapes   | Specify the graphical elements that should remain visible during canvas operations, [configuration options](#shapes) | function                               | `(type) => type === 'node'`   |          |\n\n### Shapes\n\n`shapes` is used to specify the graphical elements that need to remain visible during canvas operations. By default, nodes are always visible, while edges and combos are temporarily hidden during canvas operations to improve performance.\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // Dynamically decide whether to remain visible based on element type and graphical object\n    if (type === 'node') return true; // All nodes remain visible\n    if (type === 'edge' && shape.get('importante')) return true; // Important edges remain visible\n    return false; // Other graphics are hidden\n  };\n}\n```\n\n[Example](#keep-specific-elements-visible)\n\n## Code Examples\n\n### Basic Optimization Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### Custom Debounce Time\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // Set a longer debounce time, restoring visibility of all elements 0.5 seconds after the operation stops\n    },\n  ],\n});\n```\n\n### Keep Specific Elements Visible\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 Try dragging the canvas to see the effect\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Enable/Disable Optimization Based on Graph Element Count\n\nYou can dynamically decide whether to enable optimization based on the number of graph elements:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // Enable optimization when exceeding 500 elements\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. When should this behavior be used?\n\nWhen the graph contains a large number of nodes and edges (usually more than 500 elements), using this behavior can significantly improve operational smoothness. It is especially useful in environments with high performance requirements or limited hardware performance.\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"OptimizeViewportTransform","order":"13"},"isInternal":false,"tokens":1841,"sizeBytes":7367},{"name":"OptimizeViewportTransform.zh.md","path":"packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 优化视口变换 OptimizeViewportTransform\norder: 13\n---\n\n## 概述\n\nOptimizeViewportTransform 是 G6 中用于提升大规模图表交互性能的内置交互。\n\n该交互通过实现**选择性渲染策略**，在视口变换过程中（即用户进行拖拽、缩放、滚动等操作时）临时隐藏非关键视觉元素，从而显著降低渲染计算负载，提高帧率和响应速度。当视口变换操作结束后，系统会在设定的延迟时间后自动恢复所有元素的可见性，确保完整的视觉呈现。\n\n此交互基于 [事件系统](/api/event) 实现，通过监听 `GraphEvent.BEFORE_TRANSFORM` 和 `GraphEvent.AFTER_TRANSFORM` 事件，精确捕捉视口变换的开始和结束时机，进而执行元素可见性的动态控制。因此，必须与视口操作类交互（如 `drag-canvas`、`zoom-canvas` 或 `scroll-canvas`）配合使用才能发挥作用。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 大规模图表（上千节点/边）的流畅交互\n- 性能敏感的应用场景\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // 为交互指定标识符，方便动态更新\n      debounce: 300, // 设置更长的防抖时间\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                          | 类型                                   | 默认值                        | 必选 |\n| -------- | ------------------------------------------------------------- | -------------------------------------- | ----------------------------- | ---- |\n| type     | 交互类型名称                                                  | string                                 | `optimize-viewport-transform` | ✓    |\n| enable   | 是否启用该交互                                                | boolean \\| ((event: Event) => boolean) | true                          |      |\n| debounce | 操作结束后多长时间恢复显示所有元素（毫秒）                    | number                                 | 200                           |      |\n| shapes   | 指定在操作画布过程中始终保持可见的图形元素，[配置项](#shapes) | function                               | `(type) => type === 'node'`   |      |\n\n### Shapes\n\n`shapes` 用于指定在画布操作过程中需要保持可见的图形元素。默认情况下，节点始终可见，而边和组合在操作画布时会被临时隐藏以提升性能。\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // 根据元素类型和图形对象动态决定是否保持可见\n    if (type === 'node') return true; // 所有节点保持可见\n    if (type === 'edge' && shape.get('importante')) return true; // 重要的边保持可见\n    return false; // 其他图形隐藏\n  };\n}\n```\n\n[示例](#保持特定元素可见)\n\n## 代码示例\n\n### 基础优化功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### 自定义防抖时间\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // 设置更长的防抖时间，在操作停止后0.5秒才恢复显示所有元素\n    },\n  ],\n});\n```\n\n### 保持特定元素可见\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 试试拖拽一下画布，看看效果吧\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 根据图表元素数量动态启用/禁用优化\n\n可以根据图表元素数量动态决定是否启用优化：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // 超出500个元素时启用优化\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 什么情况下应该使用此交互？\n\n当图表包含大量节点和边（通常超过500个元素）时，使用此交互可以显著提升操作流畅度。在性能要求高或硬件性能有限的环境中尤其有用。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"优化视口变换 OptimizeViewportTransform","order":"13"},"isInternal":false,"tokens":1219,"sizeBytes":6478},{"name":"overview.en.md","path":"packages/site/docs/manual/behavior/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/overview.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Behavior Overview\norder: 0\n---\n\n## What is Behavior\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nBehavior refers to the interactive operations between users and chart elements, such as dragging the canvas, selecting nodes, zooming the view, etc. Good behavior design allows users to explore and understand graph data more intuitively. **Proper configuration of behaviors is a key step in building efficient and usable charts**.\n\n### Changes in G6 5.0 Behavior System\n\nG6 5.0 removed the concept of \"Behavior Mode\" (Mode), and directly lists the required behavior behaviors in `behaviors`, simplifying the configuration. This makes behavior configuration more intuitive and easier to get started with.\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## Built-in Behaviors\n\nG6 provides a variety of built-in behaviors that are **ready to use without registration**:\n\n| Category            | Behavior Name                                                                  | Registration Type             | Function Description                                         |\n| ------------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------------------------------ |\n| Navigation          |                                                                                |                               |                                                              |\n|                     | [Drag Canvas](/en/manual/behavior/drag-canvas)                                 | `drag-canvas`                 | Drag the entire canvas view                                  |\n|                     | [Zoom Canvas](/en/manual/behavior/zoom-canvas)                                 | `zoom-canvas`                 | Zoom the canvas view                                         |\n|                     | [Scroll Canvas](/en/manual/behavior/scroll-canvas)                             | `scroll-canvas`               | Scroll the canvas using the wheel                            |\n|                     | [Optimize Viewport Transform](/en/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | Optimize view transform performance                          |\n| Selection           |                                                                                |                               |                                                              |\n|                     | [Click Select](/en/manual/behavior/click-select)                               | `click-select`                | Click to select graph elements                               |\n|                     | [Brush Select](/en/manual/behavior/brush-select)                               | `brush-select`                | Select elements by dragging a rectangular area               |\n|                     | [Lasso Select](/en/manual/behavior/lasso-select)                               | `lasso-select`                | Freely draw an area to select elements                       |\n| Editing             |                                                                                |                               |                                                              |\n|                     | [Create Edge](/en/manual/behavior/create-edge)                                 | `create-edge`                 | Interactively create new edges                               |\n|                     | [Drag Element](/en/manual/behavior/drag-element)                               | `drag-element`                | Drag nodes or combos                                         |\n|                     | [Force-directed Drag](/en/manual/behavior/drag-element-force)                  | `drag-element-force`          | Drag nodes in force-directed layout                          |\n| Data Exploration    |                                                                                |                               |                                                              |\n|                     | [Collapse/Expand](/en/manual/behavior/collapse-expand)                         | `collapse-expand`             | Expand or collapse subtree nodes                             |\n|                     | [Focus Element](/en/manual/behavior/focus-element)                             | `focus-element`               | Focus on specific elements and automatically adjust the view |\n|                     | [Hover Activate](/en/manual/behavior/hover-activate)                           | `hover-activate`              | Highlight elements when hovering                             |\n| Visual Optimization |                                                                                |                               |                                                              |\n|                     | [Fix Element Size](/en/manual/behavior/fix-element-size)                       | `fix-element-size`            | Fix the element size to a specified value                    |\n|                     | [Auto-adapt Label](/en/manual/behavior/auto-adapt-label)                       | `auto-adapt-label`            | Automatically adjust label position                          |\n\nFor detailed configuration of each behavior, refer to the [Built-in Behavior Documentation](/en/manual/behavior/drag-canvas).\n\n:::warning{title=Behavior Compatibility}\nSome behaviors may overlap in triggering mechanisms, such as `brush-select` and `drag-canvas` both using mouse dragging. In such cases, you can avoid conflicts by modifying the trigger key (e.g., hold `Shift` to drag and select).\n:::\n\n## Custom Behaviors\n\nWhen built-in behaviors cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend by inheriting built-in behaviors\n- Create entirely new behavior behaviors\n\nUnlike built-in behaviors, **custom behaviors need to be registered before use**. For detailed tutorials, refer to the [Custom Behavior](/en/manual/behavior/custom-behavior) documentation.\n\n## Configuration and Usage\n\n### Basic Configuration\n\nThe simplest way is to directly specify the required behaviors through the `behaviors` array when initializing the graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### Configure Behavior Parameters\n\nFor behaviors that require custom parameters, you can configure properties using the `object` form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // Configure sensitivity\n      key: 'zoom-behavior', // Specify a key for the behavior for subsequent updates\n    },\n  ],\n});\n```\n\n### Dynamically Update Behaviors\n\nG6 supports dynamically managing behavior behaviors during the runtime of the graph instance to meet complex behavior needs:\n\nYou can adjust behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method:\n\n```javascript\n// Add new behavior\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// Remove behavior\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\nYou can update the configuration of behaviors using the [updateBehavior](/en/api/behavior#graphupdatebehaviorbehavior) method:\n\n```javascript\n// Update a single behavior\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // Disable the behavior\n});\n```\n\n:::warning{title=Note}\nWhen using the `updateBehavior` method, you need to specify a unique `key` for the behavior during initialization.\n:::\n\n### Uninstall Behaviors\n\nYou can also uninstall behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method by setting the behavior configuration list to empty:\n\n```javascript\ngraph.setBehaviors([]);\n```\n\nFor more behavior-related APIs, refer to the [Behavior API Documentation](/en/api/behavior).\n\n## Behavior and Events\n\nBehaviors are essentially implemented through event listening and response. Although built-in behaviors have encapsulated common behavior behaviors, you can also directly implement custom behavior logic through the event API.\n\n### Event Listening Example\n\n```javascript\n// Use event constants (recommended)\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// Listen for node clicks\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen for edge hover\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\nThe event system is the foundation for implementing behaviors. Mastering the event API is crucial for understanding and extending behavior behaviors. For more event-related information, refer to the [Event Documentation](/en/api/event).\n","frontmatter":{"title":"Behavior Overview","order":"0"},"isInternal":false,"tokens":2289,"sizeBytes":9153},{"name":"overview.zh.md","path":"packages/site/docs/manual/behavior/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/overview.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 交互总览\norder: 0\n---\n\n## 什么是交互\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n交互(Behavior)是指用户与图表元素之间的互动操作，如拖拽画布、选择节点、缩放视图等。良好的交互设计能让用户更直观地探索和理解图数据。**合理配置交互是构建高效可用图表的关键环节**。\n\n### G6 5.0 交互系统变化\n\nG6 5.0 移除了 \"交互模式\"(Mode) 概念，直接在 `behaviors` 中列出需要的交互行为，简化了配置方式。这使得交互配置更加直观，上手更加简单。\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## 内置交互\n\nG6 提供了多种开箱即用的内置交互，**无需注册，直接配置即可使用**：\n\n| 分类     | 交互名称                                                     | 注册类型                      | 功能描述                   |\n| -------- | ------------------------------------------------------------ | ----------------------------- | -------------------------- |\n| 导航     |                                                              |                               |                            |\n|          | [拖拽画布](/manual/behavior/drag-canvas)                     | `drag-canvas`                 | 拖动整个画布视图           |\n|          | [缩放画布](/manual/behavior/zoom-canvas)                     | `zoom-canvas`                 | 缩放画布视图               |\n|          | [滚动画布](/manual/behavior/scroll-canvas)                   | `scroll-canvas`               | 使用滚轮滚动画布           |\n|          | [优化视口变换](/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | 优化视图变换性能           |\n| 选择     |                                                              |                               |                            |\n|          | [点击选择](/manual/behavior/click-select)                    | `click-select`                | 点击选择图元素             |\n|          | [框选](/manual/behavior/brush-select)                        | `brush-select`                | 通过拖拽矩形区域选择元素   |\n|          | [套索选择](/manual/behavior/lasso-select)                    | `lasso-select`                | 自由绘制区域选择元素       |\n| 编辑     |                                                              |                               |                            |\n|          | [创建边](/manual/behavior/create-edge)                       | `create-edge`                 | 交互式创建新的边           |\n|          | [拖拽元素](/manual/behavior/drag-element)                    | `drag-element`                | 拖动节点或组合             |\n|          | [力导向拖拽](/manual/behavior/drag-element-force)            | `drag-element-force`          | 力导向布局中拖动节点       |\n| 数据探索 |                                                              |                               |                            |\n|          | [折叠/展开](/manual/behavior/collapse-expand)                | `collapse-expand`             | 展开或收起子树节点         |\n|          | [聚焦元素](/manual/behavior/focus-element)                   | `focus-element`               | 聚焦特定元素，自动调整视图 |\n|          | [悬停激活](/manual/behavior/hover-activate)                  | `hover-activate`              | 鼠标悬停时高亮元素         |\n| 视觉优化 |                                                              |                               |                            |\n|          | [固定元素大小](/manual/behavior/fix-element-size)            | `fix-element-size`            | 将元素大小固定为指定值     |\n|          | [自适应标签](/manual/behavior/auto-adapt-label)              | `auto-adapt-label`            | 自动调整标签位置           |\n\n各交互的详细配置可参考 [内置交互文档](/manual/behavior/drag-canvas)。\n\n:::warning{title=交互兼容性}\n某些交互在触发机制上可能存在重叠，如 `brush-select` 和 `drag-canvas` 都使用鼠标拖拽。这种情况下可以通过修改触发按键（如按住 `Shift` 拖拽选择）来避免冲突。\n:::\n\n## 自定义交互\n\n当内置交互无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置交互进行扩展\n- 创建全新的交互行为\n\n与内置交互不同，**自定义交互需要先注册后使用**。详细教程请参考 [自定义交互](/manual/behavior/custom-behavior) 文档。\n\n## 配置和使用\n\n### 基本配置\n\n最简单的方式是在图实例初始化时，通过 `behaviors` 数组直接指定需要的交互：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### 配置交互参数\n\n对于需要自定义参数的交互，可以使用 `object` 的形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // 配置灵敏度\n      key: 'zoom-behavior', // 为交互指定key，便于后续更新\n    },\n  ],\n});\n```\n\n### 动态更新交互\n\nG6 支持在图实例运行期间动态管理交互行为，满足复杂交互需求：\n\n可以通过 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法调整交互：\n\n```javascript\n// 添加新交互\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// 移除交互\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\n可以使用 [updateBehavior](/api/behavior#graphupdatebehaviorbehavior) 方法更新交互的配置：\n\n```javascript\n// 更新单个交互\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // 禁用该交互\n});\n```\n\n:::warning{title=注意}\n使用`updateBehavior`方法时，需要在初始化时为交互指定唯一的`key`。\n:::\n\n### 卸载交互\n\n使用 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法同样可以卸载交互，将交互配置列表置为空即可：\n\n```javascript\ngraph.setBehaviors([]);\n```\n\n更多与交互相关的 API 请参考 [交互 API 文档](/api/behavior)。\n\n## 交互与事件\n\n交互本质上是通过事件监听和响应来实现的。虽然内置交互已经封装了常见的交互行为，但你也可以通过事件 API 直接实现自定义交互逻辑。\n\n### 事件监听示例\n\n```javascript\n// 使用事件常量（推荐）\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// 监听节点点击\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边悬停\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\n事件系统是实现交互的基础，掌握事件 API 对于理解和扩展交互行为至关重要。更多事件相关信息，请参考 [事件文档](/api/event)。\n","frontmatter":{"title":"交互总览","order":"0"},"isInternal":false,"tokens":1349,"sizeBytes":7309},{"name":"ScrollCanvas.en.md","path":"packages/site/docs/manual/behavior/ScrollCanvas.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ScrollCanvas.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ScrollCanvas\norder: 14\n---\n\n## Overview\n\nScrollCanvas is a built-in behavior in G6 used to implement the canvas scrolling feature, supporting panning the canvas using the mouse wheel or keyboard arrow keys. This interaction is particularly useful for browsing larger charts, allowing users to explore different areas of the chart without changing the zoom level.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large chart content that exceeds the visible area\n- Exploring different parts of the graph while maintaining the current zoom level\n- Precisely adjusting the view position, especially when precise scrolling is needed in one-dimensional directions\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n      direction: 'y', // Allow only vertical scrolling\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                         | Type                                                                                                                                                                                          | Default                          | Required |\n| -------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------- |\n| type           | Behavior type name                                                                  | string                                                                                                                                                                                        | `scroll-canvas`                  | ✓        |\n| enable         | Whether to enable this behavior                                                     | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                             |          |\n| direction      | Allowed scrolling direction, [configuration options](#direction)                    | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (no direction limit) |          |\n| range          | Scrollable viewport range (in viewport size units), [configuration options](#range) | number \\| number[]                                                                                                                                                                            | 1                                |          |\n| sensitivity    | Scrolling sensitivity, the larger the value, the faster the scrolling               | number                                                                                                                                                                                        | 1                                |          |\n| trigger        | Keyboard shortcuts to trigger scrolling, [configuration options](#trigger)          | object                                                                                                                                                                                        | -                                |          |\n| onFinish       | Callback function when scrolling is finished                                        | () => void                                                                                                                                                                                    | -                                |          |\n| preventDefault | Whether to prevent the browser's default event                                      | boolean                                                                                                                                                                                       | true                             |          |\n\n### Direction\n\n`direction` is used to limit the scrolling direction:\n\n- Not set or set to `undefined`: Allow scrolling in any direction\n- Set to `'x'`: Allow only horizontal scrolling\n- Set to `'y'`: Allow only vertical scrolling\n\nThis is useful in specific visualization scenarios, such as in timeline charts where only horizontal scrolling may be needed.\n\n### Range\n\n`range` is used to control the scrollable range of the canvas:\n\n- Set to a single number: Use the same value for all four directions\n- Set to an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can scroll 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can scroll 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], where 0 means no scrolling, and Infinity means unlimited scrolling.\n\n### Trigger\n\n`trigger` allows you to configure keyboard arrow keys to control canvas scrolling:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for scrolling up\n    down: ['ArrowDown'], // Shortcut key for scrolling down\n    left: ['ArrowLeft'], // Shortcut key for scrolling left\n    right: ['ArrowRight'] // Shortcut key for scrolling right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Scrolling Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### Allow Only Horizontal Scrolling\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // Allow only horizontal scrolling\n    },\n  ],\n});\n```\n\n### Custom Scrolling Sensitivity and Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // Increase scrolling sensitivity\n      range: [0.5, 2, 0.5, 2], // Smaller limits up and down, larger limits left and right\n    },\n  ],\n});\n```\n\n### Control Scrolling with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What is the difference between ScrollCanvas and ZoomCanvas?\n\n- `ScrollCanvas` is used to pan the canvas without changing the zoom level\n- `ZoomCanvas` is used to zoom the canvas, changing the view's zoom level\n\nThey are often used together to provide complete canvas navigation functionality:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"ScrollCanvas","order":"14"},"isInternal":false,"tokens":2208,"sizeBytes":8832},{"name":"ScrollCanvas.zh.md","path":"packages/site/docs/manual/behavior/ScrollCanvas.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ScrollCanvas.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 滚动画布 ScrollCanvas\norder: 14\n---\n\n## 概述\n\nScrollCanvas 是 G6 中用于实现画布滚动功能的内置交互，支持通过鼠标滚轮或键盘方向键平移画布。这种交互方式对于浏览较大的图表特别有用，能让用户在不改变缩放比例的情况下探索图表的不同区域。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览超出可视区域的大型图表内容\n- 在保持当前缩放比例的情况下探索图的不同部分\n- 精确调整查看位置，尤其是在一维方向上需要精确滚动时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n      direction: 'y', // 只允许垂直方向滚动\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                 | 类型                                                                                                                                                                                          | 默认值                   | 必选 |\n| -------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ---- |\n| type           | 交互类型名称                                         | string                                                                                                                                                                                        | `scroll-canvas`          | ✓    |\n| enable         | 是否启用该交互                                       | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                     |      |\n| direction      | 允许的滚动方向，[配置项](#direction)                 | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (不限制方向) |      |\n| range          | 可滚动的视口范围(以视口大小为单位)，[配置项](#range) | number \\| number[]                                                                                                                                                                            | 1                        |      |\n| sensitivity    | 滚动灵敏度，值越大滚动速度越快                       | number                                                                                                                                                                                        | 1                        |      |\n| trigger        | 触发滚动的键盘快捷键，[配置项](#trigger)             | object                                                                                                                                                                                        | -                        |      |\n| onFinish       | 滚动完成时的回调函数                                 | () => void                                                                                                                                                                                    | -                        |      |\n| preventDefault | 是否阻止浏览器默认事件                               | boolean                                                                                                                                                                                       | true                     |      |\n\n### Direction\n\n`direction` 用于限制滚动的方向：\n\n- 不设置或设为 `undefined`：允许在任意方向滚动\n- 设为 `'x'`：只允许水平方向滚动\n- 设为 `'y'`：只允许垂直方向滚动\n\n这在特定的可视化场景下很有用，例如在时间轴图表中可能只需要水平滚动。\n\n### Range\n\n`range` 用于控制画布可滚动的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以滚动2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可滚动1个视口，左右方向可滚动2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能滚动，Infinity表示无限滚动。\n\n### Trigger\n\n`trigger` 允许你配置键盘方向键来控制画布滚动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上滚动的快捷键\n    down: ['ArrowDown'], // 向下滚动的快捷键\n    left: ['ArrowLeft'], // 向左滚动的快捷键\n    right: ['ArrowRight'] // 向右滚动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础滚动功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### 只允许水平滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // 只允许水平滚动\n    },\n  ],\n});\n```\n\n### 自定义滚动灵敏度和范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // 提高滚动灵敏度\n      range: [0.5, 2, 0.5, 2], // 上下方向限制较小，左右方向限制较大\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. ScrollCanvas 和 ZoomCanvas 有什么区别？\n\n- `ScrollCanvas` 用于平移画布，不改变缩放比例\n- `ZoomCanvas` 用于缩放画布，改变视图的缩放比例\n\n两者常结合使用，提供完整的画布导航功能：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"滚动画布 ScrollCanvas","order":"14"},"isInternal":false,"tokens":1568,"sizeBytes":7964},{"name":"ZoomCanvas.en.md","path":"packages/site/docs/manual/behavior/ZoomCanvas.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ZoomCanvas.en.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ZoomCanvas\nordeR: 15\n---\n\n## Overview\n\nZoomCanvas is a built-in behavior in G6 used to implement the canvas zooming feature, supporting zooming in and out of the canvas using the mouse wheel or keyboard shortcuts. This is one of the most commonly used interactions in graph visualization, helping users view both the overall structure and local details of the graph.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large-scale graph data, freely switching between the whole and details\n- Focusing on specific areas for detailed analysis\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                            | Type                                                                                | Default             | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------------- | -------- |\n| type           | Behavior type name                                                                                     | string                                                                              | `zoom-canvas`       | ✓        |\n| animation      | Zoom animation effect settings                                                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |          |\n| enable         | Whether to enable this behavior                                                                        | boolean \\| ((event: Event) => boolean)                                              | true                |          |\n| origin         | Zoom center point (viewport coordinates)                                                               | [Point](/api/viewport#point)                                                        | -                   |          |\n| onFinish       | Callback function when zooming is finished                                                             | () => void                                                                          | -                   |          |\n| preventDefault | Whether to prevent the browser's default event                                                         | boolean                                                                             | true                |          |\n| sensitivity    | Zoom sensitivity, the larger the value, the faster the zoom                                            | number                                                                              | 1                   |          |\n| trigger        | How to trigger zooming, supports mouse wheel and keyboard shortcuts, [configuration options](#trigger) | string[] \\| object                                                                  | -                   |          |\n\n### Trigger\n\n`trigger` has two usage methods, suitable for different scenarios:\n\n#### Method 1: Modifier keys combined with the mouse wheel\n\nIf you want to trigger zooming only when certain keys are pressed while scrolling the mouse wheel, you can configure it like this:\n\n```javascript\n{\n  trigger: ['Control']; // Hold down the Control key and scroll the mouse wheel to zoom\n}\n```\n\nCommon modifier keys include:\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> Not sure what value corresponds to a keyboard key? Refer to [MDN Key Values](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).\n\n#### Method 2: Pure keyboard shortcuts\n\nIf you want to control zooming entirely using the keyboard, you can set up key combinations:\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // Zoom in shortcut\n    zoomOut: ['Control', '-'], // Zoom out shortcut\n    reset: ['Control', '0']    // Reset zoom ratio shortcut\n  }\n}\n```\n\n## Code Examples\n\n### Basic Zoom Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### Custom Zoom Center\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n### Custom Zoom Sensitivity\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n    },\n  ],\n});\n```\n\n### Zoom with Shift + Mouse Wheel\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // Hold down the Shift key and scroll to zoom\n    },\n  ],\n});\n```\n\n### Control Zoom with Keyboard Shortcuts\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = to zoom in\n        zoomOut: ['Control', '-'], // Ctrl + - to zoom out\n        reset: ['Control', '0'], // Ctrl + 0 to reset\n      },\n    },\n  ],\n});\n```\n\n### Supports pinch-to-zoom on mobile devices\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // Other configurations for the PC side...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What if the canvas zoom exceeds the expected range?\n\nTo avoid excessive zooming in or out, you can set zoom limits:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  zoomRange: [0.5, 3], // Allow zooming out to 50% and zooming in to 300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. How to use it with other interactions?\n\nZooming and dragging are common combinations for a complete navigation experience:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. Conflicts when using two-finger touchpad input and scroll-canvas simultaneously\n\nOn a touchpad, both two-finger swipe (for scrolling) and pinch (for zooming) gestures are often interpreted as `wheel` events.\n\nBecause both `zoom-canvas` and `scroll-canvas` respond to `wheel` events by default, using them together can cause conflicts, such as a single gesture triggering both scrolling and zooming.\n\nYou can resolve this by checking the `event.ctrlKey` property. On most platforms, a pinch gesture sets `event.ctrlKey` to `true`, while a swipe does not. This allows you to conditionally enable `zoom-canvas` only for pinch gestures.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // When ctrlKey is true, it performs a two-finger pinch or spread operation; when false, it performs a two-finger swipe operation.\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"ZoomCanvas","ordeR":"15"},"isInternal":false,"tokens":2265,"sizeBytes":9069},{"name":"ZoomCanvas.zh.md","path":"packages/site/docs/manual/behavior/ZoomCanvas.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/behavior/ZoomCanvas.zh.md","title":"Behavior Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 缩放画布 ZoomCanvas\nordeR: 15\n---\n\n## 概述\n\nZoomCanvas 是 G6 中用于实现画布缩放功能的内置交互，支持通过鼠标滚轮或键盘快捷键调整画布缩放比例。这是图可视化中最常用的交互之一，能帮助用户查看图的整体结构和局部细节。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览大规模图数据，在整体与细节之间自由切换\n- 聚焦到特定区域进行详细分析\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                     | 类型                                                                                | 默认值              | 必选 |\n| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------- | ---- |\n| type           | 交互类型名称                                             | string                                                                              | `zoom-canvas`       | ✓    |\n| animation      | 缩放动画效果设置                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |      |\n| enable         | 是否启用该交互                                           | boolean \\| ((event: Event) => boolean)                                              | true                |      |\n| origin         | 缩放中心点(视口坐标)                                     | [Point](/api/viewport#point)                                                        | -                   |      |\n| onFinish       | 缩放完成时的回调函数                                     | () => void                                                                          | -                   |      |\n| preventDefault | 是否阻止浏览器默认事件                                   | boolean                                                                             | true                |      |\n| sensitivity    | 缩放灵敏度，值越大缩放速度越快                           | number                                                                              | 1                   |      |\n| trigger        | 触发缩放的方式，支持滚轮和键盘快捷键，[配置项](#trigger) | string[] \\| object                                                                  | -                   |      |\n\n### Trigger\n\n`trigger`有两种使用方式，分别适用于不同场景：\n\n#### 方式一：与滚轮结合的修饰键\n\n当你希望只有在按下某些键的同时滚动滚轮才触发缩放时，可以这样配置：\n\n```javascript\n{\n  trigger: ['Control']; // 按住 Control 键同时滚动鼠标滚轮才能缩放\n}\n```\n\n常见的修饰键有：\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> 不知道键盘按键对应什么值？请参考 [MDN Key Values](https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values)。\n\n#### 方式二：纯键盘快捷键\n\n当你希望完全使用键盘控制缩放操作时，可以设置组合键：\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // 放大快捷键\n    zoomOut: ['Control', '-'], // 缩小快捷键\n    reset: ['Control', '0']    // 重置缩放比例快捷键\n  }\n}\n```\n\n## 代码示例\n\n### 基础缩放功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 自定义缩放中心\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n### 自定义缩放灵敏度\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n    },\n  ],\n});\n```\n\n### 使用Shift+滚轮进行缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // 按住 Shift 键同时滚动才能缩放\n    },\n  ],\n});\n```\n\n### 使用键盘快捷键控制缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = 放大\n        zoomOut: ['Control', '-'], // Ctrl + - 缩小\n        reset: ['Control', '0'], // Ctrl + 0 重置\n      },\n    },\n  ],\n});\n```\n\n### 支持移动端双指缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // PC 端其他配置...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 画布缩放超出了预期范围怎么办？\n\n为避免缩放过大或过小，可以设置缩放限制：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  zoomRange: [0.5, 3], // 允许缩小到50%和放大到300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. 如何与其他交互结合使用？\n\n缩放与拖拽是常见的组合，实现完整的导航体验：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. 触控板双指操作下，与 scroll-canvas 同时使用时的冲突\n\n在触控板上，双指滑动（用于滚动）和双指捏合（用于缩放）手势通常都会被解析为 `wheel` 事件。\n\n由于 `zoom-canvas` 和 `scroll-canvas` 默认都会响应 `wheel` 事件，当它们同时使用时会产生冲突，例如一个手势会同时触发滚动和缩放。\n\n你可以通过检查 `event.ctrlKey` 属性来解决这个问题。在多数平台上，捏合手势会使 `event.ctrlKey` 为 `true`，而滑动则不会。这允许你有条件地仅为捏合手势启用 `zoom-canvas`。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // ctrlKey 为 true 时，是双指捏合或扩张操作，false 时是双指滑动操作\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"缩放画布 ZoomCanvas","ordeR":"15"},"isInternal":false,"tokens":1559,"sizeBytes":8124},{"name":"contribute.en.md","path":"packages/site/docs/manual/contribute.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/contribute.en.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: contribute\norder: 14\n---\n\nTo contribute, you need to understand G6's code structure and development workflow. The code repository for G6 is located at: https://github.com/antvis/G6\n\nIf you want to fix a bug or add a new feature, you need to first fork a copy of the code to your repository, then make modifications in your repository, and finally submit a Pull Request (PR) to the G6 repository.\n\n## Project Structure\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 Core Implementation</small>\n          <ul>\n            <li>\n              __tests__\n              <small>Testing and Development Environment</small>\n              <ul>\n                <li>\n                  assets\n                  <small>Test Static Resources</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bugfix Test Case</small>\n                </li>\n                <li>\n                  dataset\n                  <small>Test Dataset</small>\n                </li>\n                <li>\n                  demos\n                  <small>Development Demos</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>Test Snapshots</small>\n                </li>\n                <li>\n                  perf\n                  <small>Performance Test Case</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>Performance Test Reports</small>\n                </li>\n                <li>\n                  unit\n                  <small>Test Cases</small>\n                </li>\n                <li>\n                  utils\n                  <small>Test Utility Functions</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>Animation Executors and Built-in Animations</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>Built-in Interactions</small>   \n                </li>\n                <li>\n                  constants\n                  <small>Constants and Enumeration Values</small>   \n                </li>\n                <li>\n                  elements\n                  <small>Built-in Elements</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>Built-in Combos</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>Built-in Edges</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>Built-in Nodes</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>Composite Shapes</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>Layout References and Encapsulation</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>Built-in Palettes</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>Built-in Plugins</small>   \n                </li>\n                <li>\n                  registry\n                  <small>Registry Module</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph and Core Controller</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification Type Definitions</small>   \n                </li>\n                <li>\n                  themes\n                  <small>Built-in Themes</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>Built-in Data Transformations</small>   \n                </li>\n                <li>\n                  types\n                  <small>Type Definitions</small>   \n                </li>\n                <li>\n                  utils\n                  <small>Utility Functions</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>Export Items</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>Pre-operations</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>Development Environment Vite Configuration</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D Extension</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D Behaviors</small>\n            </li>\n            <li>\n              elements\n              <small>3D Elements</small>\n            </li>\n            <li>\n              plugins\n              <small>3D Plugins</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D Renderer</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React Node Extension</small>\n          <ul>\n            <li>\n              elements\n              <small>React Elements</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph Encapsulation</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>Official Website and Documentation</small>\n          <ul>\n            <li>\n              docs\n              <small>Tutorials and API</small>\n            </li>\n            <li>\n              examples\n              <small>Graph Examples</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>Configuration File</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## Development Process\n\n1. Fork and Pull the Code\n\nFork the G6 repository on Github to your account, then clone it locally.\n\n```bash\n# Navigate to your workspace\ncd /path/to/your/workspace\n\n# Navigate to the G6 directory\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. Install Dependencies\n\n:::warning{title=Warning}\nPlease ensure your local environment meets the following requirements:\n\n- [Node.js](https://nodejs.org/) version >= 18\n- [pnpm](https://pnpm.io/) version >= 8\n\n:::\n\n```bash\n# Enter the G6 code directory\ncd G6\n\n# Install Dependencies\npnpm install\n```\n\n3. Start the Development Environment\n\n```bash\n# Enter the g6 code directory.\ncd ./packages/g6\n\n# Start the development environment\npnpm dev\n```\n\nAt this point, you can access G6's development environment and preview the examples by visiting http://127.0.0.1:8080 in your web browser.\n\n4. Develop New Features or Fix Bugs\n\nSwitch to a development branch:\n\n```bash\ngit checkout -b [branch name]\n```\n\nMake code modifications according to your needs and test locally.\n\n5. Write Test Cases\n\nIn the `packages/g6/__tests__/unit` directory, write test cases to ensure your code behaves as expected.\n\nValidate Your Code with Tests：\n\n```bash\npnpm test\n```\n\n6. Submit a Pull Request (PR)\n\n```bash\n# Stage changes\ngit add .\n\n# Commit Changes\ngit commit -m \"[commit type]: commit message\"\n\n# Push to Your Repository\ngit push\n```\n\nSubmit a Pull Request (PR) to the G6 repository on GitHub.\n\n## Testing and Coverage\n\nG6 utilizes Jest for conducting unit tests, with the test cases situated in the `packages/g6/__tests__/unit` directory.\n\nWe require that all code submissions must pass tests to ensure code quality.\n\nThe coverage rate for the current PR (Pull Request) submission is advised not to fall below the coverage rate of the existing codebase, and it is <text style=\"color: red;\">not to fall below 90%</text>.\n\n### Update Test Snapshots\n\nG6 extends Jest tests and provides the `toMatchSnapshot` assertion for generating and comparing snapshots.\n\nIf the current possible modification affects the generation of some screenshots, it is necessary to check whether there are failed test cases by executing `pnpm test`.\n\nWhen a failed test case is found, the console will print the path of the failed test, as well as the path information of the benchmark screenshot and the current screenshot. You can hold the `Ctrl` or `Command` key and click the path to view the specific test case or screenshot.\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\nIf it is confirmed that this modification is correct, then please manually delete the corresponding benchmark screenshots and regenerate the screenshots:\n\n**Regenerate all screenshots**:\n\n1. Delete all files in the `packages/g6/__tests__/unit/snapshots` directory\n2. Execute `pnpm test`\n\n**Regenerate a single screenshot**:\n\n1. Delete the corresponding file in the `packages/g6/__tests__/snapshots` directory (test cases in the `unit` directory will generate the corresponding directory under `snapshots`)\n2. Execute `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## Code Standards\n\nThe G6 code adheres to the following standards:\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## Commit Conventions\n\nG6 adopts the [Conventional Commits](https://www.conventionalcommits.org/) specification, and the commit message format is as follows:\n\n```\n<type>[optional scope]: <description>\n```\n\nThe type field can be one of the following:\n\n- feat: A new feature\n- fix: A bug fix\n- docs: Documentation update\n- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)\n- refactor: Code change that neither fixes a bug nor adds a feature\n- perf: A code change that improves performance\n- test: Adding missing or correcting existing tests\n- build: Changes that affect the build system or external dependencies\n- ci: Changes to our CI configuration files and scripts\n- chore: Other changes that don't modify src or test files\n- revert: Reverts a previous commit\n\nFor example:\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\nPlease ensure that your commit messages conform to the standards, and try to use English descriptions whenever possible. This helps us better manage the code.\n\n## Pull Request (PR) Standards\n\nAfter completing the above steps, you can submit a PR to the G6 repository. Please ensure that your PR adheres to the following standards:\n\n- A single PR should address only one issue.\n- The title of the PR should be concise and clear.\n- The description of the PR should be clear and detailed. If the changes involve the user interface, please include screenshots.\n- The PR must pass CI (Continuous Integration) checks.\n\n## Code Review\n\nAfter your PR is submitted, we will review your code. Please be patient and await the results of the review. If there are any areas that require modification, we will point them out within the PR.\n\n## Release Process\n\nWe regularly release new versions. If your PR is for a non-urgent bug fix, it will be included in the next release. If your PR addresses an urgent bug fix, we will release a new version as soon as possible.\n\nThis project uses changeset to manage version release, and the specific release process is as follows:\n\n1. Complete related development work\n2. Create a branch from v5 (any name you want)\n3. Run `npm run version` command, fill in the information according to the prompt, and the version number will be updated automatically\n4. Commit the changes to the remote repository\n5. Create a PR on GitHub, add the `publish` label, and merge the branch to v5\n6. After the branch is merged, GitHub Actions will be triggered automatically, and the package will be published to npm\n7. After the release, the Release note needs to be updated. Execute \"pnpm tag\" in the packages/g6\n8. Fill in the tag information on the newly opened Github link. First, select the previous tag, and then select the current tag to obtain the changes. After confirming that there are no issues, release it.\n","frontmatter":{"title":"contribute","order":"14"},"isInternal":false,"tokens":3049,"sizeBytes":12197},{"name":"contribute.zh.md","path":"packages/site/docs/manual/contribute.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/contribute.zh.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 参与贡献\norder: 14\n---\n\n要参与贡献，你需要了解 G6 的代码结构和开发流程。G6 的代码仓库地址是：https://github.com/antvis/G6\n\n如果你想要修复一个 bug 或者增加一个新功能，你需要先 fork 一份代码到你的仓库，然后在你的仓库中进行修改，最后提交 PR 到 G6 的仓库。\n\n## 项目结构\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 核心实现</small>\n          <ul>\n            <li>\n              __tests__\n              <small>测试及开发环境</small>\n              <ul>\n                <li>\n                  assets\n                  <small>测试静态资源</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bug 修复测试用例</small>\n                </li>\n                <li>\n                  dataset\n                  <small>测试数据集</small>\n                </li>\n                <li>\n                  demos\n                  <small>开发示例</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>测试截图</small>\n                </li>\n                <li>\n                  perf\n                  <small>性能测试用例</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>性能测试报告</small>\n                </li>\n                <li>\n                  unit\n                  <small>测试用例</small>\n                </li>\n                <li>\n                  utils\n                  <small>测试工具函数</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>动画执行器及内置动画</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>内置交互</small>   \n                </li>\n                <li>\n                  constants\n                  <small>常量及枚举值</small>   \n                </li>\n                <li>\n                  elements\n                  <small>内置元素</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>内置组合</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>内置边</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>内置节点</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>复合图形</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>布局引用及封装</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>内置色板</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>内置插件</small>   \n                </li>\n                <li>\n                  registry\n                  <small>注册模块</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph 及核心控制器</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification 类型定义</small>   \n                </li>\n                <li>\n                  themes\n                  <small>内置主题</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>内置数据转换</small>   \n                </li>\n                <li>\n                  types\n                  <small>类型定义</small>   \n                </li>\n                <li>\n                  utils\n                  <small>工具函数</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>导出项</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>预操作</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>开发环境 Vite 配置</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D 扩展</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D 交互</small>\n            </li>\n            <li>\n              elements\n              <small>3D 元素</small>\n            </li>\n            <li>\n              plugins\n              <small>3D 插件</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D 渲染器</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React 节点扩展</small>\n          <ul>\n            <li>\n              elements\n              <small>React 元素</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph 封装</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>官网及文档</small>\n          <ul>\n            <li>\n              docs\n              <small>教程及 API</small>\n            </li>\n            <li>\n              examples\n              <small>图表示例</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>配置文件</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## 开发流程\n\n1. Fork 并拉取代码\n\n在 Github 中 Fork [G6](https://github.com/antvis/G6) 到你的仓库，并拉取到本地。\n\n```bash\n# 进入你的工作目录\ncd /path/to/your/workspace\n\n# 克隆 G6 代码\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. 安装依赖\n\n:::warning{title=注意}\n请验证你的本地环境是否符合要求：\n\n- [Node.js](https://nodejs.org/) 版本 >= 18\n- [pnpm](https://pnpm.io/) 版本 >= 8\n\n:::\n\n```bash\n# 进入 G6 代码目录\ncd G6\n\n# 安装依赖\npnpm install\n```\n\n3. 启动开发环境\n\n```bash\n# 进入 G6 代码目录\ncd ./packages/g6\n\n# 启动开发环境\npnpm dev\n```\n\n此时，你可以在浏览器中访问 `http://127.0.0.1:8080` 查看 G6 的开发环境并预览开发示例。\n\n4. 开发新功能或修复 bug\n\n切换到开发分支：\n\n```bash\ngit checkout -b [branch name]\n```\n\n根据你的需求，修改代码并在本地测试。\n\n5. 编写测试用例\n\n在 `packages/g6/__tests__/unit` 目录下编写测试用例，确保你的代码符合预期。\n\n确保你的代码通过测试：\n\n```bash\npnpm test\n```\n\n6. 提交 PR\n\n```bash\n# 添加修改\ngit add .\n\n# 提交修改\ngit commit -m \"[commit type]: commit message\"\n\n# 推送到你的仓库\ngit push\n```\n\n在 Github 中提交 PR 到 G6 仓库。\n\n## 测试与覆盖率\n\nG6 使用 Jest 进行单元测试，测试用例位于 `packages/g6/__tests__/unit` 目录下。\n\n我们要求所有的代码提交都需要通过测试，确保代码质量。\n\n当前 PR 提交的覆盖率不建议低于当前代码库的覆盖率，且<text style=\"color: red;\">不得低于 90%</text>。\n\n### 更新测试截图\n\nG6 扩展了 Jest 测试，提供了 `toMatchSnapshot` 断言用于生成以及对比快照。\n\n如果当前可能修改影响了部分截图的生成，需要通过执行 `pnpm test` 检查是否有测试用例失败。\n\n当发现测试失败的用例时，控制台会打印出失败的测试路径，以及基准截图和当前截图的路径信息。你可以按住 `Ctrl` 或 `Command` 键并点击路径，查看具体的测试用例或截图。\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\n如果确认本次修改是正确的，那么请手动删除对应的基准截图，并重新生成截图：\n\n**重新生成全部截图**：\n\n1. 删除 `packages/g6/__tests__/unit/snapshots` 目录下的所有文件\n2. 执行 `pnpm test`\n\n**重新生成单个截图**：\n\n1. 删除 `packages/g6/__tests__/snapshots` 目录下对应的文件（`unit`目录下测试用例会在`snapshots`下生成对应的目录）\n2. 执行 `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## 代码规范\n\nG6 编码尊循以下规范：\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## 提交规范\n\nG6 采用 [Conventional Commits](https://www.conventionalcommits.org/) 规范，提交信息格式如下：\n\n```\n<type>[optional scope]: <description>\n```\n\ntype 有以下几种：\n\n- feat: 新功能\n- fix: 修复 bug\n- docs: 文档更新\n- style: 代码格式（不影响代码运行的变动）\n- refactor: 重构\n- perf: 性能优化\n- test: 测试\n- build: 构建工具相关的变动\n- ci: CI 配置\n- chore: 其他无关紧要的变动\n- revert: 撤销\n\n例如：\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\n请确保你的提交信息符合规范，并尽量使用英文描述，这样有助于我们更好地管理代码。\n\n## PR 规范\n\n完成上述步骤后，你可以提交 PR 到 G6 仓库。请确保你的 PR 符合以下规范：\n\n- 一个 PR 只解决一个问题\n- PR 的标题简洁明了\n- PR 的描述清晰详细，涉及视图的变动请附上截图\n- PR 必需能够通过 CI 检查\n\n## 代码 Review\n\nPR 提交后，我们会对你的代码进行 Review。请耐心等待 Review 结果，如果有需要修改的地方，我们会在 PR 中提出。\n\n## 发布流程\n\n我们会定期发布新版本，如果你的 PR 是非紧急缺陷修复，我们会在下一个版本中发布。如果你的 PR 是紧急缺陷修复，我们会尽快发布新版本。\n\n本项目通过 changeset 来管理版本发布，具体的发布流程如下：\n\n1. 完成相关的开发工作\n2. 从 v5 分支创建一个分支（任意分支名均可）\n3. 根目录执行 `npm run version` 命令，根据提示填写相关信息，会自动更新版本号\n4. 将变更提交到远程仓库\n5. 在 GitHub 上创建一个 PR，并添加 `publish` 标签，将该分支合并到 v5 分支\n6. 分支合并后，会自动触发 GitHub Actions，发布到 npm\n7. 发布后，需更新 Release note，在 packages/g6 目录下执行 pnpm tag\n8. 在新打开的 Github 链接填写 tag 信息，先选择前一个 tag, 然后选择当前 tag 后得到变更，确认没有问题后发布\n","frontmatter":{"title":"参与贡献","order":"14"},"isInternal":false,"tokens":2004,"sizeBytes":10628},{"name":"data.en.md","path":"packages/site/docs/manual/data.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/data.en.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Data\norder: 1\n---\n\n## Overview\n\nG6 is a data-driven charting library, where data is one of the most important concepts. In G6, data is the core of the chart, and both display and interaction are based on data.\n\nCommon graph data formats include:CSV, [DOT](https://graphviz.org/doc/info/lang.html), GDF, GML, [GraphML](http://graphml.graphdrawing.org/), [GEXF](https://gexf.net/) etc。\n\nG6 uses JSON format to describe the graph structure, which includes information about nodes and edges. Here is a simple JSON data example:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\" }, { \"id\": \"node2\" }],\n  \"edges\": [{ \"source\": \"node1\", \"target\": \"node2\" }]\n}\n```\n\nCompared to the other formats mentioned above, the JSON format has a more intuitive and understandable data structure. It is also more flexible, allowing for easy expansion of node and edge attributes.\n\nIt is a data exchange format widely supported by computers, so you do not have to worry about data format compatibility issues.\n\n## Data Structure\n\nIn G6, graph data consists of three parts: `nodes` (node data), `edges` (edge data), and `combos` (combo data). Each part corresponds to different elements in the graph, and their types and data determine how the graph is displayed.\n\n```ts\ninterface GraphData {\n  nodes: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data (optional)\n  combos?: ComboData[]; // Combo data (optional)\n}\n```\n\n### Node Data\n\nA node is the basic building block of a graph and represents an entity within the graph. Each node has a unique `id` used to identify it, and nodes can also have data, styles, and states.\n\n| Attribute                                 | Type               | Description                                                                                                        |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the node, used to distinguish different nodes                                                |\n| type                                      | _string_           | Node type. It can be the type of built-in Node, or the custom Node                                                 |\n| data                                      | _Object_           | Custom data for the node, such as name, description, etc. Can be accessed in style mappings via callback functions |\n| style                                     | _Object_           | Node style, including position, size, color, and other visual properties                                           |\n| states                                    | _string[]_         | Initial states for the node, such as selected, active, hover, etc.                                                 |\n| combo                                     | _string_ \\| _null_ | ID of the combo the node belongs to. Used to organize hierarchical relationships. If none, it is null              |\n| children                                  | _string[]_         | Collection of child node IDs, used only in tree diagrams                                                           |\n\n**Example:**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### Edge Data\n\nAn edge connects nodes and represents the relationship between them. Each edge is associated with two nodes (source and target), and edges themselves can have data, styles, and states. Edge data is often used to represent logical relationships, such as user connections in social networks or step flows in flowcharts.\n\n| Attribute                                     | Type       | Description                                                                                                             |\n| --------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |\n| <Badge type=\"success\">Required</Badge> source | _string_   | Source node ID                                                                                                          |\n| <Badge type=\"success\">Required</Badge> target | _string_   | Target node ID                                                                                                          |\n| id                                            | _string_   | Unique identifier for the edge. If not specified, `id` is automatically generated with the format `${source}-${target}` |\n| type                                          | _string_   | Edge type.It can be the type of built-in Edge, or the custom Edge                                                       |\n| data                                          | _Object_   | Custom data for the edge, accessible in style mappings via callback functions                                           |\n| style                                         | _Object_   | Edge style, including stroke color, line width, arrowhead, etc.                                                         |\n| states                                        | _string[]_ | Initial states for the edge                                                                                             |\n\n**Example:**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Combo Data\n\nCombos allow you to create a logical unit for multiple nodes, used for layering, grouping, or other structural purposes. A combo can contain child nodes or other combos, forming a nested structure.\n\n| Attribute                                 | Type               | Description                                                                    |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the combo                                                |\n| type                                      | _string_           | Combo type.It can be the type of built-in Combo, or the custom Combo           |\n| data                                      | _Object_           | Custom data for the combo, accessible in style mappings via callback functions |\n| style                                     | _Object_           | Combo style                                                                    |\n| states                                    | _string[]_         | Initial states for the combo                                                   |\n| combo                                     | _string_ \\| _null_ | Parent combo ID. If there is no parent combo, it is null                       |\n\n**Example:**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## Data Organization and Best Practices\n\nTo ensure correct rendering and interaction of the graph, it is recommended to organize the data according to G6's standard data structure. Each element (node, edge, combo) should contain a `data` field to store business data and custom properties.\n\n- **Avoid using identifiers that conflict with internal G6 field names**, such as `id`, `type`, `style`, etc., to prevent naming conflicts.\n- Store business data (such as user information, social network relationships, etc.) in the `data` field. This ensures flexibility and scalability of the data.\n\n**Example:**\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"node1\",\n      \"data\": { \"name\": \"Alice\", \"role\": \"Admin\" }\n    },\n    {\n      \"id\": \"node2\",\n      \"data\": { \"name\": \"Bob\", \"role\": \"User\" }\n    }\n  ],\n  \"edges\": [\n    {\n      \"source\": \"node1\",\n      \"target\": \"node2\",\n      \"data\": { \"relationship\": \"friend\" }\n    }\n  ]\n}\n```\n\n## API\n\nG6 provides a series of APIs to access and manipulate data, including:\n\n- [getData](/en/api/data#graphgetdata)\n- [setData](/en/api/data#graphsetdata)\n- [getNodeData](/en/api/data#graphgetnodedata)\n- [getEdgeData](/en/api/data#graphgetedgedata)\n- [getComboData](/en/api/data#graphgetcombodata)\n- [addData](/en/api/data#graphadddata)\n- [addNodeData](/en/api/data#graphaddnodedata)\n- [addEdgeData](/en/api/data#graphaddedgedata)\n- [addComboData](/en/api/data#graphaddcombodata)\n- [updateData](/en/api/data#graphupdatedata)\n- [updateNodeData](/en/api/data#graphupdatenodedata)\n- [updateEdgeData](/en/api/data#graphupdateedgedata)\n- [updateComboData](/en/api/data#graphupdatecombodata)\n- [removeData](/en/api/data#graphremovedata)\n- [removeNodeData](/en/api/data#graphremovenodedata)\n- [removeEdgeData](/en/api/data#graphremoveedgedata)\n- [removeComboData](/en/api/data#graphremovecombodata)\n\nThrough different APIs, you can conveniently access and manipulate graph data, performing operations such as adding, deleting, modifying, and querying the graph.\n\n## Use Remote Data\n\nG6 does not provide functionality for data retrieval and parsing. For local JSON data, you can directly import and use it as follows:\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\nFor remote data, you can use `fetch` or other networking libraries to retrieve the data:\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // Use data\n  });\n```\n","frontmatter":{"title":"Data","order":"1"},"isInternal":false,"tokens":2440,"sizeBytes":9762},{"name":"data.zh.md","path":"packages/site/docs/manual/data.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/data.zh.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 数据 Data\norder: 4\n---\n\n## 概述\n\nG6 是一款数据驱动的图可视化引擎，数据是 G6 中最重要的概念之一。\n\nG6 使用标准的 JSON 格式描述图数据结构。以下是一个基础的图数据示例：\n\n```javascript {4-7}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n});\n```\n\n## 数据结构\n\n图数据包含三部分：`nodes`（节点数据）、`edges`（边数据）、`combos`（组合数据）。每一部分对应图中的不同元素，它们的类型和数据决定了图如何展示。\n\n### 图数据（GraphData）\n\n| 属性   | 描述     | 类型                              | 默认值 | 必选 |\n| ------ | -------- | --------------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#节点数据nodedata)[]   | -      |      |\n| edges  | 边数据   | [EdgeData](#边数据edgedata)[]     | -      |      |\n| combos | 组合数据 | [ComboData](#组合数据combodata)[] | -      |      |\n\n### 节点数据（NodeData）\n\n节点是图中的基本构成单元，它代表图中的实体。每个节点都有一个唯一的 `id`，用于标识节点，同时节点也可以有数据、样式和状态。\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### 边数据（EdgeData）\n\n边是连接节点的元素，表示节点之间的关系。每条边都与两个节点（起始节点和目标节点）关联，并且边本身可以有数据、样式和状态。边的数据常用于表示节点之间的逻辑或关系，如社交网络中的用户关系、流程图中的步骤流转等。\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n**示例：**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 组合数据（ComboData）\n\n通过组合，可以为多个节点创建一个逻辑单元，用于图形的分层、分组或其他结构化需求。组合可以包含子节点或其他组合，从而形成嵌套层次。\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## 数据操作\n\nG6 提供了丰富的 API 来操作图数据，下面展示一些常见的数据操作示例。\n\n### 数据初始化\n\n在创建图实例时，可以直接传入数据：\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n```\n\n或者通过 `setData` 方法设置数据：\n\n```javascript\ngraph.setData({\n  nodes: [\n    { id: 'node3', data: { label: '节点3' } },\n    { id: 'node4', data: { label: '节点4' } },\n  ],\n  edges: [{ source: 'node3', target: 'node4', data: { label: '新关系' } }],\n});\n```\n\n### 数据增删改查\n\n#### 添加节点和边\n\n```javascript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node5',\n    data: {\n      label: '新节点',\n      category: 'person',\n    },\n    style: {\n      fill: '#6395F9',\n      stroke: '#5B8FF9',\n    },\n  },\n]);\n\n// 批量添加多个节点\ngraph.addNodeData([\n  { id: 'node6', data: { label: '批量节点1' } },\n  { id: 'node7', data: { label: '批量节点2' } },\n]);\n\n// 添加连接新节点的边\ngraph.addEdgeData([\n  {\n    source: 'node1',\n    target: 'node5',\n    data: {\n      label: '连接到新节点',\n      weight: 2,\n    },\n    style: {\n      stroke: '#F6BD16',\n      lineWidth: 3,\n    },\n  },\n]);\n```\n\n#### 更新数据\n\n```javascript\n// 更新单个节点\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    data: {\n      label: '已更新的节点1',\n      status: 'updated',\n    },\n    style: {\n      fill: '#F6BD16',\n      stroke: '#EBEBEB',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 更新多个节点\ngraph.updateNodeData([\n  {\n    id: 'node2',\n    style: { size: 40, fill: '#5AD8A6' },\n  },\n  {\n    id: 'node3',\n    data: { importance: 'high' },\n  },\n]);\n\n// 更新边\ngraph.updateEdgeData([\n  {\n    source: 'node1',\n    target: 'node2',\n    style: {\n      stroke: '#5B8FF9',\n      lineWidth: 2,\n      lineDash: [5, 5],\n    },\n  },\n]);\n```\n\n#### 删除数据\n\n```javascript\n// 删除单个节点（以及与该节点相连的所有边）\ngraph.removeNodeData(['node7']);\n\n// 删除多个节点\ngraph.removeNodeData(['node5', 'node6']);\n\n// 删除边\ngraph.removeEdgeData(['node1-node2']);\n```\n\n#### 查询数据\n\n```javascript\n// 获取所有节点数据\nconst nodes = graph.getNodeData();\n\n// 获取所有边数据\nconst edges = graph.getEdgeData();\n\n// 获取特定节点数据\nconst node1 = graph.getNodeData('node1');\n\n// 获取特定边数据\nconst edge1 = graph.getEdgeData('node1-node2');\n```\n\n### 复杂数据结构操作\n\n#### 嵌套组合（Combo）\n\n下面是创建和操作嵌套组合的示例：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', data: { label: '节点1' }, combo: 'combo1' },\n    { id: 'node2', data: { label: '节点2' }, combo: 'combo1' },\n    { id: 'node3', data: { label: '节点3' }, combo: 'combo2' },\n    { id: 'node4', data: { label: '节点4' }, combo: 'combo2' },\n    { id: 'node5', data: { label: '节点5' }, combo: 'combo3' },\n  ],\n  edges: [\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n  combos: [\n    { id: 'combo1', data: { label: '组1' } },\n    { id: 'combo2', data: { label: '组2' } },\n    { id: 'combo3', data: { label: '组3' }, combo: 'combo1' }, // 嵌套组合\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'force',\n  },\n});\n\n// 添加新的组合\ngraph.addComboData([\n  {\n    id: 'combo4',\n    data: { label: '新组' },\n    combo: 'combo2', // 添加到现有组合中\n  },\n]);\n\n// 将节点移动到不同的组合\ngraph.updateNodeData([\n  {\n    id: 'node5',\n    combo: 'combo4', // 将节点5移动到新组合\n  },\n]);\n\n// 展开/折叠组合\ngraph.updateComboData([\n  {\n    id: 'combo1',\n    style: { collapsed: true }, // 折叠组合1\n  },\n]);\n\ngraph.render();\n```\n\n#### 树形结构数据\n\n对于树形结构，G6 支持使用 `children` 属性表示层次关系：\n\n```javascript\n// 树形结构数据\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst treeData = {\n  id: 'root',\n  children: [\n    {\n      id: 'child1',\n      children: [{ id: 'grandchild1' }],\n    },\n    {\n      id: 'child2',\n      children: [{ id: 'grandchild2' }],\n    },\n  ],\n};\n\nconst data = treeToGraphData(treeData);\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'dendrogram', // 或 'compactBox', 'mindmap' 等树布局\n    direction: 'TB', // 从上到下布局\n    nodeSep: 50, // 节点间距\n    rankSep: 100, // 层级间距\n  },\n});\n\ngraph.render();\n```\n\n通过 `treeToGraphData` 方法，可以将树形结构数据转换为 G6 的标准数据结构，实际传入到 `data` 中的数据结构如下：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"root\", \"depth\": 0, \"children\": [\"child1\", \"child2\"] },\n    { \"id\": \"child1\", \"depth\": 1, \"children\": [\"grandchild1\"] },\n    { \"id\": \"grandchild1\", \"depth\": 2 },\n    { \"id\": \"child2\", \"depth\": 1, \"children\": [\"grandchild2\"] },\n    { \"id\": \"grandchild2\", \"depth\": 2 }\n  ],\n  \"edges\": [\n    { \"source\": \"root\", \"target\": \"child1\" },\n    { \"source\": \"root\", \"target\": \"child2\" },\n    { \"source\": \"child1\", \"target\": \"grandchild1\" },\n    { \"source\": \"child2\", \"target\": \"grandchild2\" }\n  ]\n}\n```\n\n## 数据组织与最佳实践\n\n为了确保图的正确渲染和交互，建议按照 G6 标准数据结构组织数据。每个元素（节点、边、组合）应包含一个 `data` 字段，用于存放业务数据和自定义属性。\n\n- **避免使用与 G6 内部字段名称相同的标识符**，如 `id`、`type`、`style` 等，防止发生命名冲突。\n- 将业务数据（如用户信息、社交网络关系等）存储在 `data` 字段中，这样可以确保数据的灵活性和可扩展性。\n- **使用样式映射**来根据业务数据动态设置视觉属性，而不是直接修改样式对象。\n\n### 数据与样式分离\n\n良好的做法是将数据和样式分离，通过映射函数将数据属性转换为视觉属性：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 使用数据驱动样式\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', data: { value: 10, category: 'A' } },\n      { id: 'node2', data: { value: 5, category: 'B' } },\n    ],\n  },\n  node: {\n    style: {\n      // 根据数据中的 value 字段动态设置节点大小\n      size: (node) => 20 + node.data.value * 2,\n      // 根据数据中的 category 字段设置不同颜色\n      fill: (node) => {\n        const categoryColors = { A: '#F6BD16', B: '#5B8FF9' };\n        return categoryColors[node.data.category] || '#CCC';\n      },\n    },\n  },\n});\n```\n\n## API\n\nG6 提供了一系列的 API 来访问和操作数据，包括：\n\n- [getData](/api/data#graphgetdata)\n- [setData](/api/data#graphsetdata)\n- [getNodeData](/api/data#graphgetnodedata)\n- [getEdgeData](/api/data#graphgetedgedata)\n- [getComboData](/api/data#graphgetcombodata)\n- [addData](/api/data#graphadddata)\n- [addNodeData](/api/data#graphaddnodedata)\n- [addEdgeData](/api/data#graphaddedgedata)\n- [addComboData](/api/data#graphaddcombodata)\n- [updateData](/api/data#graphupdatedata)\n- [updateNodeData](/api/data#graphupdatenodedata)\n- [updateEdgeData](/api/data#graphupdateedgedata)\n- [updateComboData](/api/data#graphupdatecombodata)\n- [removeData](/api/data#graphremovedata)\n- [removeNodeData](/api/data#graphremovenodedata)\n- [removeEdgeData](/api/data#graphremoveedgedata)\n- [removeComboData](/api/data#graphremovecombodata)\n\n通过不同的 API，你可以方便地访问和操作图数据，实现图的增删改查等操作。\n\n## 使用远程数据\n\nG6 并不提供数据的获取和解析功能，对于本地 JSON 数据，你可以直接引入使用：\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\n对于远程数据，你可以使用 `fetch` 或者其他网络请求库来获取数据：\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // 使用 data\n    const graph = new Graph({\n      container: 'container',\n      data,\n    });\n    // 触发布局和渲染\n    graph.render();\n  })\n  .catch((error) => {\n    console.error('加载数据失败:', error);\n  });\n```\n","frontmatter":{"title":"数据 Data","order":"4"},"isInternal":false,"tokens":2815,"sizeBytes":14463},{"name":"BaseCombo.en.md","path":"packages/site/docs/manual/element/combo/BaseCombo.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/BaseCombo.en.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Combo Common Options\norder: 1\n---\n\nThis document introduces the built-in combo common property configurations.\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {}, // Combo style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                               | Type                    | Default  | Required |\n| --------- | --------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name | [Type](#type)           | `circle` |          |\n| style     | Combo style configuration, including color, size, etc.    | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                  | [State](#state)         | -        |          |\n| palette   | Define combo palette for mapping colors based on data     | [Palette](#palette)     | -        |          |\n| animation | Define combo animation effects                            | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the combo type, built-in combo type name or custom combo name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select combo types based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Combo](/en/manual/element/combo/circle)\n- `rect`: [Rect Combo](/en/manual/element/combo/rect)\n\n## Style\n\nDefines combo style, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All style properties below support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Combo: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the combo data object (`ComboData`), containing all combo data information.\n\nA complete combo consists of the following parts:\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the primary shape of the combo, such as circle, rectangle, etc.\n- `label`: Text label, usually used to display the combo's name or description\n- `halo`: Graphic displaying halo effect around the main graphic\n- `badge`: Badge displayed at the top-right corner of the combo by default\n\nThe following style configurations will be explained by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the combo, defining the basic shape and appearance of the combo. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdd transparency and shadow effects to combos:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreate combos with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                              | Type                          | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current combo is collapsed                                                                                                   | boolean                       | false     |          |\n| cursor                          | Combo mouse hover style, [options](#cursor)                                                                                              | string                        | default   |          |\n| fill                            | Combo fill color                                                                                                                         | string                        | `#99ADD1` |          |\n| fillOpacity                     | Combo fill opacity                                                                                                                       | number \\| string              | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick | number                        | 0         |          |\n| lineCap                         | Combo stroke end cap style                                                                                                               | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                  | number[]                      | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                 | number                        | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                  | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                       | number                        | 1         |          |\n| opacity                         | Combo opacity                                                                                                                            | number \\| string              | 1         |          |\n| pointerEvents                   | How combo responds to pointer events, [options](#pointerevents)                                                                          | string                        | `auto`    |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                        | number                        | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                       | string                        | -         |          |\n| shadowOffsetX                   | Combo shadow offset in x direction                                                                                                       | number \\| string              | -         |          |\n| shadowOffsetY                   | Combo shadow offset in y direction                                                                                                       | number \\| string              | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                        | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Combo size, quick setting for combo width and height, [options](#size)                                                                   | number \\| number[]            | -         |          |\n| stroke                          | Combo stroke color                                                                                                                       | string                        | `#99ADD1` |          |\n| strokeOpacity                   | Combo stroke opacity                                                                                                                     | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given combo                                                        | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                           | string                        | -         |          |\n| visibility                      | Whether combo is visible                                                                                                                 | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                       | number                        | 0         |          |\n| y                               | Combo y coordinate                                                                                                                       | number                        | 0         |          |\n| z                               | Combo z coordinate                                                                                                                       | number                        | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                    | number                        | 0         |          |\n\n#### Size\n\nCombo size, quick setting for combo width and height, supports three configuration methods:\n\n- number: Indicates that combo width and height are the same as the specified value\n- [number, number]: Indicates that combo width and height are represented by array elements in order for combo width and height\n- [number, number, number]: Indicates that combo width, height, and depth are represented by array elements in order\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be the target of responding events\n- **`visiblepainted`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the `fill` value\n- **`visiblestroke`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n- **`visible`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by `fill` and `stroke` values\n- **`painted`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`fill`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the `fill` value\n  - Not affected by `visibility` value\n- **`stroke`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Will respond to events as long as entering the graphic fill and stroke areas, not affected by `fill`, `stroke`, `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Does not respond to events at all\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // Combo does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Style When Expanded\n\nMain graphic style when the combo is expanded\n\n| Attribute                       | Description                                                                                                                                       | Type                                                                            | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------- | -------- |\n| collapsed                       | Whether the combo is currently collapsed                                                                                                          | boolean                                                                         | false     |          |\n| cursor                          | Combo mouse hover style, [configuration item](#cursor)                                                                                            | string                                                                          | default   |          |\n| fill                            | Combo fill color                                                                                                                                  | string                                                                          | `#99ADD1` |          |\n| fillOpacity                     | Combo fill color opacity                                                                                                                          | number  string                                                                 | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0         |          |\n| lineCap                         | Combo stroke end style                                                                                                                            | `round`  `square`  `butt`                                                     | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                           | number[]                                                                        | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                          | number                                                                          | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                           | `round`  `bevel`  `miter`                                                     | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                                | number                                                                          | 1         |          |\n| opacity                         | Combo opacity                                                                                                                                     | number  string                                                                 | 1         |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                                 | number                                                                          | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                                | string                                                                          | -         |          |\n| shadowOffsetX                   | Combo shadow offset in the x-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowOffsetY                   | Combo shadow offset in the y-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                                 | `inner`  `outer`                                                               | `outer`   |          |\n| stroke                          | Combo stroke color                                                                                                                                | string                                                                          | `#99add1` |          |\n| strokeOpacity                   | Combo stroke color opacity                                                                                                                        | number  string                                                                 | 1         |          |\n| visibility                      | Whether the combo is visible                                                                                                                      | `visible`  `hidden`                                                            | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                                | number                                                                          | 0         |          |\n| y                               | Combo y coordinate                                                                                                                                | number                                                                          | 0         |          |\n| z                               | Combo z coordinate                                                                                                                                | number                                                                          | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                             | number                                                                          | 0         |          |\n| `{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items         | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -         |          |\n\n#### Cursor\n\nOptional 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`\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      fill: '#1783FF', // Fill color\n      stroke: '#000', // Stroke color\n      lineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: { fill: '#1783FF', stroke: '#000', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Style When Collapsed\n\nEffective when `collapsed` is `true`\n\n| Attribute                                | Description                                                                                                                                                                  | Type                                                                            | Default                                  | Required |\n| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------- | -------- |\n| collapsedCursor                          | Mouse hover style when the combo is collapsed, [configuration item](#cursor)                                                                                                 | string                                                                          | Same as the cursor when expanded         |          |\n| collapsedFill                            | Fill color when the combo is collapsed                                                                                                                                       | string                                                                          | Same as the fill when expanded           |          |\n| collapsedFillOpacity                     | Fill color opacity when the combo is collapsed                                                                                                                               | number  string                                                                 | 1                                        |          |\n| collapsedIncreasedLineWidthForHitTesting | When the combo is collapsed, if lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0                                        |          |\n| collapsedLineCap                         | Stroke end style when the combo is collapsed                                                                                                                                 | `round`  `square`  `butt`                                                     | Same as the lineCap when expanded        |          |\n| collapsedLineDash                        | Stroke dash style when the combo is collapsed                                                                                                                                | number[]                                                                        | Same as the lineDash when expanded       |          |\n| collapsedLineDashOffset                  | Stroke dash offset when the combo is collapsed                                                                                                                               | number                                                                          | Same as the lineDashOffset when expanded |          |\n| collapsedLineJoin                        | Stroke join style when the combo is collapsed                                                                                                                                | `round`  `bevel`  `miter`                                                     | Same as the lineJoin when expanded       |          |\n| collapsedLineWidth                       | Stroke width when the combo is collapsed                                                                                                                                     | number                                                                          | Same as the lineWidth when expanded      |          |\n| collapsedMarker                          | Whether to display the marker when the combo is collapsed, [configuration item](#collapsedMarkerStyle)                                                                       | boolean                                                                         | true                                     |          |\n| collapsedOpacity                         | Opacity when the combo is collapsed                                                                                                                                          | number  string                                                                 | Same as the opacity when expanded        |          |\n| collapsedShadowBlur                      | Shadow blur when the combo is collapsed                                                                                                                                      | number                                                                          | Same as the shadowBlur when expanded     |          |\n| collapsedShadowColor                     | Shadow color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the shadowColor when expanded    |          |\n| collapsedShadowOffsetX                   | Shadow offset in the x-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetX when expanded  |          |\n| collapsedShadowOffsetY                   | Shadow offset in the y-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetY when expanded  |          |\n| collapsedShadowType                      | Shadow type when the combo is collapsed                                                                                                                                      | `inner`  `outer`                                                               | Same as the shadowType when expanded     |          |\n| collapsedSize                            | Size when the combo is collapsed                                                                                                                                             | number &#124; [number, number] &#124; [number, number, number]                  | 32                                       |          |\n| collapsedStroke                          | Stroke color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the stroke when expanded         |          |\n| collapsedStrokeOpacity                   | Stroke color opacity when the combo is collapsed                                                                                                                             | number  string                                                                 | Same as the strokeOpacity when expanded  |          |\n| collapsedVisibility                      | Whether the combo is visible when collapsed                                                                                                                                  | `visible`  `hidden`                                                            | Same as the visibility when expanded     |          |\n| `collapsed{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items                                    | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -                                        |          |\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedFill: '#1783FF', // Fill color\n      collapsedStroke: '#000', // Stroke color\n      collapsedLineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: { collapsedFill: '#1783FF', collapsedStroke: '#000', collapsedLineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Collapsed Marker Style\n\nEffective when `collapsedMarker` is `true`\n\n| Attribute                     | Description                                                                                                                                                                                                                                                                                                                                                         | Type                                                                                                                               | Default       | Required |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| collapsedMarkerType           | Marker type displayed when the combo is collapsed <br> - `'child-count'`: Number of child elements (including Node and Combo) <br>- `'descendant-count'`: Number of descendant elements (including Node and Combo) <br>- `'node-count'`: Number of descendant elements (only including Node) <br> - `(children: NodeLikeData[]) => string`: Custom processing logic | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string)                             | `child-count` |          |\n| collapsedMarkerFill           | Icon text color                                                                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | #fff          |          |\n| collapsedMarkerFillOpacity    | Icon text color opacity                                                                                                                                                                                                                                                                                                                                             | number                                                                                                                             | 1             |          |\n| collapsedMarkerFontSize       | Icon font size                                                                                                                                                                                                                                                                                                                                                      | number                                                                                                                             | 12            |          |\n| collapsedMarkerFontWeight     | Icon font weight                                                                                                                                                                                                                                                                                                                                                    | number \\| string                                                                                                                   | `normal`      |          |\n| collapsedMarkerRadius         | Icon corner radius                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                             | 0             |          |\n| collapsedMarkerSrc            | Image source. Its priority is higher than `collapsedMarkerText`                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | -             |          |\n| collapsedMarkerText           | Icon text                                                                                                                                                                                                                                                                                                                                                           | string                                                                                                                             | -             |          |\n| collapsedMarkerTextAlign      | Icon text horizontal alignment                                                                                                                                                                                                                                                                                                                                      | `center`  `end`  `left`  `right`  `start`                                                                                      | `center`      |          |\n| collapsedMarkerTextBaseline   | Icon text alignment baseline                                                                                                                                                                                                                                                                                                                                        | `alphabetic`  `bottom`  `hanging`  `ideographic`  `middle`  `top`                                                             | `middle`      |          |\n| collapsedMarkerWidth          | Icon width                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                             | -             |          |\n| collapsedMarkerHeight         | Icon height                                                                                                                                                                                                                                                                                                                                                         | number                                                                                                                             | -             |          |\n| collapsedMarkerZIndex         | Icon rendering layer                                                                                                                                                                                                                                                                                                                                                | number                                                                                                                             | 1             |          |\n| `collapsedMarker{StyleProps}` | More icon style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text), [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) configuration items. For example, collapsedMarkerFontSize represents the font size of the text icon                                                                                           | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) &#124; [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) | -             |          |\n\n**Example:**\n\n```js {5-6}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF', // Fill color\n      collapsedMarkerFontSize: 30, // Icon font size\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 30,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Label Style\n\nLabels are used to display text information for combos, supporting rich text style configuration and flexible position layout.\n\n#### Basic Label Configuration\n\nAdd basic text label to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Sales Department', // Label text content\n      labelFill: '#1A1A1A', // Label text color\n      labelFontSize: 14, // Label font size\n      labelPlacement: 'bottom', // Label position: bottom\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nConfigure labels that support multi-line display:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'This is a combo label text content that supports multi-line display',\n      labelWordWrap: true, // Enable text wrapping\n      labelMaxWidth: 100, // Maximum width 100px\n      labelMaxLines: 3, // Maximum 3 lines\n      labelTextAlign: 'center', // Center text alignment\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Style Label\n\nCreate labels with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // Red text\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // Bold\n      labelFontStyle: 'italic', // Italic\n      labelTextDecorationLine: 'underline', // Underline\n      labelLetterSpacing: 2, // Letter spacing\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label style configurations:\n\n| Property                 | Description                                                                                                                                                                | Type                                                                        | Default   | Required |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show combo label                                                                                                                                                | boolean                                                                     | true      |          |\n| labelCursor              | Cursor style when hovering over combo label, [options](#cursor)                                                                                                            | string                                                                      | `default` |          |\n| labelFill                | Combo label text color                                                                                                                                                     | string                                                                      | #000      |          |\n| labelFillOpacity         | Combo label text color opacity                                                                                                                                             | number                                                                      | 1         |          |\n| labelFontFamily          | Combo label font family                                                                                                                                                    | string                                                                      | -         |          |\n| labelFontSize            | Combo label font size                                                                                                                                                      | number                                                                      | 12        |          |\n| labelFontStyle           | Combo label font style                                                                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Combo label font variant                                                                                                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Combo label font weight                                                                                                                                                    | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |          |\n| labelLeading             | Line spacing                                                                                                                                                               | number                                                                      | 0         |          |\n| labelLetterSpacing       | Combo label letter spacing                                                                                                                                                 | number \\| string                                                            | -         |          |\n| labelLineHeight          | Combo label line height                                                                                                                                                    | number \\| string                                                            | -         |          |\n| labelMaxLines            | Combo label maximum lines                                                                                                                                                  | number                                                                      | 1         |          |\n| labelMaxWidth            | Combo label maximum width, [options](#labelmaxwidth)                                                                                                                       | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Combo label X offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelOffsetY             | Combo label Y offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelPadding             | Combo label padding                                                                                                                                                        | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Combo label position relative to combo main graphic, [options](#labelplacement)                                                                                            | string                                                                      | `bottom`  |          |\n| labelText                | Combo label text content                                                                                                                                                   | string                                                                      | -         |          |\n| labelTextAlign           | Combo label text horizontal alignment                                                                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Combo label text baseline                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Combo label text decoration color                                                                                                                                          | string                                                                      | -         |          |\n| labelTextDecorationLine  | Combo label text decoration line                                                                                                                                           | string                                                                      | -         |          |\n| labelTextDecorationStyle | Combo label text decoration style                                                                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Combo label text overflow handling                                                                                                                                         | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Combo label text path                                                                                                                                                      | Path                                                                        | -         |          |\n| labelWordWrap            | Whether combo label enables auto line wrapping. When labelWordWrap is enabled, parts exceeding labelMaxWidth automatically wrap                                            | boolean                                                                     | false     |          |\n| labelZIndex              | Combo label rendering layer                                                                                                                                                | number                                                                      | 0         |          |\n| `label{StyleProps}`      | More label style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) property values. For example, labelOpacity represents label opacity | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |          |\n\n#### LabelPlacement\n\nLabel position relative to combo main graphic, available values:\n\n- `center`: Label at combo center\n- `top`, `bottom`, `left`, `right`: Label at top, bottom, left, right of combo\n- `top-left`, `top-right`, `bottom-left`, `bottom-right`: Label at four corners of combo\n- `left-top`, `left-bottom`, `right-top`, `right-bottom`: Label at edge endpoints of combo\n\n#### LabelMaxWidth\n\nWhen auto line wrapping `labelWordWrap` is enabled, text wraps when exceeding this width:\n\n- string: Defines maximum width as percentage relative to combo element width. For example, `50%` means label width doesn't exceed half of combo width\n- number: Defines maximum width in pixels. For example, 100 means label maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background provides background decoration for label text, improving label readability and visual effects.\n\n#### Basic Background Style\n\nAdd simple background to label:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Important Combo',\n      labelFill: '#fff', // White text\n      labelBackground: true, // Enable background\n      labelBackgroundFill: '#1783FF', // Blue background\n      labelBackgroundPadding: [4, 8], // Padding: vertical 4px, horizontal 8px\n      labelBackgroundRadius: 4, // Border radius\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Gradient Background Effect\n\nCreate label background with gradient effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP Combo',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // Gradient background\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // Large border radius\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Stroke-only Background Style\n\nCreate label background with stroke only:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Border Label',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // Transparent background\n      labelBackgroundStroke: '#1783FF', // Blue stroke\n      labelBackgroundLineWidth: 2, // Stroke width\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label background style configurations:\n\n| Property                      | Description                                                                                                                                                                                                | Type                                                         | Default      |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | Whether to show combo label background                                                                                                                                                                     | boolean                                                      | false        |\n| labelBackgroundCursor         | Combo label background cursor style, [options](#cursor)                                                                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | Combo label background fill color                                                                                                                                                                          | string                                                       | #000         |\n| labelBackgroundFillOpacity    | Combo label background opacity                                                                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | Combo label background height                                                                                                                                                                              | string \\| number                                             | -            |\n| labelBackgroundLineDash       | Combo label background dash configuration                                                                                                                                                                  | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | Combo label background dash offset                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | Combo label background stroke line width                                                                                                                                                                   | number                                                       | -            |\n| labelBackgroundPadding        | Combo label background padding                                                                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | Combo label background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values auto-filled                                    | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | Combo label background shadow blur                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundShadowColor    | Combo label background shadow color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | Combo label background shadow X offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | Combo label background shadow Y offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundStroke         | Combo label background stroke color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | Combo label background stroke opacity                                                                                                                                                                      | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | Whether combo label background is visible                                                                                                                                                                  | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | Combo label background rendering layer                                                                                                                                                                     | number                                                       | 1            |\n| `labelBackground{StyleProps}` | More label background style configurations, refer to [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) property values. For example, labelBackgroundOpacity represents label background opacity | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### Badge Style\n\nBadges are small markers displayed on combos, usually used to show status, quantity, or other auxiliary information. Multiple badges can be displayed simultaneously with customizable positions.\n\n#### Single Badge\n\nAdd a simple badge to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Display at top by default\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdd multiple badges at different positions to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // Whether to show badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nFully customize badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete badge style configurations:\n\n| Property     | Description                    | Type                                  | Default                           |\n| ------------ | ------------------------------ | ------------------------------------- | --------------------------------- |\n| badge        | Whether to show combo badge    | boolean                               | true                              |\n| badgePalette | Combo badge background palette | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Combo badge settings           | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                            | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether to show combo badge background                                                                                                                                                                                                                                                                 | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Combo badge background cursor style, [options](#cursor)                                                                                                                                                                                                                                                | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Combo badge background fill color. If not specified, consider badgePalette for sequential allocation                                                                                                                                                                                                   | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Combo badge background fill opacity                                                                                                                                                                                                                                                                    | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Combo badge background filter                                                                                                                                                                                                                                                                          | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Combo badge background height                                                                                                                                                                                                                                                                          | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Combo badge background dash configuration                                                                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Combo badge background dash offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Combo badge background stroke line width                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Combo badge background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values will be filled <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, space-separated | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Combo badge background shadow blur                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Combo badge background shadow color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Combo badge background shadow X offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Combo badge background shadow Y offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Combo badge background stroke color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Combo badge background stroke opacity                                                                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether combo badge background is visible                                                                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | Combo badge text color                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                 | -            |\n| fontFamily               | Combo badge font family                                                                                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| fontSize                 | Combo badge font size                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | Combo badge font style                                                                                                                                                                                                                                                                                 | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Combo badge font variant                                                                                                                                                                                                                                                                               | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Combo badge font weight                                                                                                                                                                                                                                                                                | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Combo badge line height                                                                                                                                                                                                                                                                                | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Combo badge line width                                                                                                                                                                                                                                                                                 | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Combo badge text maximum lines                                                                                                                                                                                                                                                                         | number                                                                                                                                                                 | 1            |\n| offsetX                  | Combo badge X offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| offsetY                  | Combo badge Y offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| padding                  | Combo badge padding                                                                                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Combo badge position relative to combo main graphic. If not specified, defaults to clockwise placement starting from top-right                                                                                                                                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Combo badge text content                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textAlign                | Combo badge text horizontal alignment                                                                                                                                                                                                                                                                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Combo badge text baseline                                                                                                                                                                                                                                                                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Combo badge text decoration color                                                                                                                                                                                                                                                                      | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Combo badge text decoration line                                                                                                                                                                                                                                                                       | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Combo badge text decoration style                                                                                                                                                                                                                                                                      | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Combo badge text overflow handling                                                                                                                                                                                                                                                                     | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether combo badge is visible                                                                                                                                                                                                                                                                         | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether combo badge text auto-wraps                                                                                                                                                                                                                                                                    | boolean                                                                                                                                                                | -            |\n| zIndex                   | Combo badge rendering layer                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | 3            |\n\n### Halo Style\n\nHalo effect is used to highlight combos, usually used in mouse hover, selected, or active states, adding glow effect around combos.\n\n#### Basic Halo Effect\n\nAdd simple halo effect to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // Enable halo\n      haloStroke: '#1783FF', // Blue halo\n      haloLineWidth: 8, // Halo width\n      haloStrokeOpacity: 0.3, // Halo opacity\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Halo Effect\n\nCreate colorful gradient halo effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // Red halo\n      haloLineWidth: 12, // Thicker halo\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // Blur filter effect\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dynamic Halo Effect\n\nUse halo effect in state transitions:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // No halo in default state\n      halo: false,\n    },\n    state: {\n      // Show orange halo in hover state\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // Show green halo in selected state\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete halo style configurations:\n\n| Property           | Description                                                                                                                                                                       | Type                                                                  | Default                         | Required |\n| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------- | -------- |\n| halo               | Whether to show combo halo                                                                                                                                                        | boolean                                                               | false                           |          |\n| haloCursor         | Combo halo cursor style, [options](#cursor)                                                                                                                                       | string                                                                | `default`                       |          |\n| haloDraggable      | Whether combo halo allows dragging                                                                                                                                                | boolean                                                               | true                            |          |\n| haloDroppable      | Whether combo halo allows receiving dragged elements                                                                                                                              | boolean                                                               | false                           |          |\n| haloFill           | Halo fill color                                                                                                                                                                   | string                                                                | Same as main graphic fill color |          |\n| haloFillRule       | Combo halo fill rule                                                                                                                                                              | `nonzero` \\| `evenodd`                                                | -                               |          |\n| haloFilter         | Combo halo filter effect, such as 'blur(2px)' for blur effect                                                                                                                     | string                                                                | -                               |          |\n| haloLineWidth      | Combo halo stroke width, controls halo thickness                                                                                                                                  | number                                                                | 12                              |          |\n| haloPointerEvents  | Whether combo halo effect responds to pointer events, [options](#pointerevents)                                                                                                   | string                                                                | `none`                          |          |\n| haloStroke         | Combo halo stroke color, **this property is used to set the color of halo around combo, helping to highlight the combo**                                                          | string                                                                | `#99add1`                       |          |\n| haloStrokeOpacity  | Combo halo stroke opacity, recommended to use 0.2-0.6 values for natural halo effect                                                                                              | number                                                                | 0.25                            |          |\n| haloVisibility     | Combo halo visibility                                                                                                                                                             | `visible` \\| `hidden`                                                 | `visible`                       |          |\n| haloZIndex         | Combo halo rendering layer, usually set to negative value to ensure halo is below combo main graphic                                                                              | number                                                                | -1                              |          |\n| `halo{StyleProps}` | More halo style configurations, refer to [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) options. For example, haloFillOpacity represents halo fill opacity | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                               |          |\n\n**Halo Usage Recommendations:**\n\n1. **Performance Consideration**: Halo effects increase rendering burden, recommend enabling only when necessary\n2. **Color Matching**: Halo color should coordinate with combo main color tone, avoid being too abrupt\n3. **Opacity Setting**: Reasonable opacity (0.2-0.6) can create natural halo effect\n4. **State Application**: Halo is usually used for hover, selected, active and other interactive states\n\n### Icon Style\n\nIcons are used to display text or image content in combos, usually located at the center of the combo, can be used to represent combo type or function.\n\n#### Text Icon\n\nUse text as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // Display letter A\n      iconFill: '#1783FF', // Blue text\n      iconFontSize: 24, // Large font\n      iconFontWeight: 'bold', // Bold\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Image Icon\n\nUse image as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Text Icon\n\nCreate text icon with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'Dept',\n      iconFill: '#FF4D4F', // Red text\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // Italic\n      iconTextDecorationLine: 'underline', // Underline\n      iconLetterSpacing: 1, // Letter spacing\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete icon style configurations:\n\n| Property                | Description                                                                                                               | Type                                                                        | Default                     |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to show combo icon                                                                                                | boolean                                                                     | true                        |\n| iconCursor              | Combo icon cursor style, [options](#cursor)                                                                               | string                                                                      | `default`                   |\n| iconFill                | Combo icon text color                                                                                                     | string                                                                      | -                           |\n| iconFillOpacity         | Combo icon text color opacity                                                                                             | number                                                                      | 1                           |\n| iconFontFamily          | Combo icon font family                                                                                                    | string                                                                      | -                           |\n| iconFontSize            | Combo icon font size                                                                                                      | number                                                                      | 16                          |\n| iconFontStyle           | Combo icon font style                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Combo icon font variant                                                                                                   | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Combo icon font weight                                                                                                    | number \\| string                                                            | `normal`                    |\n| iconHeight              | Combo icon height, used to control image size when using image icon                                                       | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Combo icon text letter spacing                                                                                            | number \\| string                                                            | -                           |\n| iconLineHeight          | Combo icon text line height                                                                                               | number \\| string                                                            | -                           |\n| iconMaxLines            | Combo icon text maximum lines                                                                                             | number                                                                      | 1                           |\n| iconOffsetX             | Combo icon X offset                                                                                                       | number                                                                      | 0                           |\n| iconOffsetY             | Combo icon Y offset                                                                                                       | number                                                                      | 0                           |\n| iconOpacity             | Combo icon opacity                                                                                                        | number                                                                      | 1                           |\n| iconRadius              | Combo icon border radius (only effective for rectangular icons)                                                           | number                                                                      | 0                           |\n| iconSrc                 | Combo image source. Has higher priority than iconText, supports local and network images                                  | string                                                                      | -                           |\n| iconText                | Combo icon text content, supports text, Unicode characters, etc.                                                          | string                                                                      | -                           |\n| iconTextAlign           | Combo icon text horizontal alignment                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`                    |\n| iconTextBaseline        | Combo icon text baseline                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`                    |\n| iconTextDecorationColor | Combo icon text decoration color                                                                                          | string                                                                      | -                           |\n| iconTextDecorationLine  | Combo icon text decoration line, such as underline, strikethrough, etc.                                                   | string                                                                      | -                           |\n| iconTextDecorationStyle | Combo icon text decoration style                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Combo icon text overflow handling                                                                                         | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconVisibility          | Whether combo icon is visible                                                                                             | `visible` \\| `hidden`                                                       | `visible`                   |\n| iconWidth               | Combo icon width, used to control image size when using image icon                                                        | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether combo icon text auto-wraps                                                                                        | boolean                                                                     | false                       |\n| iconZIndex              | Combo icon rendering layer                                                                                                | number                                                                      | 1                           |\n| `icon{StyleProps}`      | More icon style configurations, refer to specific icon type options. For example, iconStroke represents icon stroke color | -                                                                           | -                           |\n\n**Icon Usage Recommendations:**\n\n1. **Priority**: `iconSrc` (image) has higher priority than `iconText` (text), if both are set, image will be displayed first\n2. **Size Control**: Recommend setting icon size reasonably according to combo size, avoid icons being too large or small affecting visual effect\n3. **Performance Optimization**: Text icons have better performance, image icons require additional network requests and rendering overhead\n4. **Style Consistency**: Icon styles in the same graph should be consistent to improve overall visual effect\n5. **Accessibility**: Ensure icon color has sufficient contrast with background for easy user identification\n\n## State\n\nIn some interactive behaviors, such as clicking to select a combo or hovering to activate an edge, it is merely marking certain states on the element. To reflect these states in the visual space seen by the end user, we need to set different graphic element styles for different states to respond to changes in the element's state.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the default styles of the element.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\nFor example, when the combo is in the `focus` state, you can add a stroke with a width of 3 and a color of orange.\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n**⚠️ Dynamic Configuration**: State configuration also supports dynamic configuration, which can be used to set styles dynamically based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    state: {\n      // Static configuration\n      selected: {\n        stroke: '#1783FF',\n        lineWidth: 2,\n      },\n\n      // Dynamic configuration - arrow function form\n      hover: (datum) => ({\n        fill: datum.data.isVIP ? '#FFD700' : '#1783FF',\n        fillOpacity: 0.3,\n      }),\n\n      // Dynamic configuration - regular function form (access to graph instance)\n      active: function (datum) {\n        console.log(this); // graph instance\n        return {\n          stroke: datum.data.level > 3 ? '#FF4D4F' : '#52C41A',\n          lineWidth: 3,\n        };\n      },\n    },\n  },\n});\n```\n\n**⚠️ State Priority**: When a combo has multiple states simultaneously, the style merge follows the following priority (high to low):\n\n1. Later defined states override earlier defined states\n2. More specific selectors have higher priority\n3. Dynamic configuration has higher priority than static configuration\n\nFor example, if a combo has both `selected` and `hover` states, and `hover` is defined after `selected`, then `hover` state styles will override `selected` state styles.\n\n## Animation\n\nDefines the animation effects for combos, supporting the following two configuration methods:\n\n1. Disable all combo animations\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when combos enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when combo enters the canvas\n- `update`: Animation when combo updates\n- `exit`: Animation when combo leaves the canvas\n- `show`: Animation when combo shows from hidden state\n- `hide`: Animation when combo hides\n- `collapse`: Animation when combo collapses\n- `expand`: Animation when combo expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure combos, such as:\n\n#### Enter Animation\n\nConfigure animation when combo enters the canvas:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    animation: {\n      enter: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          from: 0, // Start from 0\n          to: 1, // End at 1\n          duration: 1000, // Animation duration\n          easing: 'ease-out', // Easing function\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Update Animation\n\nConfigure animation when combo updates:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      update: [\n        {\n          fields: ['x', 'y'], // Only animate x and y properties during update\n          duration: 1000, // Animation duration\n          easing: 'linear', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Exit Animation\n\nConfigure animation when combo leaves the canvas:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      exit: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          to: 0, // End at 0\n          duration: 500, // Animation duration\n          easing: 'ease-in', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Show/Hide Animation\n\nConfigure animation when combo shows/hides:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      show: [\n        {\n          fields: ['opacity'],\n          from: 0,\n          to: 1,\n          duration: 300,\n        },\n      ],\n      hide: [\n        {\n          fields: ['opacity'],\n          to: 0,\n          duration: 300,\n        },\n      ],\n    },\n  },\n});\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass `false` to disable specific stage animations:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // Disable combo enter animation\n    }\n  }\n}\n```\n\n**Animation Configuration Options:**\n\n| Property  | Description                             | Type                                                        | Default  |\n| --------- | --------------------------------------- | ----------------------------------------------------------- | -------- |\n| fields    | Properties to animate                   | string[]                                                    | -        |\n| from      | Starting value                          | number \\| string                                            | -        |\n| to        | Ending value                            | number \\| string                                            | -        |\n| duration  | Animation duration (milliseconds)       | number                                                      | 1000     |\n| easing    | Easing function                         | string                                                      | 'ease'   |\n| delay     | Animation delay (milliseconds)          | number                                                      | 0        |\n| repeat    | Number of repetitions (-1 for infinite) | number                                                      | 0        |\n| direction | Animation direction                     | 'normal' \\| 'reverse' \\| 'alternate' \\| 'alternate-reverse' | 'normal' |\n\n## Palette\n\nDefines combo color palette, i.e., predefined combo color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For palette definition, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                          | Type                              | Default |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |\n| type     | Specifies current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                  | `group` &#124; `value`            | `group` |\n| field    | Specifies grouping field in element data. If not specified, defaults to id as grouping field                         | string &#124; ((datum) => string) | `id`    |\n| color    | Palette colors. If palette is registered, you can directly specify its registration name, also accepts a color array | string &#124; string[]            | -       |\n| invert   | Whether to invert the palette                                                                                        | boolean                           | false   |\n\nFor example, assign combo colors to a group of data by `category` field, so that combos of the same category have the same color:\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau is palette name, defaults to assign colors by ID\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Combo Common Options","order":"1"},"isInternal":false,"tokens":29525,"sizeBytes":118150},{"name":"BaseCombo.zh.md","path":"packages/site/docs/manual/element/combo/BaseCombo.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/BaseCombo.zh.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 组合通用配置项\norder: 1\n---\n\n本文介绍内置组合通用属性配置。\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {}, // 组合样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](#type)           | `circle` |      |\n| style     | 组合样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定组合类型，内置组合类型名称或自定义组合的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据组合数据动态选择组合类型：\n\n```js\nconst graph = new Graph({\n  combo: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形组合](/manual/element/combo/circle)\n- `rect`：[矩形组合](/manual/element/combo/rect)\n\n## Style\n\n定义组合的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据组合数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `组合: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为组合数据对象 (`ComboData`)，包含组合的所有数据信息。\n\n一个完整的组合由以下几部分构成：\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：组合的主图形，表示组合的主要形状，例如圆形、矩形等；\n- `label` ：文本标签，通常用于展示组合的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `badge` ：默认位于组合右上角的徽标；\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是组合的核心部分，定义了组合的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置组合的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为组合添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的组合：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前组合是否折叠                                                                          | boolean                       | false     |      |\n| cursor                          | 组合鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 组合填充色                                                                                | string                        | `#99ADD1` |      |\n| fillOpacity                     | 组合填充色透明度                                                                          | number \\| string              | 0.04      |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 组合描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 组合描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 组合描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 组合描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 组合描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 组合透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 组合如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 组合阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 组合阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 组合阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 组合阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 组合阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 组合大小，快捷设置组合宽高，[配置项](#size)                                               | number \\| number[]            | -         |      |\n| stroke                          | 组合描边色                                                                                | string                        | `#99ADD1` |      |\n| strokeOpacity                   | 组合描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定组合                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 组合是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 组合 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 组合 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 组合 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 组合渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n组合大小，快捷设置组合宽高，支持三种配置方式：\n\n- number：表示组合宽高相同为指定值\n- [number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度\n- [number, number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // 组合不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 收起时样式\n\n当组合处于收起状态时（`collapsed` 为 `true`），可以为其配置特殊的样式。收起时的样式属性以 `collapsed` 为前缀。\n\n#### 基础收起样式\n\n为收起状态的组合设置不同的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedFill: '#1783FF',\n      collapsedStroke: '#000',\n      collapsedLineWidth: 2,\n      collapsedSize: 40,\n      collapsedMarkerFill: '#fff',\n      collapsedMarkerFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时样式的完整配置：\n\n| 属性                                     | 描述                                                                                                  | 类型                          | 默认值                             | 必选 |\n| ---------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------------------------- | ---- |\n| collapsedCursor                          | 组合收起时的鼠标移入样式，[配置项](#cursor)                                                           | string                        | 默认与展开时的 cursor 一致         |      |\n| collapsedFill                            | 组合收起时的填充色                                                                                    | string                        | 默认与展开时的 fill 一致           |      |\n| collapsedFillOpacity                     | 组合收起时的填充色透明度                                                                              | number \\| string              | 1                                  |      |\n| collapsedIncreasedLineWidthForHitTesting | 组合收起时，当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0                                  |      |\n| collapsedLineCap                         | 组合收起时的描边端点样式                                                                              | `round` \\| `square` \\| `butt` | 默认与展开时的 lineCap 一致        |      |\n| collapsedLineDash                        | 组合收起时的描边虚线样式                                                                              | number[]                      | 默认与展开时的 lineDash 一致       |      |\n| collapsedLineDashOffset                  | 组合收起时的描边虚线偏移量                                                                            | number                        | 默认与展开时的 lineDashOffset 一致 |      |\n| collapsedLineJoin                        | 组合收起时的描边连接处样式                                                                            | `round` \\| `bevel` \\| `miter` | 默认与展开时的 lineJoin 一致       |      |\n| collapsedLineWidth                       | 组合收起时的描边宽度                                                                                  | number                        | 默认与展开时的 lineWidth 一致      |      |\n| collapsedMarker                          | 组合收起时是否显示标记，[配置项](#收起时标记样式)                                                     | boolean                       | true                               |      |\n| collapsedOpacity                         | 组合收起时的透明度                                                                                    | number \\| string              | 默认与展开时的 opacity 一致        |      |\n| collapsedShadowBlur                      | 组合收起时的阴影模糊度                                                                                | number                        | 默认与展开时的 shadowBlur 一致     |      |\n| collapsedShadowColor                     | 组合收起时的阴影颜色                                                                                  | string                        | 默认与展开时的 shadowColor 一致    |      |\n| collapsedShadowOffsetX                   | 组合收起时的阴影在 x 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetX 一致  |      |\n| collapsedShadowOffsetY                   | 组合收起时的阴影在 y 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetY 一致  |      |\n| collapsedShadowType                      | 组合收起时的阴影类型                                                                                  | `inner` \\| `outer`            | 默认与展开时的 shadowType 一致     |      |\n| collapsedSize                            | 组合收起时的大小                                                                                      | number \\| [number, number]    | 32                                 |      |\n| collapsedStroke                          | 组合收起时的描边色                                                                                    | string                        | 默认与展开时的 stroke 一致         |      |\n| collapsedStrokeOpacity                   | 组合收起时的描边色透明度                                                                              | number \\| string              | 默认与展开时的 strokeOpacity 一致  |      |\n| collapsedVisibility                      | 组合收起时是否可见                                                                                    | `visible` \\| `hidden`         | 默认与展开时的 visibility 一致     |      |\n\n### 收起时标记样式\n\n当 `collapsedMarker` 为 `true` 时显示的标记，用于显示收起组合内包含的元素数量。\n\n#### 自定义标记内容\n\n可以自定义收起标记显示的内容：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n      { id: 'node3', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerType: 'child-count',\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 14,\n      collapsedMarkerFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时标记样式的完整配置：\n\n| 属性                        | 描述                                                                                                                                                                                                                                                          | 类型                                                                                                   | 默认值        | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | ---- |\n| collapsedMarkerType         | 组合收起时显示的标记类型 <br> - `'child-count'`: 子元素数量（包括 Node 和 Combo）<br>- `'descendant-count'`: 后代元素数量（包括 Node 和 Combo）<br>- `'node-count'`: 后代元素数量（只包括 Node）<br> - `(children: NodeLikeData[]) => string`: 自定义处理逻辑 | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string) | `child-count` |      |\n| collapsedMarkerFill         | 标记文字颜色                                                                                                                                                                                                                                                  | string                                                                                                 | #fff          |      |\n| collapsedMarkerFillOpacity  | 标记文字颜色透明度                                                                                                                                                                                                                                            | number                                                                                                 | 1             |      |\n| collapsedMarkerFontSize     | 标记字体大小                                                                                                                                                                                                                                                  | number                                                                                                 | 12            |      |\n| collapsedMarkerFontWeight   | 标记字体粗细                                                                                                                                                                                                                                                  | number \\| string                                                                                       | `normal`      |      |\n| collapsedMarkerRadius       | 标记圆角半径                                                                                                                                                                                                                                                  | number                                                                                                 | 0             |      |\n| collapsedMarkerSrc          | 图片来源。其优先级高于 `collapsedMarkerText`                                                                                                                                                                                                                  | string                                                                                                 | -             |      |\n| collapsedMarkerText         | 标记文字                                                                                                                                                                                                                                                      | string                                                                                                 | -             |      |\n| collapsedMarkerTextAlign    | 标记文字水平对齐方式                                                                                                                                                                                                                                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                                                      | `center`      |      |\n| collapsedMarkerTextBaseline | 标记文字对齐基线                                                                                                                                                                                                                                              | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top`                            | `middle`      |      |\n| collapsedMarkerWidth        | 标记宽度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerHeight       | 标记高度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerZIndex       | 标记层级                                                                                                                                                                                                                                                      | number                                                                                                 | 1             |      |\n\n### 徽标样式\n\n徽标是组合上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为组合添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为组合添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 组合是否显示徽标   | boolean                               | true                              |\n| badgePalette | 组合徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 组合徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 组合徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 组合徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 组合徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 组合徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 组合徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 组合徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 组合徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 组合徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 组合徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 组合徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 组合徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 组合徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 组合徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 组合徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 组合徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 组合徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 组合徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | 组合徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 组合徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 组合徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 组合徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 组合徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 组合徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 组合徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 组合徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 组合徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 组合徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 组合徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 组合徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 组合徽标相对于组合主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 组合徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 组合徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 组合徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 组合徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 组合徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 组合徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 组合徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 组合徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 组合徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 组合徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 标签样式\n\n标签用于显示组合的文本信息，支持丰富的文本样式配置和灵活的位置布局。\n\n#### 基础标签配置\n\n为组合添加基本的文本标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '销售部门', // 标签文字内容\n      labelFill: '#1A1A1A', // 标签文字颜色\n      labelFontSize: 14, // 标签字体大小\n      labelPlacement: 'bottom', // 标签位置：底部\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n配置支持多行显示的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '这是一个支持多行显示的组合标签文本内容',\n      labelWordWrap: true, // 开启文本换行\n      labelMaxWidth: 100, // 最大宽度 100px\n      labelMaxLines: 3, // 最多显示 3 行\n      labelTextAlign: 'center', // 文本居中对齐\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义样式标签\n\n创建具有特殊样式的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // 红色文字\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // 粗体\n      labelFontStyle: 'italic', // 斜体\n      labelTextDecorationLine: 'underline', // 下划线\n      labelLetterSpacing: 2, // 字间距\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                                                                         | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示组合标签                                                                                                             | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入组合标签时显示的样式，[配置项](#cursor)                                                                              | string                                                                      | `default` |      |\n| labelFill                | 组合标签文字颜色                                                                                                             | string                                                                      | #000      |      |\n| labelFillOpacity         | 组合标签文字颜色的透明度                                                                                                     | number                                                                      | 1         |      |\n| labelFontFamily          | 组合标签字体族                                                                                                               | string                                                                      | -         |      |\n| labelFontSize            | 组合标签字体大小                                                                                                             | number                                                                      | 12        |      |\n| labelFontStyle           | 组合标签字体样式                                                                                                             | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 组合标签字体变种                                                                                                             | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 组合标签字体粗细                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |      |\n| labelLeading             | 行间距                                                                                                                       | number                                                                      | 0         |      |\n| labelLetterSpacing       | 组合标签字间距                                                                                                               | number \\| string                                                            | -         |      |\n| labelLineHeight          | 组合标签行高                                                                                                                 | number \\| string                                                            | -         |      |\n| labelMaxLines            | 组合标签最大行数                                                                                                             | number                                                                      | 1         |      |\n| labelMaxWidth            | 组合标签最大宽度，[配置项](#labelmaxwidth)                                                                                   | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 组合标签在 x 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelOffsetY             | 组合标签在 y 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelPadding             | 组合标签内边距                                                                                                               | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 组合标签相对于组合主图形的位置，[配置项](#labelplacement)                                                                    | string                                                                      | `bottom`  |      |\n| labelText                | 组合标签文字内容                                                                                                             | string                                                                      | -         |      |\n| labelTextAlign           | 组合标签文本水平对齐方式                                                                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 组合标签文本基线                                                                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 组合标签文本装饰线颜色                                                                                                       | string                                                                      | -         |      |\n| labelTextDecorationLine  | 组合标签文本装饰线                                                                                                           | string                                                                      | -         |      |\n| labelTextDecorationStyle | 组合标签文本装饰线样式                                                                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 组合标签文本溢出处理方式                                                                                                     | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 组合标签文本路径                                                                                                             | Path                                                                        | -         |      |\n| labelWordWrap            | 组合标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行                                           | boolean                                                                     | false     |      |\n| labelZIndex              | 组合标签渲染层级                                                                                                             | number                                                                      | 0         |      |\n| `label{StyleProps}`      | 更多标签样式配置，参考 [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) 属性值。比如 labelOpacity 代表标签透明度 | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |      |\n\n#### LabelPlacement\n\n标签相对于组合主图形的位置，可选值有：\n\n- `center`：标签位于组合中心\n- `top`、`bottom`、`left`、`right`：标签位于组合的上、下、左、右方\n- `top-left`、`top-right`、`bottom-left`、`bottom-right`：标签位于组合的四个角\n- `left-top`、`left-bottom`、`right-top`、`right-bottom`：标签位于组合边的端点\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于组合元素宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过组合宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景为标签文字提供背景装饰，可以提升标签的可读性和视觉效果。\n\n#### 基础背景样式\n\n为标签添加简单的背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '重要组合',\n      labelFill: '#fff', // 白色文字\n      labelBackground: true, // 启用背景\n      labelBackgroundFill: '#1783FF', // 蓝色背景\n      labelBackgroundPadding: [4, 8], // 内边距：垂直4px，水平8px\n      labelBackgroundRadius: 4, // 圆角半径\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 渐变背景效果\n\n创建带渐变效果的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP组合',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // 渐变背景\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // 大圆角\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 描边背景样式\n\n创建只有描边的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '边框标签',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // 透明背景\n      labelBackgroundStroke: '#1783FF', // 蓝色描边\n      labelBackgroundLineWidth: 2, // 描边宽度\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签背景样式配置：\n\n| 属性                          | 描述                                                                                                                                           | 类型                                                         | 默认值       |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | 组合标签背景是否显示                                                                                                                           | boolean                                                      | false        |\n| labelBackgroundCursor         | 组合标签背景鼠标移入样式，[配置项](#cursor)                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | 组合标签背景填充色                                                                                                                             | string                                                       | #000         |\n| labelBackgroundFillOpacity    | 组合标签背景透明度                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | 组合标签背景高度                                                                                                                               | string \\| number                                             | -            |\n| labelBackgroundLineDash       | 组合标签背景虚线配置                                                                                                                           | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | 组合标签背景虚线偏移量                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | 组合标签背景描边线宽                                                                                                                           | number                                                       | -            |\n| labelBackgroundPadding        | 组合标签背景内间距                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | 组合标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充                                 | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | 组合标签背景阴影模糊程度                                                                                                                       | number                                                       | -            |\n| labelBackgroundShadowColor    | 组合标签背景阴影颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | 组合标签背景阴影 X 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | 组合标签背景阴影 Y 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundStroke         | 组合标签背景描边颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | 组合标签背景描边透明度                                                                                                                         | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | 组合标签背景是否可见                                                                                                                           | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | 组合标签背景渲染层级                                                                                                                           | number                                                       | 1            |\n| `labelBackground{StyleProps}` | 更多标签背景样式配置，参考 [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) 属性值。例如 labelBackgroundOpacity 代表标签背景透明度 | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### 光晕样式\n\n光晕效果用于突出显示组合，通常在鼠标悬停、选中或激活状态下使用，为组合周围添加发光效果。\n\n#### 基础光晕效果\n\n为组合添加简单的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // 启用光晕\n      haloStroke: '#1783FF', // 蓝色光晕\n      haloLineWidth: 8, // 光晕宽度\n      haloStrokeOpacity: 0.3, // 光晕透明度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色光晕效果\n\n创建彩色渐变的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // 红色光晕\n      haloLineWidth: 12, // 较粗的光晕\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // 模糊滤镜效果\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 动态光晕效果\n\n在状态切换时使用光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // 默认状态下不显示光晕\n      halo: false,\n    },\n    state: {\n      // 悬停状态显示橙色光晕\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // 选中状态显示绿色光晕\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性               | 描述                                                                                                                                           | 类型                                                                  | 默认值                       | 必选 |\n| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------- | ---- |\n| halo               | 是否显示组合光晕                                                                                                                               | boolean                                                               | false                        |      |\n| haloCursor         | 组合光晕鼠标移入样式，[配置项](#cursor)                                                                                                        | string                                                                | `default`                    |      |\n| haloDraggable      | 组合光晕是否允许拖拽                                                                                                                           | boolean                                                               | true                         |      |\n| haloDroppable      | 组合光晕是否允许接收被拖拽的元素                                                                                                               | boolean                                                               | false                        |      |\n| haloFill           | 光晕填充色                                                                                                                                     | string                                                                | 与主图形的填充色 `fill` 一致 |      |\n| haloFillRule       | 组合光晕填充规则                                                                                                                               | `nonzero` \\| `evenodd`                                                | -                            |      |\n| haloFilter         | 组合光晕滤镜效果，如 'blur(2px)' 可创建模糊效果                                                                                                | string                                                                | -                            |      |\n| haloLineWidth      | 组合光晕描边宽度，控制光晕的粗细程度                                                                                                           | number                                                                | 12                           |      |\n| haloPointerEvents  | 组合光晕效果是否响应指针事件，[配置项](#pointerevents)                                                                                         | string                                                                | `none`                       |      |\n| haloStroke         | 组合光晕描边色，**此属性用于设置组合周围光晕的颜色，帮助突出显示组合**                                                                         | string                                                                | `#99add1`                    |      |\n| haloStrokeOpacity  | 组合光晕描边色透明度，建议使用 0.2-0.6 的值以获得自然的光晕效果                                                                                | number                                                                | 0.25                         |      |\n| haloVisibility     | 组合光晕可见性                                                                                                                                 | `visible` \\| `hidden`                                                 | `visible`                    |      |\n| haloZIndex         | 组合光晕渲染层级，通常设置为负值以确保光晕在组合主图形下方                                                                                     | number                                                                | -1                           |      |\n| `halo{StyleProps}` | 更多光晕样式配置，参考 [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) 配置项。例如 haloFillOpacity 代表光晕填充色透明度 | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                            |      |\n\n**光晕使用建议：**\n\n1. **性能考虑**：光晕效果会增加渲染负担，建议在必要时才启用\n2. **颜色搭配**：光晕颜色应与组合主色调协调，避免过于突兀\n3. **透明度设置**：合理的透明度（0.2-0.6）可以创造自然的光晕效果\n4. **状态应用**：光晕通常用于 hover、selected、active 等交互状态\n\n### 图标样式\n\n图标用于在组合中显示文字或图片内容，通常位于组合的中心位置，可以用来表示组合的类型或功能。\n\n#### 文字图标\n\n使用文字作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // 显示字母 A\n      iconFill: '#1783FF', // 蓝色文字\n      iconFontSize: 24, // 大字体\n      iconFontWeight: 'bold', // 粗体\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 图片图标\n\n使用图片作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色文字图标\n\n创建带有特殊样式的文字图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: '部门',\n      iconFill: '#FF4D4F', // 红色文字\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // 斜体\n      iconTextDecorationLine: 'underline', // 下划线\n      iconLetterSpacing: 1, // 字间距\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                                                         | 类型                                                                        | 默认值           |\n| ----------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示组合图标                                                             | boolean                                                                     | true             |\n| iconCursor              | 组合图标鼠标移入样式，[配置项](#cursor)                                      | string                                                                      | `default`        |\n| iconFill                | 组合图标文字颜色                                                             | string                                                                      | -                |\n| iconFillOpacity         | 组合图标文字颜色透明度                                                       | number                                                                      | 1                |\n| iconFontFamily          | 组合图标字体族                                                               | string                                                                      | -                |\n| iconFontSize            | 组合图标字体大小                                                             | number                                                                      | 16               |\n| iconFontStyle           | 组合图标字体样式                                                             | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 组合图标字体变种                                                             | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 组合图标字体粗细                                                             | number \\| string                                                            | `normal`         |\n| iconHeight              | 组合图标高度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 组合图标文本字间距                                                           | number \\| string                                                            | -                |\n| iconLineHeight          | 组合图标文本行高                                                             | number \\| string                                                            | -                |\n| iconMaxLines            | 组合图标文本最大行数                                                         | number                                                                      | 1                |\n| iconOffsetX             | 组合图标在 x 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOffsetY             | 组合图标在 y 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOpacity             | 组合图标透明度                                                               | number                                                                      | 1                |\n| iconRadius              | 组合图标圆角半径（仅对矩形图标有效）                                         | number                                                                      | 0                |\n| iconSrc                 | 组合图片来源。其优先级高于 iconText，支持本地图片和网络图片                  | string                                                                      | -                |\n| iconText                | 组合图标文字内容，支持文字、Unicode 字符等                                   | string                                                                      | -                |\n| iconTextAlign           | 组合图标文本水平对齐方式                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`         |\n| iconTextBaseline        | 组合图标文本基线                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`         |\n| iconTextDecorationColor | 组合图标文本装饰线颜色                                                       | string                                                                      | -                |\n| iconTextDecorationLine  | 组合图标文本装饰线，如下划线、删除线等                                       | string                                                                      | -                |\n| iconTextDecorationStyle | 组合图标文本装饰线样式                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 组合图标文本溢出处理方式                                                     | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconVisibility          | 组合图标是否可见                                                             | `visible` \\| `hidden`                                                       | `visible`        |\n| iconWidth               | 组合图标宽度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 组合图标文本是否自动换行                                                     | boolean                                                                     | false            |\n| iconZIndex              | 组合图标渲染层级                                                             | number                                                                      | 1                |\n| `icon{StyleProps}`      | 更多图标样式配置，参考图标的具体类型配置项。例如 iconStroke 代表图标描边颜色 | -                                                                           | -                |\n\n**图标使用建议：**\n\n1. **优先级**：`iconSrc`（图片）的优先级高于 `iconText`（文字），如果同时设置，会优先显示图片\n2. **尺寸控制**：建议根据组合大小合理设置图标尺寸，避免图标过大或过小影响视觉效果\n3. **性能优化**：使用文字图标性能更好，图片图标需要额外的网络请求和渲染开销\n4. **样式一致性**：在同一个图中的组合图标样式应保持一致，提升整体视觉效果\n5. **可访问性**：确保图标颜色与背景有足够的对比度，便于用户识别\n\n## State\n\n在一些交互行为中，比如点击选中一个组合或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\n例如，当组合处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义组合的动画效果，支持下列两种配置方式：\n\n1. 关闭组合全部动画\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指组合在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 组合进入画布时的动画\n- `update`: 组合更新时的动画\n- `exit`: 组合离开画布时的动画\n- `show`: 组合从隐藏状态显示时的动画\n- `hide`: 组合隐藏时的动画\n- `collapse`: 组合收起时的动画\n- `expand`: 组合展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置组合，如：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // 关闭组合入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义组合的色板，即预定义组合颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                              | 默认值  |\n| ------ | ------------------------------------------------------------------- | --------------------------------- | ------- |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` &#124; `value`            | `group` |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string &#124; ((datum) => string) | `id`    |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string &#124; string[]            | -       |\n| invert | 是否反转色板                                                        | boolean                           | false   |\n\n如将一组数据按 `category` 字段分配组合颜色，使得同类别的组合颜色相同：\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"组合通用配置项","order":"1"},"isInternal":false,"tokens":19736,"sizeBytes":90810},{"name":"CircleCombo.en.md","path":"packages/site/docs/manual/element/combo/CircleCombo.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/CircleCombo.en.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Circle Combo\norder: 2\n---\n\n## Overview\n\nThe circular combo wraps child nodes or child combos with a circular boundary, suitable for representing equal or non-hierarchical group relationships.\n\nApplicable scenarios:\n\n- Suitable for representing node groups without a clear hierarchical relationship. The circular combo can reflect the equality of members, such as user groups in social networks or decentralized team structures (highlighting collaboration).\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example shows the distribution of interest group members:\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","frontmatter":{"title":"Circle Combo","order":"2"},"isInternal":false,"tokens":226,"sizeBytes":903},{"name":"CircleCombo.zh.md","path":"packages/site/docs/manual/element/combo/CircleCombo.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/CircleCombo.zh.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 圆形组合 Circle\norder: 2\n---\n\n## 概述\n\n圆形组合以圆形边界包裹子节点或子组合，适合表示平等或非层级化的群组关系。\n\n适用场景：\n\n- 适合表示无明确层级关系的节点群组，圆形组合能体现成员的平等性，如社交网络中的用户群体、分散式团队结构（突出协作性）。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为兴趣小组人员分布：\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n","frontmatter":{"title":"圆形组合 Circle","order":"2"},"isInternal":false,"tokens":105,"sizeBytes":746},{"name":"custom-combo.en.md","path":"packages/site/docs/manual/element/combo/custom-combo.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/custom-combo.en.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Combo\norder: 4\n---\n\nG6 provides two types of [built-in combos](/en/manual/element/combo/base-combo): circular combos and rectangular combos. However, in complex business scenarios, you may need to create custom combos with specific styles, interactive effects, or behavior logic.\n\n## Before You Start: Understanding the Basic Composition of Combos\n\nIn G6, a complete combo typically consists of the following parts:\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the main shape of the combo, such as a circle, rectangle, etc.\n- `label`: Text label, usually used to display the name or description of the combo.\n- `halo`: A graphic that displays a halo effect around the main graphic.\n\n### Special Characteristics of Combos\n\nCombos differ from ordinary nodes and have the following characteristics:\n\n1. **Containment**: Combos can contain nodes and other combos, forming a hierarchical structure.\n2. **Two States**: Expanded and Collapsed states.\n3. **Adaptive Size**: Automatically adjusts size based on internal elements.\n4. **Drag Behavior**: Supports overall dragging and dragging elements in/out.\n\n## Ways to Customize Combos <Badge type=\"warning\">Choose the Right Way</Badge>\n\nThere are two ways to create custom combos:\n\n### 1. Inherit Existing Combo Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most common way, and you can choose to inherit one of the following types:\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - The most basic combo class, providing core functionality for combos.\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - Circular combo.\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - Rectangular combo.\n\n**Why choose this way?**\n\n- 📌 **Less Code**: Reuse existing combo properties and methods, focusing only on new features.\n- 📌 **Fast Development**: Suitable for most project needs, quickly achieving business goals.\n- 📌 **Easy Maintenance**: Clear code structure and clear inheritance relationships.\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing combo types (recommended), you can jump directly to [Create Your First Custom Combo in Three Steps](#create-your-first-custom-combo-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Develop from Scratch Based on the G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing combo types do not meet your needs, you can create combos from scratch based on the underlying graphics system of G.\n\n**Why choose this way?**\n\n- 📌 **Maximum Freedom**: Full control over every detail of the combo, achieving any complex effect.\n- 📌 **Special Needs**: Highly customized scenarios that existing combo types cannot meet.\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios.\n\n:::warning{title=Note}\nDeveloping custom combos from scratch requires handling all details yourself, including graphic drawing, event response, state changes, expand/collapse logic, etc., which is quite challenging. You can directly refer to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) for implementation.\n:::\n\n## Create Your First Custom Combo in Three Steps\n\nLet's start by inheriting `BaseCombo` to implement a custom hexagon combo:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// Define the path for the collapsed state button\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// Define the path for the expanded state button\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the expand/collapse button, using paths for finer control\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Override the render method to add more custom graphics\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // Use lifecycle hooks to add event listeners\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// Register the custom combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// Create a graph instance and use the custom combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Step 1: Write the Custom Combo Class\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// Define button path generation functions\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic, directly using path data\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic, using path type to directly pass in style objects\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the collapse/expand button, using SVG paths for finer control\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Use lifecycle hook methods to bind events\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### Step 2: Register the Custom Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### Step 3: Apply the Custom Combo\n\n```js\nconst graph = new Graph({\n  // ...other configurations\n  combo: {\n    type: 'hexagon-combo', // Use the name registered\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // Since we implemented the collapse/expand feature ourselves, only drag behavior is needed here\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 Congratulations! You have created your first custom combo.\n\n## Going Further: Understanding the Principles of Combo Drawing\n\n### Differences Between Combos and Nodes\n\nAlthough Combos inherit from `BaseNode`, there are some key differences:\n\n1. **Adaptive Size**: Combos automatically calculate the appropriate size based on internal elements.\n2. **Expand/Collapse States**: Combos have two display states and need to handle state transitions.\n3. **Hierarchical Structure**: Combos can be nested, forming hierarchical relationships.\n4. **Internal Element Management**: Combos need to manage the nodes and sub-combos they contain.\n\n### Atomic Graphics\n\nG6's Combos are drawn using atomic graphic units provided by the [G Graphics System](https://g.antv.antgroup.com/). For an introduction to atomic graphics, please refer to the [Element - Shape (Optional)](/en/manual/element/shape/overview) documentation.\n\nAll these graphics can be dynamically created or updated using `upsert()` and automatically manage graphic states and lifecycles.\n\n### Element Base Class\n\nBefore customizing Combos, you need to understand some important properties and methods in the G6 element base class:\n\n#### Properties\n\n| Property   | Type                          | Description                                               |\n| ---------- | ----------------------------- | --------------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under the current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under the current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom Combos, you will frequently use the `upsert` method. It is short for \"update or insert\" and is responsible for adding or updating graphics in the element:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| key       | string                                  | Key of the graphic, corresponding to the key in `shapeMap`. Built-in keys include `'key'`, `'label'`, `'halo'`, `'icon'`, `'port'`, `'badge'`<br/> Keys should not use special symbols, and will be converted to camel case to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                  |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                 |\n\nFor example, insert a fixed-position purple circle:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics with `container.appendChild()`? Because:\n\n1. **Better Performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and recreating them, greatly improving rendering performance.\n2. **Simpler Code**: No need to manually check if elements exist.\n3. **Easy Management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, and you can easily access them with `this.getShape(key)`.\n\n#### `render(attributes, container)`: Main Entry for Rendering Combos\n\nEvery custom combo class must implement the `render(attributes, container)` method, which defines how the combo is \"drawn\". You can use various atomic graphics here to create the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation or have interactions between sub-graphics. In this case, the `getShape` method can help you access any graphics previously created with `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, make sure A is created first.\n\n### Element Conventions\n\n- **Use Convention Properties**\n\nThe convention properties in combos include:\n\n- Use `this.getKeySize(attributes)` to get the size of the combo, considering the collapsed state and sub-elements.\n- Use `this.getContentBBox(attributes)` to get the bounding box of the content area.\n- Use `this.getComboPosition(attributes)` to get the current position of the combo, based on state and sub-elements.\n\n- **Use `getXxxStyle` and `drawXxxShape` Pairing for Graphic Drawing**\n\n`getXxxStyle` is used to get the graphic style, and `drawXxxShape` is used to draw the graphic. Graphics created this way support automatic animation execution.\n\n> `Xxx` is the camel case form of the key passed to the [upsert](#methods) method.\n\n- **Access Graph Context via `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, and you can override these methods in custom combos to execute specific logic at key moments:\n\n| Hook Function | Trigger Timing                                                     | Typical Use Cases                                                                |\n| ------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| `onCreate`    | After the combo is created and the entrance animation is completed | Bind interactive events, initialize combo state, add external listeners          |\n| `onUpdate`    | After the combo is updated and the update animation is completed   | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | After the combo is destroyed and the exit animation is completed   | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"drawing logic\"**.\n\nYou can define styles for each state in the combo configuration:\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\nThis state will be passed into the `render()` method's `attributes` and automatically applied to the graphics as a result of the internal system merging.\n\nYou can also customize rendering logic based on the state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","frontmatter":{"title":"Custom Combo","order":"4"},"isInternal":false,"tokens":5075,"sizeBytes":20315},{"name":"custom-combo.zh.md","path":"packages/site/docs/manual/element/combo/custom-combo.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/custom-combo.zh.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义 Combo\norder: 4\n---\n\nG6 提供了两种 [内置组合](/manual/element/combo/base-combo) 类型：圆形组合和矩形 Combo 。但在复杂的业务场景中，你可能需要创建具有特定样式、交互效果或行为逻辑的自定义 Combo 。\n\n## 开始之前：了解 Combo 的基本构成\n\n在 G6 中，一个完整的 Combo 通常由以下几个部分组成：\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ： Combo 的主图形，表示 Combo 的主要形状，如圆形、矩形等；\n- `label` ：文本标签，通常用于展示 Combo 的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n\n### Combo 的特殊性\n\nCombo 不同于普通节点，它具有以下特性：\n\n1. **包含性**： Combo 可以包含节点和其他 Combo ，形成层级结构\n2. **两种状态**：展开(Expanded)和收起(Collapsed)状态\n3. **自适应大小**：根据内部元素动态调整大小\n4. **拖拽行为**：支持整体拖拽及内部元素拖入/拖出\n\n## 自定义 Combo 的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义 Combo 的方式有两种途径：\n\n### 1. 继承现有 Combo 类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - 最基础的 Combo 类，提供 Combo 的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - 圆形 Combo\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - 矩形 Combo\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有 Combo 的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有组合类型（推荐），可以直接跳到 [三步创建你的第一个自定义 Combo](#三步创建你的第一个自定义-combo) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有 Combo 类型都不满足需求，你可以基于 G 的底层图形系统从零创建 Combo。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制 Combo 的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有 Combo 类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义 Combo 需要自行处理所有细节，包括图形绘制、事件响应、状态变化、展开/收起逻辑等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义 Combo\n\n让我们从继承 `BaseCombo` 开始，实现一个自定义六边形 Combo ：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// 定义收起状态的按钮路径\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// 定义展开状态的按钮路径\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建SVG路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制展开/收起按钮，使用路径实现更精细的控制\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 重写render方法，添加更多自定义图形\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // 使用生命周期钩子添加事件监听\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// 注册自定义 Combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// 创建图实例并使用自定义 Combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义 Combo 类\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// 定义按钮路径生成函数\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建 SVG 路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式，直接使用路径数据\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形，使用 path 类型直接传入样式对象\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制收起/展开按钮，使用 SVG 路径实现更精细的控制\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 使用生命周期钩子方法绑定事件\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### 第二步：注册自定义 Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### 第三步：应用自定义 Combo\n\n```js\nconst graph = new Graph({\n  // ...其他配置\n  combo: {\n    type: 'hexagon-combo', // 使用注册时的名称\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // 由于我们自己实现了折叠展开功能，这里只需要拖拽行为\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 恭喜！你已经创建了第一个自定义 Combo 。\n\n## 更进一步：理解 Combo 绘制的原理\n\n### Combo 与节点的区别\n\n虽然 Combo 继承自 `BaseNode`，但有一些关键区别：\n\n1. **自适应大小**： Combo 会根据内部元素自动计算合适的大小\n2. **展开/收起状态**： Combo 有两种显示状态，并需要处理状态切换\n3. **层级结构**： Combo 可以嵌套，形成层级关系\n4. **内部元素管理**： Combo 需要管理其包含的节点和子 Combo\n\n### 原子图形\n\nG6 的 Combo 是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。原子图形的介绍请参考 [元素 - 图形（可选）](/manual/element/shape/overview) 文档。\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义 Combo 之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义 Combo 时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见 [元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                                |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                          |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染组合的主入口\n\n每个自定义 Combo 类都必须实现 `render(attributes, container)` 方法，它定义了该组合如何被\"绘制\"出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n组合中约定的元素属性包括：\n\n- 通过 `this.getKeySize(attributes)` 获取组合的尺寸，考虑折叠状态和子元素\n- 通过 `this.getContentBBox(attributes)` 获取内容区域的边界盒\n- 通过 `this.getComboPosition(attributes)` 获取组合的当前位置，基于状态和子元素\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义 Combo 中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                   | 典型用途                                     |\n| ----------- | -------------------------- | -------------------------------------------- |\n| `onCreate`  | 当组合创建后完成入场动画时 | 绑定交互事件、初始化组合状态、添加外部监听器 |\n| `onUpdate`  | 当组合更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果     |\n| `onDestroy` | 当组合完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知       |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **\"状态响应\"** 与 **\"绘制逻辑\"** 分离。\n\n你可以在组合配置中定义每种状态下的样式：\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n","frontmatter":{"title":"自定义 Combo","order":"4"},"isInternal":false,"tokens":3534,"sizeBytes":18419},{"name":"overview.en.md","path":"packages/site/docs/manual/element/combo/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/overview.en.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Combo Overview\norder: 0\n---\n\n## What is a Combo\n\nA Combo, short for Combination, is a special type of graph element in G6 that can contain nodes and sub-combos, similar to the concept of \"groups\" or \"containers.\" It is typically used to represent set relationships, such as a department containing multiple employees or a city containing multiple regions.\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=Note}\nIt is not recommended to use Combos in **tree graphs**. The layout mechanism of tree graphs is incompatible with that of Combos, which can lead to node misalignment or style confusion.\n:::\n\nG6 has built-in Combos including `circle` (circular combo) and `rect` (rectangular combo), as shown in the images below:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## Data Structure\n\nWhen defining a Combo, you need to add a `combos` field to the graph's data object. Each Combo is an object with the following structure:\n\n| Attribute | Description                                                                                            | Type           | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------ | -------------- | ------- | -------- |\n| id        | Unique identifier of the combo                                                                         | string         | -       | ✓        |\n| type      | Combo type, name of built-in combo type or custom combo name, such as `circle` or `rect`               | string         | -       |          |\n| data      | Combo data, used to store custom data of the combo, accessible via callback functions in style mapping | object         | -       |          |\n| style     | Combo style                                                                                            | object         | -       |          |\n| states    | Initial states of the combo                                                                            | string[]       | -       |          |\n| combo     | Parent combo ID. If there is no parent combo, it is null                                               | string \\| null | -       |          |\n\nAn example of a data item in the `combos` array:\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\nTo assign a node to a Combo, you can add a `combo` field to the node data:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 belongs to comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // define comboA\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure Combos, listed in order of priority from highest to lowest:\n\n- Use `graph.setCombo()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setCombo()`\n\nYou can dynamically set the style mapping logic of Combos using `graph.setCombo()` after the graph instance is created.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nYou can configure Combo style mapping globally during graph instantiation. This configuration will apply to all Combos.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Specify combo type and combo style type in the combo configuration\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different Combos, you can write the configuration into the Combo data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\n// Specify combo type and combo style type in the data\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## Example\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo Interaction\n\nSimply rendering a Combo does not provide much practical value; it is only when a series of interactive operations are supported that the value of Combos can be maximized.\n\nIn G6, we have built-in interactions such as `drag-element` and `collapse-expand`.\n\n#### drag-element\n\nSupports dragging nodes and Combos. During the dragging of a Combo, the positions of nodes and edges within the Combo will dynamically change. After dragging is complete, the relative positions of the Combo and nodes remain unchanged. You can also change the affiliation of the Combo during dragging by setting `dropEffect: 'link'`.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\nSupports double-clicking a Combo to collapse and expand it. After collapsing a Combo, all nodes within the Combo are hidden. If there are connections between external nodes and nodes within the Combo, all connections will connect to the Combo.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## Custom Combos\n\nWhen built-in Combos cannot meet your needs, G6 provides powerful customization capabilities:\n\n- Extend built-in Combos\n- Create new Combo types\n\nUnlike Combos, custom Combos need to be registered before use. For detailed tutorials, please refer to the [Custom Combo](/en/manual/element/combo/custom-combo) documentation.\n","frontmatter":{"title":"Combo Overview","order":"0"},"isInternal":false,"tokens":2060,"sizeBytes":8242},{"name":"overview.zh.md","path":"packages/site/docs/manual/element/combo/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/overview.zh.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 组合总览\norder: 0\n---\n\n## 什么是组合\n\n组合(Combo) 全称为 Combination，是 G6 中的一种特殊的图元素，它可以包含节点和子组合，类似“群组”或“容器”的概念。它通常用于表示集合关系，例如一个部门包含多个员工，一个城市包含多个区域等。\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=注意}\n不推荐在**树图**中使用 Combo。因为树图的布局与 Combo 的布局机制不兼容，容易导致节点错位或样式混乱。\n:::\n\nG6 的内置 Combo 包括 `circle`（圆形组合）和 `rect` (矩形组合) 两种类型，分别如下图所示：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## 数据结构\n\n定义 Combo 时，需要在图的数据对象中添加 `combos` 字段，每个 Combo 是一个对象，结构如下：\n\n| 属性   | 描述                                                                    | 类型           | 默认值 | 必选 |\n| ------ | ----------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                        | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称，比如 `circle` 或者 `rect` | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取    | object         | -      |      |\n| style  | 组合样式                                                                | object         | -      |      |\n| states | 组合初始状态                                                            | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                              | string \\| null | -      |      |\n\n`combos` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n要将节点归属到某个 Combo，可以在节点数据中添加 `combo` 字段：\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 属于 comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // 定义 comboA\n}\n```\n\n## 配置方法\n\n配置 Combo 的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setCombo()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setCombo()`\n\n可在图实例创建后，使用 `graph.setCombo()` 动态设置 Combo 的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `combo` 配置 Combo 样式映射，这里的配置是全局的配置，将会在所有 Combo 上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 在组合配置中指定组合类型以及组合样式类型\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同 Combo 进行不同的配置，可以将配置写入到 Combo 数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\n// 在数据中指定组合类型以及组合样式类型\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## 示例\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo 交互\n\n只是简单地将 Combo 渲染出来，并没有多大的实用价值，只有支持一系列的交互操作后，才能最大程度地体现 Combo 的价值。\n\n在 G6 中，我们内置了 `drag-element`、`collapse-expand` 三个交互。\n\n#### drag-element\n\n支持拖动节点和 Combo。拖动 Combo 过程中，会动态改变 Combo 中节点和边的位置，在拖拽完成以后，保持 Combo 和节点的相对位置不变。还可以通过设置 `dropEffect: 'link'` 在拖拽时改变 Combo 的从属关系。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\n支持双击 Combo 收起和展开 Combo ，收起 Combo 以后，隐藏 Combo 中的所有节点，外部节点和 Combo 中节点有连线的情况下，所有连接会连接到 Combo 上面。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## 自定义组合\n\n当内置组合无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置组合进行扩展\n- 创建全新的组合类型\n\n与组合不同，自定义组合需要先注册后使用。详细教程请参考 [自定义组合](/manual/element/combo/custom-combo) 文档。\n","frontmatter":{"title":"组合总览","order":"0"},"isInternal":false,"tokens":1415,"sizeBytes":7521},{"name":"RectCombo.en.md","path":"packages/site/docs/manual/element/combo/RectCombo.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/RectCombo.en.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Rect Combo\norder: 3\n---\n\n## Overview\n\nThe rectangular combo organizes content with right-angle boundaries, supporting strict hierarchical structures.\n\nApplicable scenarios:\n\n- **System Architecture Diagrams**: Such as service layering within system architecture, and subdivisions within each layer.\n- **Geographical Area Division**: Such as cities containing multiple areas, where the rectangular combo can intuitively display administrative boundaries or functional divisions.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example is a simple microservice architecture service layer:\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","frontmatter":{"title":"Rect Combo","order":"3"},"isInternal":false,"tokens":232,"sizeBytes":927},{"name":"RectCombo.zh.md","path":"packages/site/docs/manual/element/combo/RectCombo.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/combo/RectCombo.zh.md","title":"Combo Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 矩形组合 Rect\norder: 3\n---\n\n## 概述\n\n矩形组合以直角边界组织内容，支持严格的层级结构。\n\n适用场景：\n\n- **系统架构图**：如系统架构里面的服务分层，以及每层服务里面的细分等。\n- **地理区域划分**：如城市包含多个区域，矩形组合能直观展示行政边界或功能分区。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为简单的微服务架构服务层：\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n","frontmatter":{"title":"矩形组合 Rect","order":"3"},"isInternal":false,"tokens":108,"sizeBytes":758},{"name":"BaseEdge.en.md","path":"packages/site/docs/manual/element/edge/BaseEdge.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/BaseEdge.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Edge Common Configuration\norder: 1\n---\n\nThis document introduces the built-in edge common property configurations.\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // Edge type\n    style: {}, // Edge style\n    state: {}, // State styles\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name         | [Type](#type)           | `line`  |          |\n| style     | Edge style configuration, including color, thickness, etc.     | [Style](#style)         | -       |          |\n| state     | Style configuration for different states                       | [State](#state)         | -       |          |\n| palette   | Define edge palette for mapping colors based on different data | [Palette](#palette)     | -       |          |\n| animation | Define edge animation effects                                  | [Animation](#animation) | -       |          |\n\n## Type\n\nSpecify the edge type, built-in edge type name or custom edge name. Default is `line` (straight line edge). **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select edge types based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    // Static configuration\n    type: 'line',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `line`: [Straight line edge](/en/manual/element/edge/line)\n- `polyline`: [Polyline edge](/en/manual/element/edge/polyline)\n- `cubic`: [Cubic Bezier curve edge](/en/manual/element/edge/cubic)\n- `cubic-horizontal`: [Horizontal cubic Bezier curve edge](/en/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`: [Vertical cubic Bezier curve edge](/en/manual/element/edge/cubic-vertical)\n- `quadratic`: [Quadratic Bezier curve edge](/en/manual/element/edge/quadratic)\n\n## Style\n\nDefine edge styles, including color, thickness, etc.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // Static configuration\n      stroke: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineDash: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Edge: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the edge data object (`EdgeData`), containing all data information of the edge.\n\nA complete edge consists of the following parts:\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the main path of the edge, such as straight lines, curves, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `badge`: Badge on the edge\n- `halo`: The halo effect graphic displayed around the main graphic\n- `startArrow`: Arrow at the starting end of the edge\n- `endArrow`: Arrow at the ending end of the edge\n\nThe following style configurations will be explained by atomic graphics in order:\n\n### Main Graphic Styles\n\nThe main graphic is the core part of the edge, defining the basic path and appearance of the edge. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // Blue edge\n      lineWidth: 2, // Edge width\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Line Style\n\nCreate edges with dashed line style:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // Dashed line style\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Shadow Effect\n\nAdd shadow effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                        | Type                  | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------- | -------- |\n| cursor                          | Mouse cursor style when hovering over edge, [options](#cursor)                                                                     | string                | `default` |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. We can increase this area to make \"thin lines\" easier to pick up | number                | 0         |          |\n| lineDash                        | Edge dash line style                                                                                                               | number[]              | -         |          |\n| lineDashOffset                  | Edge dash line offset                                                                                                              | number                | 0         |          |\n| lineWidth                       | Edge width                                                                                                                         | number                | 1         |          |\n| opacity                         | Edge opacity                                                                                                                       | number \\| string      | 1         |          |\n| pointerEvents                   | How edge responds to pointer events, [options](#pointerevents)                                                                     | string                | `auto`    |          |\n| shadowBlur                      | Edge shadow blur                                                                                                                   | number                | -         |          |\n| shadowColor                     | Edge shadow color                                                                                                                  | string                | -         |          |\n| shadowOffsetX                   | Edge shadow offset in x direction                                                                                                  | number \\| string      | -         |          |\n| shadowOffsetY                   | Edge shadow offset in y direction                                                                                                  | number \\| string      | -         |          |\n| shadowType                      | Edge shadow type                                                                                                                   | `inner` \\| `outer`    | `outer`   |          |\n| sourcePort                      | Connection port at the source end of the edge                                                                                      | string                | -         |          |\n| stroke                          | Edge color                                                                                                                         | string                | `#000`    |          |\n| strokeOpacity                   | Edge color opacity                                                                                                                 | number \\| string      | 1         |          |\n| targetPort                      | Connection port at the target end of the edge                                                                                      | string                | -         |          |\n| transform                       | Transform property allows you to rotate, scale, skew, or translate the given edge                                                  | string                | -         |          |\n| transformOrigin                 | The center of rotation and scaling, also known as the transform center                                                             | string                | -         |          |\n| visibility                      | Whether the edge is visible                                                                                                        | `visible` \\| `hidden` | `visible` |          |\n| zIndex                          | Edge rendering layer                                                                                                               | number                | 1         |          |\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, both `stroke` and `visibility` can independently or in combination affect hit testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Never becomes a target for responding to events\n- **`visiblepainted`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n- **`visiblestroke`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`visible`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`painted`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`stroke`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Responds to events as long as entering the graphic stroke area, not affected by `stroke` or `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely non-responsive to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // Edge does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Styles\n\nLabels are used to display text information for edges, supporting various style configurations and layout options. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Edge Label',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'This is a very long edge label that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdd background to labels for better readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Important Connection',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Auto-rotating Label\n\nLabels can automatically rotate to align with edge direction:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Auto Rotate',\n      labelAutoRotate: true, // Auto rotate\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete label style configuration:\n\n| Property                 | Description                                                                                                     | Type                                                                        | Default   | Required |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show edge label                                                                                      | boolean                                                                     | true      |          |\n| labelAutoRotate          | Whether edge label automatically rotates to align with edge direction                                           | boolean                                                                     | true      |          |\n| labelCursor              | Mouse cursor style when hovering over edge label, [options](#cursor)                                            | string                                                                      | `default` |          |\n| labelFill                | Edge label text color                                                                                           | string                                                                      | -         |          |\n| labelFontFamily          | Edge label font family                                                                                          | string                                                                      | -         |          |\n| labelFontSize            | Edge label font size                                                                                            | number                                                                      | 12        |          |\n| labelFontStyle           | Edge label font style                                                                                           | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Edge label font variant                                                                                         | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Edge label font weight                                                                                          | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                    | number                                                                      | 0         |          |\n| labelLetterSpacing       | Edge label letter spacing                                                                                       | number \\| string                                                            | -         |          |\n| labelLineHeight          | Edge label line height                                                                                          | number \\| string                                                            | -         |          |\n| labelMaxLines            | Edge label maximum lines                                                                                        | number                                                                      | 1         |          |\n| labelMaxWidth            | Edge label maximum width, [options](#labelmaxwidth)                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Edge label offset in x direction                                                                                | number                                                                      | 0         |          |\n| labelOffsetY             | Edge label offset in y direction                                                                                | number                                                                      | 0         |          |\n| labelPadding             | Edge label padding                                                                                              | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Edge label position relative to edge, [options](#labelplacement)                                                | string \\| number                                                            | `center`  |          |\n| labelText                | Edge label text content                                                                                         | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Edge label text horizontal alignment                                                                            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Edge label text baseline                                                                                        | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Edge label text decoration line color                                                                           | string                                                                      | -         |          |\n| labelTextDecorationLine  | Edge label text decoration line                                                                                 | string                                                                      | -         |          |\n| labelTextDecorationStyle | Edge label text decoration line style                                                                           | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Edge label text overflow handling                                                                               | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Edge label text path                                                                                            | Path                                                                        | -         |          |\n| labelWordWrap            | Whether to enable automatic line wrapping for edge labels. When enabled, text exceeding labelMaxWidth will wrap | boolean                                                                     | false     |          |\n| labelZIndex              | Edge label rendering layer                                                                                      | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nEdge label position relative to the edge, can be set to:\n\n- `start`: Label positioned at the starting point of the edge\n- `center`: Label positioned at the center of the edge (default)\n- `end`: Label positioned at the ending point of the edge\n- `number`: Value range 0-1, representing the specific position ratio of the label on the edge, 0 for start position, 1 for end position\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text exceeding this width will wrap:\n\n- string: Represents the maximum width defined as a percentage relative to the edge length. For example, `50%` means the label width does not exceed half the edge length\n- number: Represents the maximum width defined in pixels. For example, 100 means the label's maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Styles\n\nLabel background is used to display the background of edge labels:\n\n| Property                      | Description                                                                                                                                                       | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to show edge label background                                                                                                                             | boolean                                  | false     |\n| labelBackgroundCursor         | Edge label background mouse cursor style, [options](#cursor)                                                                                                      | string                                   | `default` |\n| labelBackgroundFill           | Edge label background fill color                                                                                                                                  | string                                   | -         |\n| labelBackgroundFillOpacity    | Edge label background opacity                                                                                                                                     | number                                   | 1         |\n| labelBackgroundHeight         | Edge label background height                                                                                                                                      | string \\| number                         | -         |\n| labelBackgroundLineDash       | Edge label background dash line configuration                                                                                                                     | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Edge label background dash line offset                                                                                                                            | number                                   | -         |\n| labelBackgroundLineWidth      | Edge label background stroke line width                                                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | Edge label background border radius <br> - number: Uniform radius for all corners <br> - number[]: Individual radius for each corner, auto-filled if insufficient | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Edge label background shadow blur                                                                                                                                 | number                                   | -         |\n| labelBackgroundShadowColor    | Edge label background shadow color                                                                                                                                | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Edge label background shadow X offset                                                                                                                             | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Edge label background shadow Y offset                                                                                                                             | number                                   | -         |\n| labelBackgroundStroke         | Edge label background stroke color                                                                                                                                | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Edge label background stroke opacity                                                                                                                              | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Edge label background visibility                                                                                                                                  | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Edge label background rendering layer                                                                                                                             | number                                   | 1         |\n\n### Halo Styles\n\nHalo is an effect displayed around the edge main graphic, usually used for highlighting or indicating special states of the edge.\n\n#### Basic Halo Effect\n\nAdd basic halo effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete halo style configuration:\n\n| Property          | Description                                                                          | Type                   | Default                                   | Required |\n| ----------------- | ------------------------------------------------------------------------------------ | ---------------------- | ----------------------------------------- | -------- |\n| halo              | Whether to show edge halo                                                            | boolean                | false                                     |          |\n| haloCursor        | Edge halo mouse cursor style, [options](#cursor)                                     | string                 | `default`                                 |          |\n| haloDraggable     | Whether edge halo allows dragging                                                    | boolean                | true                                      |          |\n| haloDroppable     | Whether edge halo allows receiving dragged elements                                  | boolean                | true                                      |          |\n| haloFillRule      | Edge halo fill rule                                                                  | `nonzero` \\| `evenodd` | -                                         |          |\n| haloFilter        | Edge halo filter                                                                     | string                 | -                                         |          |\n| haloLineWidth     | Edge halo stroke width                                                               | number                 | 3                                         |          |\n| haloPointerEvents | Whether edge halo responds to pointer events, [options](#pointerevents)              | string                 | `none`                                    |          |\n| haloStroke        | Edge halo stroke color, **this property sets the color of the halo around the edge** | string                 | Consistent with main graphic stroke color |          |\n| haloStrokeOpacity | Edge halo stroke opacity                                                             | number                 | 0.25                                      |          |\n| haloVisibility    | Edge halo visibility                                                                 | `visible` \\| `hidden`  | `visible`                                 |          |\n| haloZIndex        | Edge halo rendering layer                                                            | number                 | -1                                        |          |\n\n### Arrow Styles\n\nEdges support adding arrows at the start and end points to indicate the directionality of the edge.\n\n#### Basic Arrow\n\nAdd basic arrow to the end of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // End arrow\n      endArrowType: 'vee', // Arrow type\n      endArrowSize: 10, // Arrow size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Bidirectional Arrows\n\nAdd arrows to both ends of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // Start arrow\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // End arrow\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Arrow Style\n\nCustomize arrow color and type:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // Diamond arrow\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // Red arrow fill\n      endArrowStroke: '#722ED1', // Arrow stroke color\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Start Arrow Style Configuration\n\n| Property                | Description                                             | Type                                                                                 | Default                            | Required |\n| ----------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| startArrow              | Whether to show edge start arrow                        | boolean                                                                              | false                              |          |\n| startArrowCursor        | Edge start arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| startArrowFill          | Edge start arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| startArrowFillOpacity   | Edge start arrow fill opacity                           | number                                                                               | 1                                  |          |\n| startArrowOffset        | Edge start arrow offset                                 | number                                                                               | 0                                  |          |\n| startArrowSize          | Edge start arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| startArrowStroke        | Edge start arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| startArrowStrokeOpacity | Edge start arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| startArrowType          | Edge start arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n#### End Arrow Style Configuration\n\n| Property              | Description                                           | Type                                                                                 | Default                            | Required |\n| --------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| endArrow              | Whether to show edge end arrow                        | boolean                                                                              | false                              |          |\n| endArrowCursor        | Edge end arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| endArrowFill          | Edge end arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| endArrowFillOpacity   | Edge end arrow fill opacity                           | number                                                                               | 1                                  |          |\n| endArrowOffset        | Edge end arrow offset                                 | number                                                                               | 0                                  |          |\n| endArrowSize          | Edge end arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| endArrowStroke        | Edge end arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| endArrowStrokeOpacity | Edge end arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| endArrowType          | Edge end arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n### Loop Edge Styles\n\nLoop edges are special edges where the start and end nodes are the same node.\n\n#### Basic Loop Edge\n\nCreate a basic loop edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // Loop position\n      loopDist: 30, // Loop size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Loop Edges\n\nCreate multiple loop edges at different positions for the same node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete loop edge style configuration:\n\n| Property      | Description                                                         | Type                                                                                                                                                                   | Default                  | Required |\n| ------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- |\n| loop          | Whether to enable loop edges                                        | boolean                                                                                                                                                                | true                     |          |\n| loopClockwise | Whether to draw the loop clockwise                                  | boolean                                                                                                                                                                | true                     |          |\n| loopDist      | Distance from node edge to loop top, used to specify loop curvature | number                                                                                                                                                                 | Default to max node size |          |\n| loopPlacement | Loop edge position                                                  | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                    |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select an edge or hovering to activate an edge, it's simply marking certain states on that element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of that graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. Additionally, it supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\nFor example, when an edge is in the `focus` state, you can add a halo with a width of 6 and orange color.\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefine edge animation effects. Supports the following two configuration methods:\n\n1. Disable all edge animations\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to the animation effects when edges enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when edge enters the canvas\n- `update`: Animation when edge updates\n- `exit`: Animation when edge leaves the canvas\n- `show`: Animation when edge shows from hidden state\n- `hide`: Animation when edge hides\n- `collapse`: Animation when edge collapses\n- `expand`: Animation when edge expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#动画范式) to use animation syntax to configure edges, such as:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // Only animate stroke property during update\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"path-in\", // Use path animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable specific stage animations:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // Disable edge entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefine the edge palette, which is a predefined edge color pool that is allocated according to rules and maps colors to the `stroke` property.\n\n> For palette definitions, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to using id as grouping field                  | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                     | `group` \\| `value`            | `group` |\n\nFor example, to assign edge colors to a group of data by the `direction` field, making edges of the same category have the same color:\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau is the palette name, colors assigned by ID by default\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Edge Common Configuration","order":"1"},"isInternal":false,"tokens":12716,"sizeBytes":50881},{"name":"BaseEdge.zh.md","path":"packages/site/docs/manual/element/edge/BaseEdge.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/BaseEdge.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 边通用配置项\norder: 1\n---\n\n本文介绍内置边通用属性配置。\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // 边类型\n    style: {}, // 边样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                   | 类型                    | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](#type)           | `line` |      |\n| style     | 边样式配置，包括颜色、粗细等           | [Style](#style)         | -      |      |\n| state     | 不同状态下的样式配置                   | [State](#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](#animation) | -      |      |\n\n## Type\n\n指定边类型，内置边类型名称或自定义边的名称。默认为 `line`（直线边）。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据边数据动态选择边类型：\n\n```js\nconst graph = new Graph({\n  edge: {\n    // 静态配置\n    type: 'line',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `line`：[直线边](/manual/element/edge/line)\n- `polyline`：[折线边](/manual/element/edge/polyline)\n- `cubic`：[三次贝塞尔曲线边](/manual/element/edge/cubic)\n- `cubic-horizontal`：[水平三次贝塞尔曲线边](/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`：[垂直三次贝塞尔曲线边](/manual/element/edge/cubic-vertical)\n- `quadratic`：[二次贝塞尔曲线边](/manual/element/edge/quadratic)\n\n## Style\n\n定义边的样式，包括颜色、粗细等。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据边数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // 静态配置\n      stroke: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineDash: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `边: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\n其中 `datum` 参数为边数据对象 (`EdgeData`)，包含边的所有数据信息。\n\n一个完整的边由以下几部分构成：\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要路径，例如直线、曲线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `badge` ：边上的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `startArrow` ：边起始端的箭头；\n- `endArrow` ：边结束端的箭头。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是边的核心部分，定义了边的基本路径和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置边的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // 蓝色边\n      lineWidth: 2, // 边宽度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线样式\n\n创建带虚线样式的边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // 虚线样式\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 阴影效果\n\n为边添加阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                  | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | --------------------- | --------- | ---- |\n| cursor                          | 边鼠标移入样式，[配置项](#cursor)                                                         | string                | `default` |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                | 0         |      |\n| lineDash                        | 边虚线样式                                                                                | number[]              | -         |      |\n| lineDashOffset                  | 边虚线偏移量                                                                              | number                | 0         |      |\n| lineWidth                       | 边宽度                                                                                    | number                | 1         |      |\n| opacity                         | 边透明度                                                                                  | number \\| string      | 1         |      |\n| pointerEvents                   | 边如何响应指针事件，[配置项](#pointerevents)                                              | string                | `auto`    |      |\n| shadowBlur                      | 边阴影模糊度                                                                              | number                | -         |      |\n| shadowColor                     | 边阴影颜色                                                                                | string                | -         |      |\n| shadowOffsetX                   | 边阴影在 x 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowOffsetY                   | 边阴影在 y 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowType                      | 边阴影类型                                                                                | `inner` \\| `outer`    | `outer`   |      |\n| sourcePort                      | 边起始连接的连接桩                                                                        | string                | -         |      |\n| stroke                          | 边颜色                                                                                    | string                | `#000`    |      |\n| strokeOpacity                   | 边颜色透明度                                                                              | number \\| string      | 1         |      |\n| targetPort                      | 边终点连接的连接桩                                                                        | string                | -         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定边                                          | string                | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                | -         |      |\n| visibility                      | 边是否可见                                                                                | `visible` \\| `hidden` | `visible` |      |\n| zIndex                          | 边渲染层级                                                                                | number                | 1         |      |\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的描边区域就会响应事件，不会受 `stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // 边不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示边的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '边标签',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '这是一个很长的边标签需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '重要连接',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自动旋转标签\n\n标签可以自动旋转以保持与边方向一致：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '自动旋转',\n      labelAutoRotate: true, // 自动旋转\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                             | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 边标签是否显示                                                                   | boolean                                                                     | true      |      |\n| labelAutoRotate          | 边标签是否自动旋转，保持与边的方向一致                                           | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入边标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 边标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 边标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 边标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 边标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 边标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 边标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                           | number                                                                      | 0         |      |\n| labelLetterSpacing       | 边标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 边标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 边标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 边标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 边标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 边标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 边标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 边标签相对于边的位置，[配置项](#labelplacement)                                  | string \\| number                                                            | `center`  |      |\n| labelText                | 边标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 边标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 边标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 边标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 边标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 边标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 边标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 边标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 边标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 边标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n边标签相对于边的位置，可以设置为：\n\n- `start`：标签位于边的起始位置\n- `center`：标签位于边的中心位置（默认）\n- `end`：标签位于边的结束位置\n- `number`：取值范围为 0-1，表示标签在边上的具体位置比例，0 为起始位置，1 为结束位置\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于边长度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过边长度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示边标签的背景：\n\n| 属性                          | 描述                                                                                                         | 类型                                     | 默认值    |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | --------- |\n| labelBackground               | 边标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 边标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 边标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 边标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 边标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 边标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 边标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 边标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 边标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 边标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 边标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 边标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 边标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 边标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 边标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 边标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 边标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕边主图形显示的效果，通常用于高亮显示或表示边的特殊状态。\n\n#### 基础光晕效果\n\n为边添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                 | 类型                   | 默认值                         | 必选 |\n| ----------------- | ---------------------------------------------------- | ---------------------- | ------------------------------ | ---- |\n| halo              | 边光晕是否显示                                       | boolean                | false                          |      |\n| haloCursor        | 边光晕鼠标移入样式，[配置项](#cursor)                | string                 | `default`                      |      |\n| haloDraggable     | 边光晕是否允许拖拽                                   | boolean                | true                           |      |\n| haloDroppable     | 边光晕是否允许接收被拖拽的元素                       | boolean                | true                           |      |\n| haloFillRule      | 边光晕填充规则                                       | `nonzero` \\| `evenodd` | -                              |      |\n| haloFilter        | 边光晕滤镜                                           | string                 | -                              |      |\n| haloLineWidth     | 边光晕描边宽度                                       | number                 | 3                              |      |\n| haloPointerEvents | 边光晕效果是否响应指针事件，[配置项](#pointerevents) | string                 | `none`                         |      |\n| haloStroke        | 边光晕描边色，**此属性用于设置边周围光晕的颜色**     | string                 | 与主图形的描边色 `stroke` 一致 |      |\n| haloStrokeOpacity | 边光晕描边色透明度                                   | number                 | 0.25                           |      |\n| haloVisibility    | 边光晕可见性                                         | `visible` \\| `hidden`  | `visible`                      |      |\n| haloZIndex        | 边光晕渲染层级                                       | number                 | -1                             |      |\n\n### 箭头样式\n\n边支持在起始端和结束端添加箭头，用于表示边的方向性。\n\n#### 基础箭头\n\n为边的结束端添加基本箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'vee', // 箭头类型\n      endArrowSize: 10, // 箭头大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 双向箭头\n\n为边的两端都添加箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // 起始端箭头\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义箭头样式\n\n自定义箭头的颜色和类型：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // 菱形箭头\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // 红色箭头填充\n      endArrowStroke: '#722ED1', // 箭头描边颜色\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 起始箭头样式配置\n\n| 属性                    | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| ----------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| startArrow              | 边起始箭头是否显示                        | boolean                                                                              | false              |      |\n| startArrowCursor        | 边起始箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| startArrowFill          | 边起始箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowFillOpacity   | 边起始箭头填充透明度                      | number                                                                               | 1                  |      |\n| startArrowOffset        | 边起始箭头的偏移量                        | number                                                                               | 0                  |      |\n| startArrowSize          | 边起始箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| startArrowStroke        | 边起始箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowStrokeOpacity | 边起始箭头描边透明度                      | number                                                                               | 1                  |      |\n| startArrowType          | 边起始箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n#### 结束箭头样式配置\n\n| 属性                  | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| --------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| endArrow              | 边结束箭头是否显示                        | boolean                                                                              | false              |      |\n| endArrowCursor        | 边结束箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| endArrowFill          | 边结束箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowFillOpacity   | 边结束箭头填充透明度                      | number                                                                               | 1                  |      |\n| endArrowOffset        | 边结束箭头的偏移量                        | number                                                                               | 0                  |      |\n| endArrowSize          | 边结束箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| endArrowStroke        | 边结束箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowStrokeOpacity | 边结束箭头描边透明度                      | number                                                                               | 1                  |      |\n| endArrowType          | 边结束箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n### 自环边样式\n\n自环边是指起始节点和结束节点为同一个节点的特殊边。\n\n#### 基础自环边\n\n创建基本的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // 自环位置\n      loopDist: 30, // 自环大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个自环边\n\n为同一节点创建多个不同位置的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的自环边样式配置：\n\n| 属性          | 描述                                           | 类型                                                                                                                                                                   | 默认值                 | 必选 |\n| ------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| loop          | 是否启用自环边                                 | boolean                                                                                                                                                                | true                   |      |\n| loopClockwise | 指定是否顺时针绘制环                           | boolean                                                                                                                                                                | true                   |      |\n| loopDist      | 从节点边缘到自环顶部的距离，用于指定自环的曲率 | number                                                                                                                                                                 | 默认为节点尺寸的最大值 |      |\n| loopPlacement | 自环边的位置                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                  |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个边或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\n例如，当边处于 `focus` 状态时，可以为其添加一个宽度为 6 且颜色为橙色的光晕。\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义边的动画效果，支持下列两种配置方式：\n\n1. 关闭边全部动画\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指边在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 边进入画布时的动画\n- `update`: 边更新时的动画\n- `exit`: 边离开画布时的动画\n- `show`: 边从隐藏状态显示时的动画\n- `hide`: 边隐藏时的动画\n- `collapse`: 边收起时的动画\n- `expand`: 边展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置边，如：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // 更新时只对 stroke 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ]\n    }\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"path-in\", // 使用路径动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // 关闭边入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义边的色板，即预定义边颜色池，并根据规则进行分配，将颜色映射到 `stroke` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `direction` 字段分配边颜色，使得同类别的边颜色相同：\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"边通用配置项","order":"1"},"isInternal":false,"tokens":9599,"sizeBytes":45325},{"name":"Cubic.en.md","path":"packages/site/docs/manual/element/edge/Cubic.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Cubic.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Cubic Bezier Curve Edge\norder: 2\n---\n\n## Overview\n\nA cubic Bezier curve is a versatile smooth curve with control points that can be freely distributed, suitable for connecting nodes in any direction.\n\nUse cases:\n\n- Suitable for graphs with any layout, such as network graphs and relationship graphs.\n\n- Use when smooth node connections are needed without specific directional requirements.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type                               | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [[Point](#point), [Point](#point)] | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number &#124; number[]             | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number &#124; number[]             | 20      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Cubic Bezier Curve Edge","order":"2"},"isInternal":false,"tokens":858,"sizeBytes":3429},{"name":"Cubic.zh.md","path":"packages/site/docs/manual/element/edge/Cubic.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Cubic.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 三次贝塞尔曲线边 Cubic\norder: 2\n---\n\n## 概述\n\n三次贝塞尔曲线是一种通用的平滑曲线，其控制点可以自由分布，适合连接任意方向的节点。\n\n使用场景：\n\n- 适用于任意布局的图，如网络图、关系图。\n\n- 当需要平滑连接节点且无特定方向要求时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型                               | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [[Point](#point), [Point](#point)] | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number &#124; number[]             | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number &#124; number[]             | 20     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"三次贝塞尔曲线边 Cubic","order":"2"},"isInternal":false,"tokens":661,"sizeBytes":3124},{"name":"CubicHorizontal.en.md","path":"packages/site/docs/manual/element/edge/CubicHorizontal.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/CubicHorizontal.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CubicHorizontal Bezier Curve Edge\norder: 3\n---\n\n## Overview\n\nThe horizontal cubic Bezier curve is a smooth curve with control points primarily distributed along the horizontal direction, suitable for connecting nodes horizontally.\n\nUse cases:\n\n- Suitable for horizontally laid-out graphs, such as flowcharts and hierarchical diagrams.\n\n- Use when emphasizing horizontal connections is needed.\n\n> Note: When calculating control points, the distance on the x-axis is primarily considered, ignoring changes on the y-axis.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Horizontal Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"CubicHorizontal Bezier Curve Edge","order":"3"},"isInternal":false,"tokens":724,"sizeBytes":2895},{"name":"CubicHorizontal.zh.md","path":"packages/site/docs/manual/element/edge/CubicHorizontal.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/CubicHorizontal.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 水平三次贝塞尔曲线边 CubicHorizontal\norder: 3\n---\n\n## 概述\n\n水平三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿水平方向分布，适合在水平方向上连接节点。\n\n使用场景：\n\n- 适用于水平布局的图，如流程图、层次结构图。\n\n- 当需要强调水平方向的连接关系时使用。\n\n> 特别注意，计算控制点时主要考虑 x 轴上的距离，忽略 y 轴的变化\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置水平三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"水平三次贝塞尔曲线边 CubicHorizontal","order":"3"},"isInternal":false,"tokens":524,"sizeBytes":2577},{"name":"CubicVertical.en.md","path":"packages/site/docs/manual/element/edge/CubicVertical.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/CubicVertical.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CubicVertical Bezier Curve Edge\norder: 4\n---\n\n## Overview\n\nThe vertical cubic Bezier curve is a smooth curve with control points primarily distributed along the vertical direction, suitable for connecting nodes vertically.\n\nUse cases:\n\n- Suitable for vertically laid-out graphs, such as organizational charts and tree diagrams.\n\n- Use when emphasizing vertical connections is needed.\n\n**Note: When calculating control points, the distance on the y-axis is primarily considered, ignoring changes on the x-axis.**\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Vertical Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"CubicVertical Bezier Curve Edge","order":"4"},"isInternal":false,"tokens":726,"sizeBytes":2903},{"name":"CubicVertical.zh.md","path":"packages/site/docs/manual/element/edge/CubicVertical.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/CubicVertical.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 垂直三次贝塞尔曲线边 CubicVertical\norder: 4\n---\n\n## 概述\n\n垂直三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿垂直方向分布，适合在垂直方向上连接节点。\n\n使用场景：\n\n- 适用于垂直布局的图，如组织结构图、树状图。\n\n- 当需要强调垂直方向的连接关系时使用。\n\n**特别注意，计算控制点时主要考虑 y 轴上的距离，忽略 x 轴的变化**\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置垂直三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"垂直三次贝塞尔曲线边 CubicVertical","order":"4"},"isInternal":false,"tokens":528,"sizeBytes":2594},{"name":"custom-edge.en.md","path":"packages/site/docs/manual/element/edge/custom-edge.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/custom-edge.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Edge\norder: 7\n---\n\nG6 provides multiple [built-in edge](/en/manual/element/edge/base-edge) types, including [line](/en/manual/element/edge/line), [polyline](/en/manual/element/edge/polyline), [quadratic (quadratic Bézier curve edge)](/en/manual/element/edge/quadratic), [cubic (cubic Bézier curve edge)](/en/manual/element/edge/cubic), [cubic-horizontal](/en/manual/element/edge/cubic-horizontal), [cubic-vertical](/en/manual/element/edge/cubic-vertical), and more. These built-in edges can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter requirements that these basic edges cannot satisfy. In such cases, you need to create custom edges. Don't worry, it's simpler than you think!\n\n## Before Starting: Understanding the Basic Components of an Edge\n\nIn G6, a complete edge typically consists of the following parts:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the primary shape of the edge, such as straight lines, polylines, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `arrow`: Arrow, used to indicate the direction of the edge\n- `halo`: Graphic displaying halo effects around the main graphic\n\n## Ways to Create Custom Edges <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are two main ways to create custom edges:\n\n### 1. Inherit from Existing Edge Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach. You can choose to inherit from one of the following types:\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - The most basic edge class, providing core edge functionality\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - Straight line edge\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - Polyline edge\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - Quadratic Bézier curve edge\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - Cubic Bézier curve edge\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - Vertical cubic Bézier curve edge\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - Horizontal cubic Bézier curve edge\n\n**Why choose this approach?**\n\n- 📌 **Less code**: Reuse existing edge properties and methods, only focus on new functionality\n- 📌 **Fast development**: Suitable for most project requirements, quickly achieve business goals\n- 📌 **Easy maintenance**: Clear code structure, clear inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing edge types (recommended), you can jump directly to [Create Your First Custom Edge in Three Steps](#create-your-first-custom-edge-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing edge types don't meet your requirements, you can create edges from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum freedom**: Complete control over every detail of the edge, achieving any complex effects\n- 📌 **Special requirements**: Highly customized scenarios that existing edge types cannot satisfy\n- 📌 **Performance optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom edges built from scratch need to handle all details by themselves, including graphic rendering, event response, state changes, etc., which is more challenging to develop. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) for implementation.\n:::\n\n## Create Your First Custom Edge in Three Steps\n\nLet's start with the most basic `BaseEdge` to implement a custom straight line edge:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Edge Class\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // Define edge style, can add or override default styles\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // Call parent class method to get basic style, then add custom styles\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // Implement abstract method: define edge path\n  // This is an abstract method of BaseEdge, all subclasses must implement it\n  protected getKeyPath(attributes) {\n    // Get source node and target node\n    const { sourceNode, targetNode } = this;\n\n    // Get node position coordinates\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // Return SVG path array, defining a straight line from start to end\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=Key Method Analysis}\n\n- `getKeyStyle`: Defines the basic style of the edge, such as line width, color, etc.\n- `getKeyPath`: An abstract method in `BaseEdge` that **must be implemented**, it defines the path shape of the edge\n  :::\n\n### Step 2: Register Custom Edge\n\nUse the `register` method to register the edge type so that G6 can recognize your custom edge:\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.EDGE` indicates this is an edge type\n- Type name: `my-line-edge` is the name we give to this custom edge, which will be used in configuration later\n- Class definition: `MyLineEdge` is the edge class we just created\n\n### Step 3: Apply Custom Edge\n\nIn the graph configuration, use our custom edge by setting `edge.type`:\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom edge.\n\n## Going Further: Understanding the Principles of Edge Rendering\n\n### Atomic Graphics\n\nG6 nodes are drawn using atomic graphic units provided by the [G graphics system](https://g.antv.antgroup.com/). Here are common graphic elements and their uses:\n\n| Graphic Element | Type       | Description                                                                                                                                                                                                                                                                 |\n| --------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Circle          | `circle`   | Suitable for representing states, avatars, circular buttons, etc. Refer to SVG's [\\<circle\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/circle) element                                                                                            |\n| Ellipse         | `ellipse`  | Similar to circle, but supports scenarios with different horizontal and vertical axes. Refer to SVG's [\\<ellipse\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/ellipse) element                                                                     |\n| Image           | `image`    | Used to display icons, user avatars, LOGOs, etc. Refer to SVG's [\\<image\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image) element                                                                                                                         |\n| Line            | `line`     | Used for decoration, auxiliary connections, etc. Refer to SVG's [\\<line\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) element                                                                                                                           |\n| Path            | `path`     | Supports complex graphics such as arrows, arcs, curves, Bézier paths, etc. The path contains a set of commands and parameters with different semantics, [specific usage](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths)                                   |\n| Polygon         | `polygon`  | Supports custom graphics such as pentagrams, arrows. Refer to SVG's [\\<polygon\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon) element                                                                                                                 |\n| Polyline        | `polyline` | Multi-point polyline, suitable for complex connection structures. Refer to SVG's [\\<polyline\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline) element                                                                                                  |\n| Rectangle       | `rect`     | Most commonly used graphic, suitable as containers, cards, buttons, and other basic structures. Refer to SVG's [\\<rect\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect) element                                                                            |\n| Text            | `text`     | Displays names, descriptions, labels, and other content. Provides simple single-line/multi-line text layout capabilities, single-line supports horizontal alignment, character spacing; multi-line supports explicit line breaks and automatic wrapping, vertical alignment |\n\n> For more atomic graphics and detailed properties, please refer to [Element - Shape (Optional)](/en/manual/element/shape/overview)\n\nAll these graphics can be dynamically created or updated through `upsert()`, automatically managing graphic state and lifecycle.\n\n### Element Base Class\n\nBefore starting to customize elements, you need to understand some important properties and methods in G6 element base classes:\n\n#### Properties\n\n| Property   | Type                          | Description                                           |\n| ---------- | ----------------------------- | ----------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom elements, you will frequently use the `upsert` method. It's short for \"update or insert\", responsible for adding or updating graphics in elements:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                       |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | The key of the graphic, i.e., the corresponding key in `shapeMap`. Built-in keys include `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> The key should not use special symbols, it will be converted to camelCase to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                     |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                     |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                    |\n\nFor example, inserting a purple circle at a fixed position:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics through `container.appendChild()`? Because:\n\n1. **Better performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and rebuilding, greatly improving rendering performance\n2. **Simpler code**: No need to manually check if elements exist\n3. **Easy management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, you can easily get them through `this.getShape(key)`\n\n#### `render(attributes, container)`: Main Entry Point for Rendering Edges\n\nEvery custom edge class must implement the `render(attributes, container)` method, which defines how the edge is \"drawn\". You can use various atomic graphics here to compose the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation, or make sub-graphics interact with each other. In this case, the `getShape` method can help you get any graphic previously created through `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, you must ensure A is created first\n\n### Element Conventions\n\n- **Use Conventional Properties**\n\nCurrently conventional element properties include:\n\n- Get element size through `this.getSize()`\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` (simple mode - doesn't consider node shape, directly returns node center or nearest port center position)\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` (optimized mode - default is true, considers node shape, returns connection points on node boundary)\n\n- **Use Paired `getXxxStyle` and `drawXxxShape` Methods for Graphic Drawing**\n\n`getXxxStyle` is used to get graphic styles, `drawXxxShape` is used to draw graphics. Graphics created this way support automatic animation execution.\n\n> Where `Xxx` is the camelCase form of the key passed when calling the [upsert](#methods) method.\n\n- **Access Graph Context through `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, which you can override in custom edges to execute specific logic at key moments:\n\n| Hook Function | Trigger Time                                            | Typical Usage                                                                    |\n| ------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------- |\n| `onCreate`    | When edge creation is completed with entrance animation | Bind interaction events, initialize edge state, add external listeners           |\n| `onUpdate`    | When edge update is completed with update animation     | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | When edge completes exit animation and is destroyed     | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"rendering logic\"**.\n\nYou can define styles for each state in edge configuration:\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\nThis state will be passed to the `render()` method's `attributes`, and the merged result by the internal system will be automatically applied to the graphics.\n\nYou can also customize rendering logic based on state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## From Simple to Complex\n\n### Custom Path Polyline Edge\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Additional Labels\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Custom Edge","order":"7"},"isInternal":false,"tokens":5544,"sizeBytes":22201},{"name":"custom-edge.zh.md","path":"packages/site/docs/manual/element/edge/custom-edge.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/custom-edge.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义边\norder: 7\n---\n\nG6 提供了多种[内置边](/manual/element/edge/base-edge)类型，包含 [line（直线边）](/manual/element/edge/line)、[polyline（折线边）](/manual/element/edge/polyline)、[quadratic（二次贝塞尔曲线边）](/manual/element/edge/quadratic)、[cubic（三次贝塞尔曲线边）](/manual/element/edge/cubic)、[cubic-horizontal（水平三次贝塞尔曲线边）](/manual/element/edge/cubic-horizontal)、[cubic-vertical（垂直三次贝塞尔曲线边）](/manual/element/edge/cubic-vertical) 等。这些内置边能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础边无法满足的需求。这时，你需要创建自定义边。别担心，这比你想象的要简单！\n\n## 开始之前：了解边的基本构成\n\n在 G6 中，一条完整的边通常由以下几个部分组成：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要形状，例如直线、折线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `arrow` ：箭头，用于表示边的方向；\n- `halo` ：主图形周围展示的光晕效果的图形。\n\n## 自定义边的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义边的方式主要有两种途径：\n\n### 1. 继承现有边类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - 最基础的边类，提供边的核心功能\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - 直线边\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - 折线边\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - 二次贝塞尔曲线边\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - 三次贝塞尔曲线边\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - 垂直三次贝塞尔曲线边\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - 水平三次贝塞尔曲线边\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有边的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有边类型（推荐），可以直接跳到 [三步创建你的第一个自定义边](#三步创建你的第一个自定义边) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有边类型都不满足需求，你可以基于 G 的底层图形系统从零创建边。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制边的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有边类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义边需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义边\n\n让我们从最基础的 `BaseEdge` 开始，实现一个自定义直线边：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义边类\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // 定义边的样式，可以添加或覆盖默认样式\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // 调用父类方法获取基础样式，然后添加自定义样式\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // 实现抽象方法：定义边的路径\n  // 这是 BaseEdge 的抽象方法，所有子类必须实现\n  protected getKeyPath(attributes) {\n    // 获取源节点和目标节点\n    const { sourceNode, targetNode } = this;\n\n    // 获取节点的位置坐标\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // 返回SVG路径数组，定义从起点到终点的直线\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=关键方法解析}\n\n- `getKeyStyle`: 定义边的基本样式，如线宽、颜色等\n- `getKeyPath`: 是 `BaseEdge` 中的抽象方法，**必须实现**，它定义了边的路径形状\n  :::\n\n### 第二步：注册自定义边\n\n使用 `register` 方法注册边类型，这样 G6 才能识别你的自定义边：\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.EDGE` 表示这是一个边类型\n- 类型名称：`my-line-edge` 是我们给这个自定义边起的名字，后续会在配置中使用\n- 类定义：`MyLineEdge` 是我们刚刚创建的边类\n\n### 第三步：应用自定义边\n\n在图的配置中，通过设置 `edge.type` 来使用我们的自定义边：\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义边。\n\n## 更进一步：理解边绘制的原理\n\n### 原子图形\n\nG6 的节点是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。以下是常见图形元素及其用途：\n\n| 图形元素 | 类型       | 描述                                                                                                                                                                        |\n| -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 圆形     | `circle`   | 适合表示状态、头像、圆形按钮等。可以参考 SVG 的 [\\<circle\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/circle) 元素                                |\n| 椭圆     | `ellipse`  | 与 circle 类似，但支持横纵轴不同的场景。可以参考 SVG 的 [\\<ellipse\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/ellipse) 元素                      |\n| 图片     | `image`    | 用于展示图标、用户头像、LOGO 等。可以参考 SVG 的 [\\<image\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/image) 元素                                           |\n| 直线     | `line`     | 用于装饰、辅助连接等。可以参考 SVG 的 [\\<line\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/line) 元素                                                        |\n| 路径     | `path`     | 支持复杂图形，如箭头、圆弧、曲线、贝塞尔路径等。路径中包含一组命令与参数，这些命令有不同的语义，[具体用法](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths) |\n| 多边形   | `polygon`  | 支持自定义图形，如五角星、箭头。可以参考 SVG 的 [\\<polygon\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polygon) 元素                                        |\n| 折线     | `polyline` | 多点折线，适合复杂的连线结构。可以参考 SVG 的 [\\<polyline\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polyline) 元素                                        |\n| 矩形     | `rect`     | 最常用图形，适合作为容器、卡片、按钮等基础结构。可以参考 SVG 的 [\\<rect\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/rect) 元素                              |\n| 文本     | `text`     | 显示名称、描述、标签等内容。提供简单的单行/多行文本排版能力，单行支持水平对齐、字符间距；多行支持显式换行符以及自动换行，垂直对齐                                           |\n\n> 更多原子图形和详细的属性请参考 [元素 - 图形（可选）](/manual/element/shape/overview)\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义元素之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义元素时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                   |\n| --------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见[元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                 |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                               |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                         |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染边的主入口\n\n每个自定义边类都必须实现 `render(attributes, container)` 方法，它定义了该边如何被“绘制”出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n目前约定的元素属性包括：\n\n- 通过 `this.getSize()` 获取元素的尺寸\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` 获取边的起点和终点（简单模式 - 不考虑节点形状，直接返回节点中心点或最近连接桩中心˝位置）\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` 获取边的起点和终点（优化模式 - 默认为 true，考虑节点形状，返回节点边界上的连接点）\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义边中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                 | 典型用途                                   |\n| ----------- | ------------------------ | ------------------------------------------ |\n| `onCreate`  | 当边创建后完成入场动画时 | 绑定交互事件、初始化边状态、添加外部监听器 |\n| `onUpdate`  | 当边更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果   |\n| `onDestroy` | 当边完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知     |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **“状态响应”** 与 **“绘制逻辑”** 分离。\n\n你可以在边配置中定义每种状态下的样式：\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## 从简单到复杂\n\n### 自定义路径的折线边\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 额外标签\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"自定义边","order":"7"},"isInternal":false,"tokens":3674,"sizeBytes":19658},{"name":"Line.en.md","path":"packages/site/docs/manual/element/edge/Line.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Line.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Line Edge\norder: 5\n---\n\n## Overview\n\nA line is the simplest type of edge, directly connecting two nodes without any curvature.\n\nUse cases:\n\n- Suitable for simple graphs, such as topology diagrams and flowcharts.\n\n- Use when quick drawing is needed without complex visual effects.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n## Example\n\n### Built-in Line Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Line Edge","order":"5"},"isInternal":false,"tokens":507,"sizeBytes":2028},{"name":"Line.zh.md","path":"packages/site/docs/manual/element/edge/Line.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Line.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 直线边 Line\norder: 5\n---\n\n## 概述\n\n直线是最简单的边类型，直接连接两个节点，没有任何弯曲。\n\n使用场景：\n\n- 适用于简单的图，如拓扑图、流程图。\n\n- 当需要快速绘制且无需复杂视觉效果时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n## 示例\n\n### 内置直线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"直线边 Line","order":"5"},"isInternal":false,"tokens":434,"sizeBytes":1986},{"name":"overview.en.md","path":"packages/site/docs/manual/element/edge/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/overview.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Edge Overview\norder: 0\n---\n\n## What is an Edge\n\nAn edge is one of the basic elements in a graph, used to connect two nodes or combos, representing the relationship between them. In G6, edges are directional, pointing from `source` to `target`, but you can configure them to hide the arrow to represent undirected connections.\n\nYou can create edges between any two nodes, combos, or between a node and a combo, and you can express different types of relationships by creating multiple edges.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 provides the following built-in edges:\n\n- `line` Straight line edge\n- `polyline` Polyline edge\n- `quadratic` Quadratic Bezier curve edge\n- `cubic` Cubic Bezier curve edge\n- `cubicVertical` Vertical cubic Bezier curve edge\n- `cubicHorizontal` Horizontal cubic Bezier curve edge\n\n### Data Structure\n\nWhen defining an edge, you need to add an `edges` field to the graph's data object. Each edge is an object with the following structure:\n\n| Attribute | Description                                                                                                   | Type     | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source    | ID of the starting node of the edge                                                                           | string   | -       | ✓        |\n| target    | ID of the target node of the edge                                                                             | string   | -       | ✓        |\n| id        | Unique identifier of the edge                                                                                 | string   | -       |          |\n| type      | Type of edge, name of built-in edge type or custom edge, such as `line` or `polyline`                         | string   | -       |          |\n| data      | Edge data, used to store custom data of the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style     | Edge style, including visual attributes like line color, width, arrow, etc.                                   | object   | -       |          |\n| states    | Initial states of the edge                                                                                    | string[] | -       |          |\n\nAn example of a data item in the `edges` array:\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Configuration Methods\n\nThere are three ways to configure edges, listed in order of priority from high to low:\n\n- Use `graph.setEdge()` for dynamic configuration\n- Global configuration when instantiating the graph\n- Dynamic attributes in data\n\nThese configuration methods can be used simultaneously. When there are the same configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setEdge()`\n\nYou can dynamically set the style mapping logic of edges using `graph.setEdge()` after the graph instance is created.\n\nThis method needs to be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration When Instantiating the Graph\n\nYou can configure edge style mapping globally when instantiating the graph, and this configuration will take effect on all edges.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different edges, you can write the configuration into the edge data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## Custom Edges\n\nWhen built-in edges cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend built-in edges\n- Create entirely new edge types\n\nUnlike combos, custom edges need to be registered before use. For detailed tutorials, please refer to the [Custom Edge](/manual/element/edge/custom-edge) documentation.\n","frontmatter":{"title":"Edge Overview","order":"0"},"isInternal":false,"tokens":1280,"sizeBytes":5124},{"name":"overview.zh.md","path":"packages/site/docs/manual/element/edge/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/overview.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 边总览\norder: 0\n---\n\n## 什么是边\n\n边（Edge）是图中的基本元素之一，用于连接两个节点或组合，表示它们之间的关系。在 G6 中，边具有方向性，从 `source` 指向 `target`，也可以通过配置隐藏箭头以表示无方向连接。\n\n你可以在任意两个节点、组合，或节点与组合之间创建边，还可以通过创建多条边来表达不同的关系类型。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 提供了以下内置边：\n\n- `line` 直线边\n- `polyline` 折线边\n- `quadratic` 二次贝塞尔曲线边\n- `cubic` 三次贝塞尔曲线边\n- `cubicVertical` 垂直三次贝塞尔曲线边\n- `cubicHorizontal` 水平三次贝塞尔曲线边\n\n### 数据结构\n\n定义边时，需要在图的数据对象中添加 `edges` 字段。每条边是一个对象，结构如下：\n\n| 属性   | 描述                                                                  | 类型     | 默认值 | 必选 |\n| ------ | --------------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                         | string   | -      | ✓    |\n| target | 边目标节点 ID                                                         | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                        | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称，比如 `line` 或者 `polyline` | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取      | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                            | object   | -      |      |\n| states | 边初始状态                                                            | string[] | -      |      |\n\n`edges` 数组中一个数据项的示例：\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 配置方法\n\n配置边的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setEdge()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setEdge()`\n\n可在图实例创建后，使用 `graph.setEdge()` 动态设置边的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `edge` 配置边样式映射，这里的配置是全局的配置，将会在所有边上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同边进行不同的配置，可以将配置写入到边数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## 自定义边\n\n当内置边无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置边进行扩展\n- 创建全新的边类型\n\n与组合不同，自定义边需要先注册后使用。详细教程请参考 [自定义边](/manual/element/edge/custom-edge) 文档。\n","frontmatter":{"title":"边总览","order":"0"},"isInternal":false,"tokens":736,"sizeBytes":4341},{"name":"Polyline.en.md","path":"packages/site/docs/manual/element/edge/Polyline.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Polyline.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Polyline Edge\norder: 6\n---\n\n## Overview\n\nA polyline is an edge composed of multiple straight line segments, suitable for connecting nodes by bypassing obstacles in complex layouts.\n\nUse cases:\n\n- Suitable for graphs with complex layouts, such as circuit diagrams and pipeline diagrams.\n\n- Use when you need to bypass other nodes or obstacles.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                | Type                                                                                    | Default | Required |\n| ------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the turning points of the polyline. | [Point](#point)[]                                                                       | []      |          |\n| radius        | Corner radius of the turning points.                                       | number                                                                                  | 0       |          |\n| router        | Whether to enable routing.                                                 | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false   |          |\n\n### OrthRouter\n\n| Attribute | Description                                                                                              | Type                | Default |\n| --------- | -------------------------------------------------------------------------------------------------------- | ------------------- | ------- |\n| type      | Orthogonal routing, adding extra control points on the path to keep each segment horizontal or vertical. | `'orth'`            | -       |\n| padding   | Minimum distance between the node connection point and the corner.                                       | [Padding](#padding) | `0`     |\n\n### ShortestPathRouter\n\n| Attribute                 | Description                                                                                                                                                                                                                                                                          | Type                                                                   | Default |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------- |\n| type                      | Shortest path routing, an intelligent version of orthogonal routing `'orth'`. This routing consists of horizontal or vertical orthogonal segments. It uses the A\\* algorithm to calculate the shortest path and supports automatic avoidance of other nodes (obstacles) on the path. | `'shortest-path'`                                                      | -       |\n| offset                    | Minimum distance between the node anchor point and the corner.                                                                                                                                                                                                                       | [Padding](#padding)                                                    | 0       |\n| gridSize                  | Grid cell size.                                                                                                                                                                                                                                                                      | number                                                                 | 0       |\n| maxAllowedDirectionChange | Maximum allowed rotation angle (radians).                                                                                                                                                                                                                                            | number                                                                 | 0       |\n| startDirections           | Possible starting directions of the node.                                                                                                                                                                                                                                            | [Direction](#direction)[]                                              | 0       |\n| endDirections             | Possible ending directions of the node.                                                                                                                                                                                                                                              | [Direction](#direction)[]                                              | 0       |\n| directionMap              | Specifies the movable directions.                                                                                                                                                                                                                                                    | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0       |\n| penalties                 | Represents additional costs for certain paths during path searching. The key is the radian value, and the value is the cost.                                                                                                                                                         | { [key: string]: number }                                              | 0       |\n| distFunc                  | Specifies the function to calculate the distance between two points.                                                                                                                                                                                                                 | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0       |\n| maximumLoops              | Maximum number of iterations.                                                                                                                                                                                                                                                        | number                                                                 | 0       |\n| enableObstacleAvoidance   | Whether to enable obstacle avoidance.                                                                                                                                                                                                                                                | boolean                                                                | false   |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## Example\n\n### Built-in Polyline Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Polyline Edge","order":"6"},"isInternal":false,"tokens":2076,"sizeBytes":8303},{"name":"Polyline.zh.md","path":"packages/site/docs/manual/element/edge/Polyline.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Polyline.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 折线边 Polyline\norder: 6\n---\n\n## 概述\n\n折线是由多条直线段组成的边，适合在复杂布局中绕过障碍物连接节点。\n\n使用场景：\n\n- 适用于复杂布局的图，如电路图、管道图。\n\n- 当需要绕过其他节点或障碍物时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                             | 类型                                                                                    | 默认值 | 必选 |\n| ------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义折线的转折点 | [Point](#point)[]                                                                       | []     |      |\n| radius        | 转折点圆角半径                   | number                                                                                  | 0      |      |\n| router        | 是否启用路由                     | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false  |      |\n\n### OrthRouter\n\n| 属性    | 描述                                                                   | 类型                | 默认值 |\n| ------- | ---------------------------------------------------------------------- | ------------------- | ------ |\n| type    | 正交路由，通过在路径上添加额外的控制点，使得边的每一段都保持水平或垂直 | `'orth'`            | -      |\n| padding | 节点连接点与转角的最小距离                                             | [Padding](#padding) | `0`    |\n\n### ShortestPathRouter\n\n| 属性                      | 描述                                                                                                                                              | 类型                                                                   | 默认值 |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------ |\n| type                      | 最短路径路由，是正交路由 `'orth'` 的智能版本。该路由由水平或垂直的正交线段组成。采用 A\\* 算法计算最短路径，并支持自动避开路径上的其他节点（障碍） | `'shortest-path'`                                                      | -      |\n| offset                    | 节点锚点与转角的最小距离                                                                                                                          | [Padding](#padding)                                                    | 0      |\n| gridSize                  | grid 格子大小                                                                                                                                     | number                                                                 | 0      |\n| maxAllowedDirectionChange | 支持的最大旋转角度（弧度）                                                                                                                        | number                                                                 | 0      |\n| startDirections           | 节点的可能起始方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| endDirections             | 节点的可能结束方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| directionMap              | 指定可移动的方向                                                                                                                                  | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0      |\n| penalties                 | 表示在路径搜索过程中某些路径的额外代价。key 为弧度值，value 为代价                                                                                | { [key: string]: number }                                              | 0      |\n| distFunc                  | 指定计算两点之间距离的函数                                                                                                                        | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0      |\n| maximumLoops              | 最大迭代次数                                                                                                                                      | number                                                                 | 0      |\n| enableObstacleAvoidance   | 是否开启避障                                                                                                                                      | boolean                                                                | false  |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## 示例\n\n### 内置折线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"折线边 Polyline","order":"6"},"isInternal":false,"tokens":1394,"sizeBytes":6390},{"name":"Quadratic.en.md","path":"packages/site/docs/manual/element/edge/Quadratic.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Quadratic.en.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Quadratic Bezier Curve Edge\norder: 6\n---\n\n## Overview\n\nA quadratic Bezier curve is a smooth curve whose shape is determined by a start point, an end point, and a control point.\n\nUse cases:\n\n- Suitable for moderately complex graphs, such as relationship graphs and network graphs.\n\n- Use when smooth node connections are needed with limited computational resources.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type            | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [Point](#point) | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number          | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number          | 30      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Quadratic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Quadratic Bezier Curve Edge","order":"6"},"isInternal":false,"tokens":831,"sizeBytes":3321},{"name":"Quadratic.zh.md","path":"packages/site/docs/manual/element/edge/Quadratic.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/edge/Quadratic.zh.md","title":"Edge Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 二次贝塞尔曲线边 Quadratic\norder: 6\n---\n\n## 概述\n\n二次贝塞尔曲线是一种平滑的曲线，其形状由起点、终点和一个控制点决定。\n\n使用场景：\n\n- 适用于中等复杂度的图，如关系图、网络图。\n\n- 当需要平滑连接节点且计算资源有限时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型            | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | --------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [Point](#point) | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number          | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number          | 30     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置二次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"二次贝塞尔曲线边 Quadratic","order":"6"},"isInternal":false,"tokens":638,"sizeBytes":3020},{"name":"BaseNode.en.md","path":"packages/site/docs/manual/element/node/BaseNode.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/BaseNode.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Common Node Configuration\norder: 1\n---\n\nThis document introduces the common configuration properties for built-in nodes.\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {}, // Node style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default  | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name         | [Type](#type)           | `circle` |          |\n| style     | Node style configuration, including color, size, etc.          | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                       | [State](#state)         | -        |          |\n| palette   | Define node palette for mapping colors based on different data | [Palette](#palette)     | -        |          |\n| animation | Define animation effects for nodes                             | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the node type, built-in node type name or custom node name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: The `type` property also supports dynamic configuration, allowing you to dynamically select node types based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Node](/en/manual/element/node/circle)\n- `diamond`: [Diamond Node](/en/manual/element/node/diamond)\n- `donut`: [Donut Node](/en/manual/element/node/donut)\n- `ellipse`: [Ellipse Node](/en/manual/element/node/ellipse)\n- `hexagon`: [Hexagon Node](/en/manual/element/node/hexagon)\n- `html`: [HTML Node](/en/manual/element/node/html)\n- `image`: [Image Node](/en/manual/element/node/image)\n- `rect`: [Rectangle Node](/en/manual/element/node/rect)\n- `star`: [Star Node](/en/manual/element/node/star)\n- `triangle`: [Triangle Node](/en/manual/element/node/triangle)\n\n## Style\n\nDefines the style of nodes, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Node: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the node data object (`NodeData`), containing all data information of the node.\n\nA complete node consists of the following parts:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the node, representing the primary shape of the node, such as rectangle, circle, etc.\n- `label`: Text label, usually used to display the name or description of the node\n- `icon`: Icon graphic, usually used to display node icons, can be images or text icons\n- `badge`: Badge, by default located at the top-right corner of the node\n- `halo`: Graphic showing halo effect around the main graphic\n- `port`: Connection points on the node, used to connect edges\n\nThe following style configurations are explained in order by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the node, defining the basic shape and appearance of the node. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSetting the basic appearance of nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdding transparency and shadow effects to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreating nodes with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete main graphic style configuration is as follows:\n\n| Property                        | Description                                                                                                                                      | Type                          | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current node/combo is collapsed                                                                                                      | boolean                       | false     |          |\n| cursor                          | Node mouse hover style, [options](#cursor)                                                                                                       | string                        | default   |          |\n| fill                            | Node fill color                                                                                                                                  | string                        | `#1783FF` |          |\n| fillOpacity                     | Node fill color transparency                                                                                                                     | number \\| string              | 1         |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick up | number                        | 0         |          |\n| lineCap                         | Node stroke end style                                                                                                                            | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Node stroke dash style                                                                                                                           | number[]                      | -         |          |\n| lineDashOffset                  | Node stroke dash offset                                                                                                                          | number                        | -         |          |\n| lineJoin                        | Node stroke join style                                                                                                                           | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Node stroke width                                                                                                                                | number                        | 1         |          |\n| opacity                         | Node transparency                                                                                                                                | number \\| string              | 1         |          |\n| pointerEvents                   | How the node responds to pointer events, [options](#pointerevents)                                                                               | string                        | `auto`    |          |\n| shadowBlur                      | Node shadow blur                                                                                                                                 | number                        | -         |          |\n| shadowColor                     | Node shadow color                                                                                                                                | string                        | -         |          |\n| shadowOffsetX                   | Node shadow offset in x-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowOffsetY                   | Node shadow offset in y-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowType                      | Node shadow type                                                                                                                                 | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Node size, quick setting for node width and height, [options](#size)                                                                             | number \\| number[]            | 32        |          |\n| stroke                          | Node stroke color                                                                                                                                | string                        | `#000`    |          |\n| strokeOpacity                   | Node stroke color transparency                                                                                                                   | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given node                                                                 | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                                   | string                        | -         |          |\n| visibility                      | Whether the node is visible                                                                                                                      | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Node x coordinate                                                                                                                                | number                        | 0         |          |\n| y                               | Node y coordinate                                                                                                                                | number                        | 0         |          |\n| z                               | Node z coordinate                                                                                                                                | number                        | 0         |          |\n| zIndex                          | Node rendering level                                                                                                                             | number                        | 0         |          |\n\n#### Size\n\nNode size, quick setting for node width and height, supports three configuration methods:\n\n- number: Indicates that the node width and height are the same as the specified value\n- [number, number]: Indicates that the node width and height are represented by array elements indicating the node's width and height respectively\n- [number, number, number]: Indicates that the node width, height, and depth are represented by array elements\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. You can refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be a target for responding to events\n- **`visiblepainted`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n- **`visiblestroke`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n- **`visible`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by the values of `fill` and `stroke`\n- **`painted`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by the value of `visibility`\n- **`fill`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n  - Not affected by the value of `visibility`\n- **`stroke`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n  - Not affected by the value of `visibility`\n- **`all`**: Will respond to events as long as entering the fill and stroke areas of the graphic, not affected by the values of `fill`, `stroke`, and `visibility`\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely unresponsive to events\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // Node does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Style\n\nLabels are used to display text information of nodes, supporting various style configurations and layout methods. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Node Name',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'This is a very long node name that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdding background to labels to improve readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Important Node',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete label style configuration is as follows:\n\n| Property                 | Description                                                                                                                        | Type                                                                        | Default   | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to display node label                                                                                                      | boolean                                                                     | true      |          |\n| labelCursor              | Style displayed when mouse hovers over node label, [options](#cursor)                                                              | string                                                                      | `default` |          |\n| labelFill                | Node label text color                                                                                                              | string                                                                      | -         |          |\n| labelFontFamily          | Node label font family                                                                                                             | string                                                                      | -         |          |\n| labelFontSize            | Node label font size                                                                                                               | number                                                                      | 12        |          |\n| labelFontStyle           | Node label font style                                                                                                              | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Node label font variant                                                                                                            | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Node label font weight                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                                       | number                                                                      | 0         |          |\n| labelLetterSpacing       | Node label letter spacing                                                                                                          | number \\| string                                                            | -         |          |\n| labelLineHeight          | Node label line height                                                                                                             | number \\| string                                                            | -         |          |\n| labelMaxLines            | Maximum number of lines for node label                                                                                             | number                                                                      | 1         |          |\n| labelMaxWidth            | Maximum width of node label, [options](#labelmaxwidth)                                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Node label offset in x-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelOffsetY             | Node label offset in y-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelPadding             | Node label padding                                                                                                                 | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Position of node label relative to node main graphic, [options](#labelplacement)                                                   | string                                                                      | `bottom`  |          |\n| labelText                | Node label text content                                                                                                            | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Node label text horizontal alignment                                                                                               | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Node label text baseline                                                                                                           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Node label text decoration line color                                                                                              | string                                                                      | -         |          |\n| labelTextDecorationLine  | Node label text decoration line                                                                                                    | string                                                                      | -         |          |\n| labelTextDecorationStyle | Node label text decoration line style                                                                                              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Node label text overflow handling                                                                                                  | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Node label text path                                                                                                               | Path                                                                        | -         |          |\n| labelWordWrap            | Whether node label enables automatic line wrapping. After enabling labelWordWrap, parts exceeding labelMaxWidth wrap automatically | boolean                                                                     | false     |          |\n| labelZIndex              | Node label rendering level                                                                                                         | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nAvailable values: `left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text wraps when exceeding this width:\n\n- string: Defines maximum width as a percentage relative to node width. For example, `50%` means label width does not exceed half of the node width\n- number: Defines maximum width in pixels. For example, 100 means the maximum width of the label is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background is used to display the background of node labels:\n\n| Property                      | Description                                                                                                                                                                         | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to display node label background                                                                                                                                            | boolean                                  | false     |\n| labelBackgroundCursor         | Node label background mouse hover style, [options](#cursor)                                                                                                                         | string                                   | `default` |\n| labelBackgroundFill           | Node label background fill color                                                                                                                                                    | string                                   | -         |\n| labelBackgroundFillOpacity    | Node label background transparency                                                                                                                                                  | number                                   | 1         |\n| labelBackgroundHeight         | Node label background height                                                                                                                                                        | string \\| number                         | -         |\n| labelBackgroundLineDash       | Node label background dash configuration                                                                                                                                            | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Node label background dash offset                                                                                                                                                   | number                                   | -         |\n| labelBackgroundLineWidth      | Node label background stroke line width                                                                                                                                             | number                                   | -         |\n| labelBackgroundRadius         | Node label background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Node label background shadow blur degree                                                                                                                                            | number                                   | -         |\n| labelBackgroundShadowColor    | Node label background shadow color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Node label background shadow X direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Node label background shadow Y direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundStroke         | Node label background stroke color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Node label background stroke transparency                                                                                                                                           | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Whether node label background is visible                                                                                                                                            | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Node label background rendering level                                                                                                                                               | number                                   | 1         |\n\n### Halo Style\n\nHalo is an effect displayed around the node's main graphic, usually used for highlighting or indicating special states of nodes.\n\n#### Basic Halo Effect\n\nAdding basic halo effect to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete halo style configuration is as follows:\n\n| Property          | Description                                                                                                                   | Type                   | Default                                 | Required |\n| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------------------------------------- | -------- |\n| halo              | Whether to display node halo                                                                                                  | boolean                | false                                   |          |\n| haloCursor        | Node halo mouse hover style, [options](#cursor)                                                                               | string                 | `default`                               |          |\n| haloDraggable     | Whether node halo allows dragging                                                                                             | boolean                | true                                    |          |\n| haloDroppable     | Whether node halo allows receiving dragged elements                                                                           | boolean                | true                                    |          |\n| haloFillRule      | Node halo fill rule                                                                                                           | `nonzero` \\| `evenodd` | -                                       |          |\n| haloFilter        | Node halo filter                                                                                                              | string                 | -                                       |          |\n| haloLineWidth     | Node halo stroke width                                                                                                        | number                 | 3                                       |          |\n| haloPointerEvents | Whether node halo effect responds to pointer events, [options](#pointerevents)                                                | string                 | `none`                                  |          |\n| haloStroke        | Node halo stroke color, **this property is used to set the color of the halo around the node, helping to highlight the node** | string                 | Consistent with main graphic fill color |          |\n| haloStrokeOpacity | Node halo stroke color transparency                                                                                           | number                 | 0.25                                    |          |\n| haloVisibility    | Node halo visibility                                                                                                          | `visible` \\| `hidden`  | `visible`                               |          |\n| haloZIndex        | Node halo rendering level                                                                                                     | number                 | -1                                      |          |\n\n### Icon Style\n\nNode icons support three common usage methods: text icons, image icons, and IconFont icons. The configurations for these three methods are shown below:\n\n#### 1. Text Icons\n\nUsing text directly as icons, suitable for simple identifiers:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // Icon text content\n      iconFill: '#C41D7F', // Deep pink icon\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. Image Icons\n\nUsing images as icons, supporting various image formats:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont Icons\n\nUsing IconFont font icons, you need to import the corresponding font files first:\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // Light blue background\n      stroke: '#1890FF', // Blue border\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete icon style configuration is as follows:\n\n| Property                | Description                                          | Type                                                                        | Default                     |\n| ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to display node icon                         | boolean                                                                     | true                        |\n| iconFill                | Node icon text color                                 | string                                                                      | -                           |\n| iconFontFamily          | Node icon font family                                | string                                                                      | -                           |\n| iconFontSize            | Node icon font size                                  | number                                                                      | 16                          |\n| iconFontStyle           | Node icon font style                                 | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Node icon font variant                               | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Node icon font weight                                | number \\| string                                                            | `normal`                    |\n| iconHeight              | Node icon height                                     | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Node icon text letter spacing                        | number \\| string                                                            | -                           |\n| iconLineHeight          | Node icon text line height                           | number \\| string                                                            | -                           |\n| iconMaxLines            | Maximum lines for node icon text                     | number                                                                      | 1                           |\n| iconRadius              | Node icon border radius                              | number                                                                      | 0                           |\n| iconSrc                 | Node image source. Has higher priority than iconText | string                                                                      | -                           |\n| iconText                | Node icon text                                       | string                                                                      | -                           |\n| iconTextAlign           | Node icon text horizontal alignment                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`                      |\n| iconTextBaseline        | Node icon text baseline                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`                |\n| iconTextDecorationColor | Node icon text decoration line color                 | string                                                                      | -                           |\n| iconTextDecorationLine  | Node icon text decoration line                       | string                                                                      | -                           |\n| iconTextDecorationStyle | Node icon text decoration line style                 | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Node icon text overflow handling                     | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconWidth               | Node icon width                                      | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether node icon text automatically wraps           | boolean                                                                     | -                           |\n\n### Badge Style\n\nBadges are small markers displayed on nodes, usually used to show status, quantity, or other auxiliary information. Supports displaying multiple badges simultaneously with customizable positions.\n\n#### Single Badge\n\nAdding a simple badge to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Default display at the top\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdding multiple badges at different positions to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // Whether to display badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background color palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nCompletely customizing badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete badge style configuration is as follows:\n\n| Property     | Description                      | Type                                  | Default                           |\n| ------------ | -------------------------------- | ------------------------------------- | --------------------------------- |\n| badge        | Whether the node displays badges | boolean                               | true                              |\n| badgePalette | Badge background color palette   | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Node badge settings              | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                                         | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether node badge displays background                                                                                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Node badge background mouse hover style, [options](#cursor)                                                                                                                                                                                                                                                         | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Node badge background fill color. If not specified, badgePalette is considered for allocation in order                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Node badge background fill transparency                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Node badge background filter                                                                                                                                                                                                                                                                                        | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Node badge background height                                                                                                                                                                                                                                                                                        | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Node badge background dash configuration                                                                                                                                                                                                                                                                            | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Node badge background dash offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Node badge background stroke line width                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Node badge background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, separated by spaces | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Node badge background shadow blur degree                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Node badge background shadow color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Node badge background shadow X direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Node badge background shadow Y direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Node badge background stroke color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Node badge background stroke transparency                                                                                                                                                                                                                                                                           | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether node badge background is visible                                                                                                                                                                                                                                                                            | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | Node badge background rendering level                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| fill                     | Node badge text color                                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| fontFamily               | Node badge font family                                                                                                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| fontSize                 | Node badge font size                                                                                                                                                                                                                                                                                                | number                                                                                                                                                                 | 8            |\n| fontStyle                | Node badge font style                                                                                                                                                                                                                                                                                               | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Node badge font variant                                                                                                                                                                                                                                                                                             | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Node badge font weight                                                                                                                                                                                                                                                                                              | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Node badge line height                                                                                                                                                                                                                                                                                              | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Node badge line width                                                                                                                                                                                                                                                                                               | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Maximum lines for node badge text                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 1            |\n| offsetX                  | Node badge offset in x-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| offsetY                  | Node badge offset in y-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| padding                  | Node badge padding                                                                                                                                                                                                                                                                                                  | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Position of node badge relative to node main graphic. If not specified, defaults to clockwise arrangement starting from top-right corner                                                                                                                                                                            | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Node badge text content                                                                                                                                                                                                                                                                                             | string                                                                                                                                                                 | -            |\n| textAlign                | Node badge text horizontal alignment                                                                                                                                                                                                                                                                                | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Node badge text baseline                                                                                                                                                                                                                                                                                            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Node badge text decoration line color                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Node badge text decoration line                                                                                                                                                                                                                                                                                     | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Node badge text decoration line style                                                                                                                                                                                                                                                                               | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Node badge text overflow handling                                                                                                                                                                                                                                                                                   | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether node badge is visible                                                                                                                                                                                                                                                                                       | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether node badge text automatically wraps                                                                                                                                                                                                                                                                         | boolean                                                                                                                                                                | -            |\n| zIndex                   | Node badge rendering level                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                 | 3            |\n\n### Port Style\n\nPorts are connection points on nodes, used to connect edges. Supports adding multiple ports at different positions on nodes with customizable styles.\n\n#### Basic Ports\n\nAdding four basic directional ports to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Position Ports\n\nUsing percentages or absolute coordinates to precisely position ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // Relative position: 20% from top-left\n        { key: 'custom2', placement: [0.8, 0] }, // Relative position: 80% from top-right\n        { key: 'custom3', placement: [1, 0.5] }, // Relative position: right center\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Differentiated Port Styles\n\nSetting different styles for different ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // Green input port\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // Red output port\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // Unified stroke color\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete port style configuration is as follows:\n\n| Property | Description                                                  | Type                                | Default | Required |\n| -------- | ------------------------------------------------------------ | ----------------------------------- | ------- | -------- |\n| port     | Whether the node displays ports                              | boolean                             | true    |          |\n| ports    | Node port configuration, supports configuring multiple ports | [PortStyleProps](#portstyleprops)[] | -       |          |\n\n#### PortStyleProps\n\n| Property          | Description                                                                                                                                                                                                                                                  | Type                                                                                                                                                                                                   | Default   | Required |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- |\n| key               | Key value of node port, defaults to the index of the node port                                                                                                                                                                                               | string                                                                                                                                                                                                 | -         |          |\n| placement         | Position of node port relative to node main graphic                                                                                                                                                                                                          | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓        |\n| r                 | Node port radius <br> - If set to undefined, the port is treated as a point, not displayed on canvas but exists, edges will preferentially connect to the nearest port <br> - If set to a number, the port is treated as a circle with radius specified here | number                                                                                                                                                                                                 | -         |          |\n| linkToCenter      | Whether edges connect to the center of the node port <br> - If true, edges connect to the center of the node port <br> - If false, edges connect to the edge of the node port                                                                                | boolean                                                                                                                                                                                                | false     |          |\n| cursor            | Node port mouse hover style, [options](#cursor)                                                                                                                                                                                                              | string                                                                                                                                                                                                 | `default` |          |\n| fill              | Node port fill color                                                                                                                                                                                                                                         | string                                                                                                                                                                                                 | -         |          |\n| fillOpacity       | Node port fill transparency                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | 1         |          |\n| isBillboard       | Whether node port has Billboard effect                                                                                                                                                                                                                       | boolean                                                                                                                                                                                                | -         |          |\n| isSizeAttenuation | Whether node port enables size attenuation                                                                                                                                                                                                                   | boolean                                                                                                                                                                                                | -         |          |\n| lineDash          | Node port stroke dash configuration                                                                                                                                                                                                                          | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |          |\n| lineDashOffset    | Node port stroke dash offset                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| lineWidth         | Node port stroke line width                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | -         |          |\n| shadowBlur        | Node port shadow blur degree                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| shadowColor       | Node port shadow color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| shadowOffsetX     | Node port shadow X direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| shadowOffsetY     | Node port shadow Y direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| stroke            | Node port stroke color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| strokeOpacity     | Node port stroke transparency                                                                                                                                                                                                                                | number \\| string                                                                                                                                                                                       | 1         |          |\n| visibility        | Whether node port is visible                                                                                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |          |\n| zIndex            | Node port rendering level                                                                                                                                                                                                                                    | number                                                                                                                                                                                                 | 2         |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select a node or hovering to activate an edge, only certain state identifications are made on the element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of the graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\nFor example, when a node is in the `focus` state, you can add a stroke with width 3 and orange color.\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefines animation effects for nodes, supporting the following two configuration methods:\n\n1. Disable all node animations\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when nodes enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when nodes enter the canvas\n- `update`: Animation when nodes are updated\n- `exit`: Animation when nodes leave the canvas\n- `show`: Animation when nodes are shown from hidden state\n- `hide`: Animation when nodes are hidden\n- `collapse`: Animation when nodes are collapsed\n- `expand`: Animation when nodes are expanded\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure nodes, such as:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // Only animate x and y properties during updates\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable animations for specific stages:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // Disable node entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefines the color palette for nodes, i.e., predefined node color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For the definition of palettes, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to id as the grouping field                    | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify the current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                 | `group` \\| `value`            | `group` |\n\nFor example, assigning node colors to a group of data by `category` field, so that nodes of the same category have the same color:\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau is the palette name, defaults to assigning colors based on ID\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Common Node Configuration","order":"1"},"isInternal":false,"tokens":22082,"sizeBytes":88342},{"name":"BaseNode.zh.md","path":"packages/site/docs/manual/element/node/BaseNode.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/BaseNode.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 节点通用配置项\norder: 1\n---\n\n本文介绍内置节点通用属性配置。\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {}, // 节点样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](#type)           | `circle` |      |\n| style     | 节点样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定节点类型，内置节点类型名称或自定义节点的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据节点数据动态选择节点类型：\n\n```js\nconst graph = new Graph({\n  node: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形节点](/manual/element/node/circle)\n- `diamond`：[菱形节点](/manual/element/node/diamond)\n- `donut`：[甜甜圈节点](/manual/element/node/donut)\n- `ellipse`：[椭圆节点](/manual/element/node/ellipse)\n- `hexagon`：[六边形节点](/manual/element/node/hexagon)\n- `html`：[HTML 节点](/manual/element/node/html)\n- `image`：[图片节点](/manual/element/node/image)\n- `rect`：[矩形节点](/manual/element/node/rect)\n- `star`：[星形节点](/manual/element/node/star)\n- `triangle`：[三角形节点](/manual/element/node/triangle)\n\n## Style\n\n定义节点的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据节点数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `节点: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为节点数据对象 (`NodeData`)，包含节点的所有数据信息。\n\n一个完整的节点由以下几部分构成：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：节点的主图形，表示节点的主要形状，例如矩形、圆形等；\n- `label` ：文本标签，通常用于展示节点的名称或描述；\n- `icon` ：图标图形，通常用于展示节点的图标，可以是图片或者文本图标；\n- `badge` ：默认位于节点右上角的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `port` ：节点上的连接点，用于连接边。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是节点的核心部分，定义了节点的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置节点的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为节点添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的节点：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前节点/组合是否折叠                                                                     | boolean                       | false     |      |\n| cursor                          | 节点鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 节点填充色                                                                                | string                        | `#1783FF` |      |\n| fillOpacity                     | 节点填充色透明度                                                                          | number \\| string              | 1         |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 节点描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 节点描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 节点描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 节点描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 节点描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 节点透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 节点如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 节点阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 节点阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 节点阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 节点阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 节点阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 节点大小，快捷设置节点宽高，[配置项](#size)                                               | number \\| number[]            | 32        |      |\n| stroke                          | 节点描边色                                                                                | string                        | `#000`    |      |\n| strokeOpacity                   | 节点描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定节点                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 节点是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 节点 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 节点 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 节点 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 节点渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n节点大小，快捷设置节点宽高，支持三种配置方式：\n\n- number：表示节点宽高相同为指定值\n- [number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度\n- [number, number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // 节点不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示节点的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '节点名称',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '这是一个很长的节点名称需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '重要节点',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                               | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示节点标签                                                                   | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入节点标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 节点标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 节点标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 节点标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 节点标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 节点标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 节点标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                             | number                                                                      | 0         |      |\n| labelLetterSpacing       | 节点标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 节点标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 节点标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 节点标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 节点标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 节点标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 节点标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 节点标签相对于节点主图形的位置，[配置项](#labelplacement)                          | string                                                                      | `bottom`  |      |\n| labelText                | 节点标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 节点标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 节点标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 节点标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 节点标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 节点标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 节点标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 节点标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 节点标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 节点标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n可选值有：`left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于节点宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过节点宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示节点标签的背景：\n\n| 属性                          | 描述                                                                                                           | 类型                                     | 默认值    |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | 节点标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 节点标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 节点标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 节点标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 节点标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 节点标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 节点标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 节点标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 节点标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 节点标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 节点标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 节点标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 节点标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 节点标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 节点标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 节点标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 节点标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕节点主图形显示的效果，通常用于高亮显示或表示节点的特殊状态。\n\n#### 基础光晕效果\n\n为节点添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                                   | 类型                   | 默认值                       | 必选 |\n| ----------------- | ---------------------------------------------------------------------- | ---------------------- | ---------------------------- | ---- |\n| halo              | 节点光晕是否显示                                                       | boolean                | false                        |      |\n| haloCursor        | 节点光晕鼠标移入样式，[配置项](#cursor)                                | strig                  | `default`                    |      |\n| haloDraggable     | 节点光晕是否允许拖拽                                                   | boolean                | true                         |      |\n| haloDroppable     | 节点光晕是否允许接收被拖拽的元素                                       | boolean                | true                         |      |\n| haloFillRule      | 节点光晕填充规则                                                       | `nonzero` \\| `evenodd` | -                            |      |\n| haloFilter        | 节点光晕滤镜                                                           | string                 | -                            |      |\n| haloLineWidth     | 节点光晕描边宽度                                                       | number                 | 3                            |      |\n| haloPointerEvents | 节点光晕效果是否响应指针事件，[配置项](#pointerevents)                 | string                 | `none`                       |      |\n| haloStroke        | 节点光晕描边色，**此属性用于设置节点周围光晕的颜色，帮助突出显示节点** | string                 | 与主图形的填充色 `fill` 一致 |      |\n| haloStrokeOpacity | 节点光晕描边色透明度                                                   | number                 | 0.25                         |      |\n| haloVisibility    | 节点光晕可见性                                                         | `visible` \\| `hidden`  | `visible`                    |      |\n| haloZIndex        | 节点光晕渲染层级                                                       | number                 | -1                           |      |\n\n### 图标样式\n\n节点图标支持三种常见的使用方式：文字图标、图片图标和 IconFont 图标。下面分别展示这三种方式的配置：\n\n#### 1. 文字图标\n\n直接使用文字作为图标，适合简单的标识：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // 图标文字内容\n      iconFill: '#C41D7F', // 深粉色图标\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. 图片图标\n\n使用图片作为图标，支持各种图片格式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont 图标\n\n使用 IconFont 字体图标，需要先引入相应的字体文件：\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // 淡蓝色背景\n      stroke: '#1890FF', // 蓝色边框\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                | 类型                                                                        | 默认值           |\n| ----------------------- | ----------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示节点图标                    | boolean                                                                     | true             |\n| iconFill                | 节点图标文字颜色                    | string                                                                      | -                |\n| iconFontFamily          | 节点图标字体族                      | string                                                                      | -                |\n| iconFontSize            | 节点图标字体大小                    | number                                                                      | 16               |\n| iconFontStyle           | 节点图标字体样式                    | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 节点图标字体变种                    | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 节点图标字体粗细                    | number \\| string                                                            | `normal`         |\n| iconHeight              | 节点图标高度                        | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 节点图标文本字间距                  | number \\| string                                                            | -                |\n| iconLineHeight          | 节点图标文本行高                    | number \\| string                                                            | -                |\n| iconMaxLines            | 节点图标文本最大行数                | number                                                                      | 1                |\n| iconRadius              | 节点图标圆角半径                    | number                                                                      | 0                |\n| iconSrc                 | 节点图片来源。其优先级高于 iconText | string \\| ((datum) => string)                                                | -                |\n| iconText                | 节点图标文字                        | string \\| ((datum) => string)                                               | -                |\n| iconTextAlign           | 节点图标文本水平对齐方式            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`           |\n| iconTextBaseline        | 节点图标文本基线                    | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`     |\n| iconTextDecorationColor | 节点图标文本装饰线颜色              | string                                                                      | -                |\n| iconTextDecorationLine  | 节点图标文本装饰线                  | string                                                                      | -                |\n| iconTextDecorationStyle | 节点图标文本装饰线样式              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 节点图标文本溢出处理方式            | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconWidth               | 节点图标宽度                        | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 节点图标文本是否自动换行            | boolean                                                                     | -                |\n\n### 徽标样式\n\n徽标是节点上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为节点添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为节点添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 节点是否显示徽标   | boolean                               | true                              |\n| badgePalette | 节点徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 节点徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 节点徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 节点徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 节点徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 节点徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 节点徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 节点徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 节点徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 节点徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 节点徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 节点徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 节点徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 节点徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 节点徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 节点徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 节点徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 节点徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 节点徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | 节点徽标背景渲染层级                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| fill                     | 节点徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 节点徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 节点徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 节点徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 节点徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 节点徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 节点徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 节点徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 节点徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 节点徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 节点徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 节点徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 节点徽标相对于节点主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 节点徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 节点徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 节点徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 节点徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 节点徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 节点徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 节点徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 节点徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 节点徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 节点徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 连接桩样式\n\n连接桩是节点上的连接点，用于连接边。支持在节点的不同位置添加多个连接桩，并可自定义样式。\n\n#### 基础连接桩\n\n为节点添加四个基本方向的连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义位置连接桩\n\n使用百分比或绝对坐标精确定位连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // 相对位置：左上角20%处\n        { key: 'custom2', placement: [0.8, 0] }, // 相对位置：右上角80%处\n        { key: 'custom3', placement: [1, 0.5] }, // 相对位置：右边中央\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 差异化连接桩样式\n\n为不同的连接桩设置不同的样式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // 绿色输入桩\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // 红色输出桩\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // 统一的描边颜色\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的连接桩样式配置：\n\n| 属性  | 描述                                 | 类型                                | 默认值 | 必选 |\n| ----- | ------------------------------------ | ----------------------------------- | ------ | ---- |\n| port  | 节点是否显示连接桩                   | boolean                             | true   |      |\n| ports | 节点连接桩配置项，支持配置多个连接桩 | [PortStyleProps](#portstyleprops)[] |        |      |\n\n#### PortStyleProps\n\n| 属性              | 描述                                                                                                                                                                               | 类型                                                                                                                                                                                                   | 默认值    | 必选 |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ---- |\n| key               | 节点连接桩的键值，默认为节点连接桩的索引                                                                                                                                           | string                                                                                                                                                                                                 | -         |      |\n| placement         | 节点连接桩相对于节点主图形的位置                                                                                                                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓    |\n| r                 | 节点连接桩半径 <br> - 如果设置为 undefined，则连接桩被视为一个点，不在画布上显示但存在，边会优先连接到最近的连接桩 <br> - 如果设置为数字，则连接桩被视为一个圆，圆的半径由此处指定 | number                                                                                                                                                                                                 | -         |      |\n| linkToCenter      | 边是否连接到节点连接桩的中心 <br> - 若为 true，则边连接到节点连接桩的中心 <br> - 若为 false，则边连接到节点连接桩的边缘                                                            | boolean                                                                                                                                                                                                | false     |      |\n| cursor            | 节点连接桩鼠标移入样式，[配置项](#cursor)                                                                                                                                          | string                                                                                                                                                                                                 | `default` |      |\n| fill              | 节点连接桩填充颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| fillOpacity       | 节点连接桩填充透明度                                                                                                                                                               | number                                                                                                                                                                                                 | 1         |      |\n| isBillboard       | 节点连接桩是否为Billboard 效果                                                                                                                                                     | boolean                                                                                                                                                                                                | -         |      |\n| isSizeAttenuation | 节点连接桩是否启用大小衰减                                                                                                                                                         | boolean                                                                                                                                                                                                | -         |      |\n| lineDash          | 节点连接桩描边虚线配置                                                                                                                                                             | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |      |\n| lineDashOffset    | 节点连接桩描边虚线偏移量                                                                                                                                                           | number                                                                                                                                                                                                 | -         |      |\n| lineWidth         | 节点连接桩描边线宽                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |      |\n| shadowBlur        | 节点连接桩阴影模糊程度                                                                                                                                                             | number                                                                                                                                                                                                 | -         |      |\n| shadowColor       | 节点连接桩阴影颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| shadowOffsetX     | 节点连接桩阴影 X 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| shadowOffsetY     | 节点连接桩阴影 Y 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| stroke            | 节点连接桩描边颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| strokeOpacity     | 节点连接桩描边透明度                                                                                                                                                               | number \\| string                                                                                                                                                                                       | 1         |      |\n| visibility        | 节点连接桩是否可见                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |      |\n| zIndex            | 节点连接桩渲染层级                                                                                                                                                                 | number                                                                                                                                                                                                 | 2         |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个节点或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\n例如，当节点处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义节点的动画效果，支持下列两种配置方式：\n\n1. 关闭节点全部动画\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指节点在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 节点进入画布时的动画\n- `update`: 节点更新时的动画\n- `exit`: 节点离开画布时的动画\n- `show`: 节点从隐藏状态显示时的动画\n- `hide`: 节点隐藏时的动画\n- `collapse`: 节点收起时的动画\n- `expand`: 节点展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置节点，如：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // 关闭节点入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义节点的色板，即预定义节点颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `category` 字段分配节点颜色，使得同类别的节点颜色相同：\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"节点通用配置项","order":"1"},"isInternal":false,"tokens":16794,"sizeBytes":76937},{"name":"Circle.en.md","path":"packages/site/docs/manual/element/node/Circle.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Circle.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Circle Node\norder: 2\n---\n\n## Overview\n\nA circle is a symmetrical geometric shape with a uniform radius.\n\nApplicable scenarios:\n\n- Used to represent the size or weight of a node (controlled by radius).\n- Suitable for representing non-directional relationships, such as user nodes in social networks.\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node))\n\n## Example\n\n### Built-in Circle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Circle Node","order":"2"},"isInternal":false,"tokens":576,"sizeBytes":2304},{"name":"Circle.zh.md","path":"packages/site/docs/manual/element/node/Circle.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Circle.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 圆形节点 Circle\norder: 2\n---\n\n## 概述\n\n圆形是一个对称的几何形状，具有均匀的半径。\n\n适用场景：\n\n- 用于表示节点的大小或权重（通过半径控制）。\n- 适合表示无方向性的关系，如社交网络中的用户节点。\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见[BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"圆形节点 Circle","order":"2"},"isInternal":false,"tokens":485,"sizeBytes":2230},{"name":"custom-node.en.md","path":"packages/site/docs/manual/element/node/custom-node.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/custom-node.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Node\norder: 12\n---\n\nG6 provides a series of [built-in nodes](/en/manual/element/node/base-node), including [circle (Circle Node)](/en/manual/element/node/circle), [diamond (Diamond Node)](/en/manual/element/node/diamond), [donut (Donut Node)](/en/manual/element/node/donut), [ellipse (Ellipse Node)](/en/manual/element/node/ellipse), [hexagon (Hexagon Node)](/en/manual/element/node/hexagon), [html (HTML Node)](/en/manual/element/node/html), [image (Image Node)](/en/manual/element/node/image), [rect (Rectangle Node)](/en/manual/element/node/rect), [star (Star Node)](/en/manual/element/node/star), and [triangle (Triangle Node)](/en/manual/element/node/triangle). These built-in nodes can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter needs that these basic nodes cannot satisfy. In such cases, you need to create custom nodes. Don't worry, this is simpler than you might think!\n\n## Ways to Create Custom Nodes <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are mainly two approaches to creating custom nodes:\n\n### 1. Inherit from Existing Node Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach, where you can choose to inherit from one of the following types:\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - The most basic node class, providing core node functionality\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - Circle node\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - Rectangle node\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - Ellipse node\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - Diamond node\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - Triangle node\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - Star node\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - Image node\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - Donut node\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - Hexagon node\n\n**Why choose this approach?**\n\n- 📌 **Less Code**: Reuse properties and methods of existing nodes, only focus on new features\n- 📌 **Rapid Development**: Suitable for most project needs, quickly achieve business goals\n- 📌 **Easy Maintenance**: Clear code structure with well-defined inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing node types (recommended), you can jump directly to [Create Your First Custom Node in Three Steps](#create-your-first-custom-node-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing node types don't meet your requirements, you can create nodes from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum Freedom**: Complete control over every detail of the node, achieving any complex effects\n- 📌 **Special Requirements**: Highly customized scenarios that existing node types cannot satisfy\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom nodes built from scratch require handling all details yourself, including graphics rendering, event response, state changes, etc., with higher development difficulty. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) for implementation.\n:::\n\n## Create Your First Custom Node in Three Steps\n\nLet's start with a simple example - creating a **rectangle node with main and subtitle**:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// Step 1: Create custom node class\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// Step 2: Register custom node\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// Step 3: Use custom node\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Node Class\n\nInherit from G6's `Rect` (rectangle node) and add a subtitle:\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// Create custom node, inheriting from Rect\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### Step 2: Register Custom Node\n\nUse the `register` method to register the node type so that G6 can recognize your custom node:\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `dual-label-node` is the name we give to this custom node, which will be used in configuration later\n- Class definition: `DualLabelNode` is the node class we just created\n\n### Step 3: Apply Custom Node\n\nUse the custom node in graph configuration:\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom node. It looks simple, but this process contains the core concept of custom nodes: **inherit from a basic node type**, then **override the `render` method** to add custom content.\n\n## Understanding Data Flow: How to Access Data in Custom Nodes\n\nBefore creating complex custom nodes, understanding how data flows into custom nodes is very important. G6 provides multiple ways to access data for custom nodes:\n\n### Method 1: Through `attributes` Parameter (Recommended)\n\nThe first parameter `attributes` of the `render` method contains processed style attributes, including data-driven styles:\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes contains all style attributes, including data-driven styles\n    console.log('All properties of current node:', attributes);\n\n    // If customData: (d) => d.data.someValue is defined in style\n    // Then you can access it through attributes.customData\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Method 2: Through `this.context.graph` to Access Raw Data\n\nWhen you need to access the node's raw data, you can get it through the graph instance:\n\n```js\nclass CustomNode extends Rect {\n  // Convenient data access method\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Get complete node data\n    const nodeData = this.nodeData;\n    console.log('Complete node data:', nodeData);\n\n    // Get business data from data field\n    const businessData = this.data;\n    console.log('Business data:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Complete Data Flow Process\n\nLet's understand how data flows from graph data to custom nodes through a specific example:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // Method 2: Get raw data through graph\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Method 1: Get processed styles from attributes\n    console.log('Get from attributes:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // Method 2: Get from raw data\n    console.log('Get from raw data:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Use data to render custom content\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // This is the node's business data\n        data: {\n          name: 'Zhang San',\n          role: 'Developer',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // Map data from data field to style attributes\n      iconUrl: (d) => d.data.icon, // This becomes attributes.iconUrl\n      userName: (d) => d.data.name, // This becomes attributes.userName\n      // Main title uses role information\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=Data Flow Summary}\n\n1. **Graph Data Definition**: Define business data in `data.nodes[].data`\n2. **Style Mapping**: Use functions in `node.style` to map data to style attributes\n3. **Node Access**: Access data in custom nodes through `attributes` or `this.context.graph`\n4. **Rendering Usage**: Use the obtained data to render custom graphics\n   :::\n\n## From Simple to Complex: Gradually Building Feature-Rich Nodes\n\nLet's gradually increase the complexity and functionality of nodes through practical examples.\n\n### Example 1: User Card Node with Icon and Badge\n\nThis example shows how to create a user card node containing avatar, name, and status badge:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // Avatar style\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // Circular avatar\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // Status badge style\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // Username style\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // Role label style\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Add various components\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: 'Zhang Xiaoming',\n          role: 'Frontend Engineer',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // Data mapping\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 2: Node with Clickable Action Button\n\nAdd a blue button to the node that triggers events (prints logs or executes callbacks) when clicked.\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // Mouse pointer becomes hand\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // Add click event to button\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // Prevent event bubbling to avoid triggering node click event\n        e.stopPropagation();\n\n        // Execute business logic\n        console.log('Button clicked on node:', this.id);\n\n        // If there's a callback function in data, call it\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // Mark as bound to avoid duplicate binding\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // Add a button\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // Specify using our custom node\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 3: Node Responding to State Changes (Click to Change Color)\n\nCommon interactions require nodes and edges to provide feedback through style changes, such as when the mouse moves over a node, clicking to select nodes/edges, or activating interactions on edges through interaction. All these require changing the styles of nodes and edges. There are two ways to achieve this effect:\n\n1. Get the current state from `data.states` and handle state changes in the custom node class;\n2. Separate interaction state from raw data and node drawing logic, only update the node.\n\nWe recommend users use the second approach to implement node state adjustments, which can be achieved through the following steps:\n\n1. Implement custom node;\n2. Configure node state styles in graph configuration;\n3. Set node state through the `graph.setElementState()` method.\n\nBased on rect, extend a hole shape with default white fill color that turns orange when clicked. The sample code to achieve this effect is as follows:\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. Define node class\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. Register node\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. Create graph instance\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // Mouse selected state\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. Add node interaction\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Custom Node","order":"12"},"isInternal":false,"tokens":5165,"sizeBytes":20671},{"name":"custom-node.zh.md","path":"packages/site/docs/manual/element/node/custom-node.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/custom-node.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义节点\norder: 12\n---\n\nG6 提供了一系列 [内置节点](/manual/element/node/base-node)，包含 [circle（圆形节点）](/manual/element/node/circle)、[diamond（菱形节点）](/manual/element/node/diamond)、[donut（甜甜圈节点）](/manual/element/node/donut)、[ellipse（椭圆节点）](/manual/element/node/ellipse)、[hexagon（六边形节点）](/manual/element/node/hexagon)、[html（HTML节点）](/manual/element/node/html)、[image（图片节点）](/manual/element/node/image)、[rect（矩形节点）](/manual/element/node/rect)、[star（星形节点）](/manual/element/node/star) 和 [triangle（三角形节点）](/manual/element/node/triangle)。这些内置节点能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础节点无法满足的需求。这时，你需要创建自定义节点。别担心，这比你想象的要简单！\n\n## 自定义节点的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义节点的方式主要有两种途径：\n\n### 1. 继承现有节点类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - 最基础的节点类，提供节点的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - 圆形节点\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - 矩形节点\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - 椭圆节点\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - 菱形节点\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - 三角形节点\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - 星形节点\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - 图片节点\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - 甜甜圈节点\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - 六边形节点\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有节点的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有节点类型（推荐），可以直接跳到 [三步创建你的第一个自定义节点](#三步创建你的第一个自定义节点) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有节点类型都不满足需求，你可以基于 G 的底层图形系统从零创建节点。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制节点的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有节点类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义节点需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义节点\n\n让我们从一个简单的例子开始 - 创建一个 **带有主副标题的矩形节点**：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// 第一步：创建自定义节点类\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// 第二步：注册自定义节点\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// 第三步：使用自定义节点\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义节点类\n\n继承 G6 的 `Rect`（矩形节点），并添加一个副标题：\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 创建自定义节点，继承自 Rect\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### 第二步：注册自定义节点\n\n使用 `register` 方法注册节点类型，这样 G6 才能识别你的自定义节点：\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`dual-label-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：`DualLabelNode` 是我们刚刚创建的节点类\n\n### 第三步：应用自定义节点\n\n在图配置中使用自定义节点：\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义节点。它看起来很简单，但这个过程包含了自定义节点的核心思想：**继承一个基础节点类型**，然后 **重写 `render` 方法** 来添加自定义内容。\n\n## 理解数据流：如何在自定义节点中获取数据\n\n在创建复杂的自定义节点之前，理解数据如何流入自定义节点是非常重要的。G6 为自定义节点提供了多种数据获取方式：\n\n### 方式一：通过 `attributes` 参数（推荐）\n\n`render` 方法的第一个参数 `attributes` 包含了经过处理的样式属性，包括数据驱动的样式：\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes 包含了所有样式属性，包括数据驱动的样式\n    console.log('当前节点的所有属性:', attributes);\n\n    // 如果在 style 中定义了 customData: (d) => d.data.someValue\n    // 那么可以通过 attributes.customData 获取\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 方式二：通过 `this.context.graph` 获取原始数据\n\n当你需要访问节点的原始数据时，可以通过图实例获取：\n\n```js\nclass CustomNode extends Rect {\n  // 便捷的数据获取方法\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 获取节点的完整数据\n    const nodeData = this.nodeData;\n    console.log('节点完整数据:', nodeData);\n\n    // 获取 data 字段中的业务数据\n    const businessData = this.data;\n    console.log('业务数据:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 数据传递的完整流程\n\n让我们通过一个具体例子来理解数据是如何从图数据传递到自定义节点的：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // 方式二：通过 graph 获取原始数据\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 方式一：从 attributes 获取处理后的样式\n    console.log('从 attributes 获取:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // 方式二：从原始数据获取\n    console.log('从原始数据获取:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 使用数据渲染自定义内容\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // 这里是节点的业务数据\n        data: {\n          name: '张三',\n          role: '开发者',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // 将 data 中的数据映射到样式属性\n      iconUrl: (d) => d.data.icon, // 这会变成 attributes.iconUrl\n      userName: (d) => d.data.name, // 这会变成 attributes.userName\n      // 主标题使用角色信息\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=数据流总结}\n\n1. **图数据定义**：在 `data.nodes[].data` 中定义业务数据\n2. **样式映射**：在 `node.style` 中使用函数将数据映射到样式属性\n3. **节点获取**：在自定义节点中通过 `attributes` 或 `this.context.graph` 获取数据\n4. **渲染使用**：使用获取到的数据渲染自定义图形\n   :::\n\n## 从简单到复杂：逐步构建功能丰富的节点\n\n让我们通过实际例子，逐步增加节点的复杂度和功能。\n\n### 示例一：带图标和徽章的用户卡片节点\n\n这个例子展示如何创建一个包含头像、姓名、状态徽章的用户卡片节点：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // 头像样式\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // 圆形头像\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // 状态徽章样式\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // 用户名样式\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // 角色标签样式\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 添加各个组件\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: '张小明',\n          role: '前端工程师',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // 数据映射\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例二：可点击操作按钮的节点\n\n给节点加一个蓝色按钮，点击后触发事件（打印日志或执行回调）。\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // 鼠标指针变为手型\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // 为按钮添加点击事件\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // 阻止事件冒泡，避免触发节点的点击事件\n        e.stopPropagation();\n\n        // 执行业务逻辑\n        console.log('Button clicked on node:', this.id);\n\n        // 如果数据中有回调函数，则调用\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // 标记已绑定事件，避免重复绑定\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // 添加一个按钮\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // 指定使用我们的自定义节点\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例三：响应状态变化的节点（点击变色）\n\n常见的交互都需要节点和边通过样式变化做出反馈，例如鼠标移动到节点上、点击选中节点/边、通过交互激活边上的交互等，都需要改变节点和边的样式，有两种方式来实现这种效果：\n\n1. 从 `data.states` 获取当前状态，在自定义节点类中处理状态变化；\n2. 将交互状态同原始数据和绘制节点的逻辑分开，仅更新节点。\n\n我们推荐用户使用第二种方式来实现节点的状态调整，可以通过以下方式来实现：\n\n1. 实现自定义节点；\n2. 在图配置项中配置节点状态样式；\n3. 通过 `graph.setElementState()` 方法来设置节点状态。\n\n基于 rect 扩展出一个 hole 图形，默认填充色为白色，当鼠标点击时变成橙色，实现这一效果的示例代码如下：\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. 定义节点类\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. 注册节点\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. 创建图实例\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // 鼠标选中状态\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. 添加节点交互\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"自定义节点","order":"12"},"isInternal":false,"tokens":4008,"sizeBytes":20230},{"name":"Diamond.en.md","path":"packages/site/docs/manual/element/node/Diamond.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Diamond.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Diamond Node\norder: 3\n---\n\n## Overview\n\nA diamond is a geometric shape with four equal sides and diagonal symmetry.\n\nApplicable scenarios:\n\n- Used to represent decision nodes, conditional judgments, or critical paths.\n\n- Suitable for representing decision nodes or key steps in flowcharts.\n\n- Commonly used in flowcharts, decision trees, network diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Diamond Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Diamond Node","order":"3"},"isInternal":false,"tokens":574,"sizeBytes":2295},{"name":"Diamond.zh.md","path":"packages/site/docs/manual/element/node/Diamond.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Diamond.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 菱形节点 Diamond\norder: 3\n---\n\n## 概述\n\n菱形是一个四边相等的几何形状，具有对角线对称性。\n\n适用场景：\n\n- 用于表示决策节点、条件判断或关键路径。\n\n- 适合表示流程图中的判断节点或关键步骤。\n\n- 常用于流程图、决策树、网络图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置菱形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"菱形节点 Diamond","order":"3"},"isInternal":false,"tokens":486,"sizeBytes":2224},{"name":"Donut.en.md","path":"packages/site/docs/manual/element/node/Donut.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Donut.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Donut Node\norder: 4\n---\n\n## Overview\n\nThe donut node is a ring-shaped geometric figure composed of two concentric circles.\n\nApplicable scenarios:\n\n- Used to represent proportional data, such as completion progress and ratio analysis.\n\n- Suitable for representing multi-layered data, such as nested ring charts.\n\n- Commonly used in data visualization, dashboards, progress charts, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute           | Description                         | Type                                    | Default   | Required |\n| ------------------- | ----------------------------------- | --------------------------------------- | --------- | -------- |\n| donutFill           | Fill color                          | string                                  | `#1783FF` |          |\n| donutFillOpacity    | Fill color opacity                  | number \\| string                        | 1         |          |\n| donutLineCap        | Stroke end style                    | `round` \\| `square` \\| `butt`           | `butt`    |          |\n| donutLineDash       | Stroke dash style                   | number[]                                | -         |          |\n| donutLineDashOffset | Stroke dash offset                  | number                                  | -         |          |\n| donutLineJoin       | Stroke join style                   | `round` \\| `bevel` \\| `miter`           | `miter`   |          |\n| donutLineWidth      | Stroke width                        | number                                  | 1         |          |\n| donutOpacity        | Opacity                             | number \\| string                        | 1         |          |\n| donutPalette        | Color or palette name               | string \\| string[]                      | `tableau` |          |\n| donuts              | Donut data                          | number[] \\| [DonutRound](#donutround)[] | -         |          |\n| donutShadowBlur     | Shadow blur                         | number                                  | -         |          |\n| donutShadowColor    | Shadow color                        | string                                  | -         |          |\n| donutShadowOffsetX  | Shadow offset in x-axis direction   | number \\| string                        | -         |          |\n| donutShadowOffsetY  | Shadow offset in y-axis direction   | number \\| string                        | -         |          |\n| donutShadowType     | Shadow type                         | `inner` \\| `outer`                      | `outer`   |          |\n| donutStroke         | Stroke color                        | string                                  | `#000`    |          |\n| donutStrokeOpacity  | Stroke color opacity                | number \\| string                        | 1         |          |\n| donutVisibility     | Visibility of the shape             | `visible` \\| `hidden`                   | `visible` |          |\n| innerR              | Inner ring radius, percentage or px | string \\| number                        | 50%       |          |\n\n### DonutRound\n\n| Attribute      | Description                       | Type                          | Default   | Required |\n| -------------- | --------------------------------- | ----------------------------- | --------- | -------- |\n| color          | Color                             | string                        | -         |          |\n| fill           | Fill color                        | string                        | `#1783FF` |          |\n| fillOpacity    | Fill color opacity                | number \\| string              | 1         |          |\n| lineCap        | Stroke end style                  | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash       | Stroke dash style                 | number[]                      | -         |          |\n| lineDashOffset | Stroke dash offset                | number                        | -         |          |\n| lineJoin       | Stroke join style                 | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth      | Stroke width                      | number                        | 1         |          |\n| opacity        | Opacity                           | number \\| string              | 1         |          |\n| shadowBlur     | Shadow blur                       | number                        | -         |          |\n| shadowColor    | Shadow color                      | string                        | -         |          |\n| shadowOffsetX  | Shadow offset in x-axis direction | number \\| string              | -         |          |\n| shadowOffsetY  | Shadow offset in y-axis direction | number \\| string              | -         |          |\n| shadowType     | Shadow type                       | `inner` \\| `outer`            | `outer`   |          |\n| stroke         | Stroke color                      | string                        | `#000`    |          |\n| strokeOpacity  | Stroke color opacity              | number \\| string              | 1         |          |\n| value          | Value for ratio calculation       | number                        | -         | ✓        |\n| visibility     | Visibility of the shape           | `visible` \\| `hidden`         | `visible` |          |\n\n## Example\n\n### Built-in Donut Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Donut Node","order":"4"},"isInternal":false,"tokens":2005,"sizeBytes":8059},{"name":"Donut.zh.md","path":"packages/site/docs/manual/element/node/Donut.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Donut.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 甜甜圈节点 Donut\norder: 4\n---\n\n## 概述\n\n甜甜圈节点是一个环形几何形状，由内外两个同心圆组成。\n\n适用场景：\n\n- 用于表示比例数据，如完成进度、占比分析。\n\n- 适合表示多层数据，如嵌套的环形图。\n\n- 常用于数据可视化、仪表盘、进度图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性                | 描述                           | 类型                                        | 默认值    | 必选 |\n| ------------------- | ------------------------------ | ------------------------------------------- | --------- | ---- |\n| donutFill           | 填充色                         | string                                      | `#1783FF` |      |\n| donutFillOpacity    | 填充色透明度                   | number \\| string                            | 1         |      |\n| donutLineCap        | 描边端点样式                   | `round` \\| `square` \\| `butt`               | `butt`    |      |\n| donutLineDash       | 描边虚线样式                   | number[]                                    | -         |      |\n| donutLineDashOffset | 描边虚线偏移量                 | number                                      | -         |      |\n| donutLineJoin       | 描边连接处样式                 | `round` \\| `bevel` \\| `miter`               | `miter`   |      |\n| donutLineWidth      | 描边宽度                       | number                                      | 1         |      |\n| donutOpacity        | 透明度                         | number \\| string                            | 1         |      |\n| donutPalette        | 颜色或者色板名                 | string &#124; string[]                      | `tableau` |      |\n| donuts              | 圆环数据                       | number[] &#124; [DonutRound](#donutround)[] | -         |      |\n| donutShadowBlur     | 阴影模糊度                     | number                                      | -         |      |\n| donutShadowColor    | 阴影颜色                       | string                                      | -         |      |\n| donutShadowOffsetX  | 阴影在 x 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowOffsetY  | 阴影在 y 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowType     | 阴影类型                       | `inner` \\| `outer`                          | `outer`   |      |\n| donutStroke         | 描边色                         | string                                      | `#000`    |      |\n| donutStrokeOpacity  | 描边色透明度                   | number \\| string                            | 1         |      |\n| donutVisibility     | 图形是否可见                   | `visible` \\| `hidden`                       | `visible` |      |\n| innerR              | 内环半径，使用百分比或者像素值 | string &#124; number                        | 50%       |      |\n\n### DonutRound\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| color          | 颜色                      | string                        | -         |      |\n| fill           | 填充色                    | string                        | `#1783FF` |      |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |      |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash       | 描边虚线样式              | number[]                      | -         |      |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |      |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth      | 描边宽度                  | number                        | 1         |      |\n| opacity        | 透明度                    | number \\| string              | 1         |      |\n| shadowBlur     | 阴影模糊度                | number                        | -         |      |\n| shadowColor    | 阴影颜色                  | string                        | -         |      |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |      |\n| stroke         | 描边色                    | string                        | `#000`    |      |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |      |\n| value          | 数值，用于计算比例        | number                        | -         | ✓    |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |      |\n\n## 示例\n\n### 内置甜甜圈节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"甜甜圈节点 Donut","order":"4"},"isInternal":false,"tokens":1765,"sizeBytes":7877},{"name":"Ellipse.en.md","path":"packages/site/docs/manual/element/node/Ellipse.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Ellipse.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Ellipse Node\norder: 5\n---\n\n## Overview\n\nAn ellipse is a geometric shape with asymmetrical major and minor axes.\n\nApplicable scenarios:\n\n- Used to represent dynamic nodes, asymmetric relationships, or special shapes.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Ellipse Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Ellipse Node","order":"5"},"isInternal":false,"tokens":578,"sizeBytes":2311},{"name":"Ellipse.zh.md","path":"packages/site/docs/manual/element/node/Ellipse.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Ellipse.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 椭圆形节点 Ellipse\norder: 5\n---\n\n## 概述\n\n椭圆是一个长轴和短轴不对称的几何形状。\n\n适用场景：\n\n- 用于表示动态节点、非对称关系或特殊形状。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置椭圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"椭圆形节点 Ellipse","order":"5"},"isInternal":false,"tokens":486,"sizeBytes":2215},{"name":"Hexagon.en.md","path":"packages/site/docs/manual/element/node/Hexagon.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Hexagon.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Hexagon Node\norder: 6\n---\n\n## Overview\n\nA hexagon is a geometric shape with six equal sides, featuring a honeycomb structure.\n\nApplicable scenarios:\n\n- Used to represent honeycomb networks, molecular structures, or tightly packed nodes.\n\n- Suitable for representing network topology, molecular diagrams, or game maps.\n\n- Commonly used in network diagrams, topology diagrams, game design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                        | Type   | Default                                 | Required |\n| --------- | ------------------------------------------------------------------ | ------ | --------------------------------------- | -------- |\n| outerR    | Outer radius, the distance from the hexagon's center to any vertex | number | Half of the minimum of width and height |          |\n\n## Example\n\n### Built-in Hexagon Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Hexagon Node","order":"6"},"isInternal":false,"tokens":697,"sizeBytes":2794},{"name":"Hexagon.zh.md","path":"packages/site/docs/manual/element/node/Hexagon.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Hexagon.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 六边形节点 Hexagon\norder: 6\n---\n\n## 概述\n\n六边形是一个六边相等的几何形状，具有蜂窝状结构。\n\n适用场景：\n\n- 用于表示蜂窝网络、分子结构或紧密排列的节点。\n\n- 适合表示网络拓扑、分子图或游戏地图。\n\n- 常用于网络图、拓扑图、游戏设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                     | 类型   | 默认值                   | 必选 |\n| ------ | ---------------------------------------- | ------ | ------------------------ | ---- |\n| outerR | 外半径，是指从六边形中心到任意顶点的距离 | number | 默认为宽高的最小值的一半 |      |\n\n## 示例\n\n### 内置六边形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"六边形节点 Hexagon","order":"6"},"isInternal":false,"tokens":556,"sizeBytes":2605},{"name":"Html.en.md","path":"packages/site/docs/manual/element/node/Html.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Html.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: HTML Node\norder: 7\n---\n\n## Overview\n\nHTML node is a custom rectangular area used to display HTML content. It allows you to embed arbitrary HTML elements within graph nodes, providing great flexibility for creating complex custom nodes.\n\nUse Cases:\n\n- Used to represent complex custom nodes such as tables, charts, or rich text\n- Suitable for representing custom visual elements or interactive components\n- Commonly used in custom charts, UI design, dashboards, and other scenarios\n- When you need to embed interactive elements like forms and buttons in nodes\n\n## Framework Support\n\n> **💡 Tips**：\n>\n> - **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node) for better component-based development experience\n> - **Vue Projects**: Vue Node is not currently supported, community contributions are welcome\n> - **Native HTML**: The HTML node introduced in this document is suitable for native HTML development\n\n## Online Demo\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific properties, we will list them below. For all common style properties, see [BaseNode](/en/manual/element/node/base-node)\n\n| Property  | Description                                                                                           | Type                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------------- | --------------------------- | ------- | -------- |\n| dx        | Horizontal offset. HTML container defaults to top-left corner as origin, use dx for horizontal offset | number                      | 0       |          |\n| dy        | Vertical offset. HTML container defaults to top-left corner as origin, use dy for vertical offset     | number                      | 0       |          |\n| innerHTML | HTML content, can be string or `HTMLElement`                                                          | string &#124; `HTMLElement` | -       | ✓        |\n\n## Examples\n\n### Basic HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### HTML Node with Interactive Buttons\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >Restart</button>\n    <button \n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >Monitor</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle button clicks\nwindow.handleRestart = (nodeId) => {\n  console.log(`Restarting server: ${nodeId}`);\n  alert(`Restarting server ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`Opening monitoring panel: ${nodeId}`);\n  alert(`Opening monitoring panel for server ${nodeId}`);\n};\n\ngraph.render();\n```\n\n### Form Input HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: 'User Information', type: 'user-form' } },\n      { id: 'form-2', data: { title: 'Configuration Panel', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Name</label>\n    <input \n      type=\"text\" \n      placeholder=\"Enter name\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Email</label>\n    <input \n      type=\"email\" \n      placeholder=\"Enter email\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Role</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>Administrator</option>\n      <option>User</option>\n      <option>Guest</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Save</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Cancel</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle form operations\nwindow.handleSave = (nodeId) => {\n  console.log(`Saving form: ${nodeId}`);\n  alert(`Form ${nodeId} saved`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`Canceling form: ${nodeId}`);\n  alert(`Form ${nodeId} operation canceled`);\n};\n\ngraph.render();\n```\n\n## Usage Notes\n\n### 1. Performance Optimization\n\n- HTML nodes have higher rendering costs compared to regular graphic nodes, recommend using when node count is small\n- Complex HTML structures will affect performance, recommend keeping structure simple\n- Avoid using too many animation effects in HTML\n\n### 2. Event Handling\n\n- Event handling in HTML nodes needs to be implemented through global functions or event delegation\n- Recommend mounting event handling functions to the `window` object to ensure accessibility in HTML strings\n- Be careful to prevent event bubbling from affecting graph interaction behavior\n\n### 3. Style Isolation\n\n- HTML node styles may be affected by global page styles\n- Recommend using inline styles or ensuring sufficient style specificity\n- Consider using CSS-in-JS or style namespaces to avoid style conflicts\n\n### 4. Responsive Design\n\n- HTML node dimensions are fixed and do not automatically adapt to content\n- Need to dynamically calculate node dimensions based on content or use responsive layouts\n- Consider display effects at different zoom levels\n\n### 5. Framework Integration Recommendations\n\n- **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node), which allows direct use of React components as node content\n- **Vue Projects**: Vue Node is not currently supported, community contributions are welcome if needed\n- **Native Projects**: HTML nodes are the best choice, providing maximum flexibility\n","frontmatter":{"title":"HTML Node","order":"7"},"isInternal":false,"tokens":3089,"sizeBytes":12362},{"name":"Html.zh.md","path":"packages/site/docs/manual/element/node/Html.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Html.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: HTML节点 Html\norder: 7\n---\n\n## 概述\n\nHTML 节点是一个自定义的矩形区域，用于显示 HTML 内容。它允许您在图形节点中嵌入任意的 HTML 元素，提供了极大的灵活性来创建复杂的自定义节点。\n\n适用场景：\n\n- 用于表示复杂的自定义节点，如表格、图表或富文本\n- 适合表示自定义的可视化元素或交互组件\n- 常用于自定义图表、UI 设计、仪表板等场景\n- 需要在节点中嵌入表单、按钮等交互元素时\n\n## 框架支持说明\n\n> **💡 提示**：\n>\n> - **React 项目**：推荐使用 [React Node](/manual/element/node/react-node) 来实现更好的组件化开发体验\n> - **Vue 项目**：目前暂不支持 Vue Node，欢迎社区共建贡献\n> - **原生 HTML**：本文档介绍的 HTML 节点适用于原生 HTML 开发\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述                                                            | 类型                        | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------- | --------------------------- | ------ | ---- |\n| dx        | 横行偏移量。HTML 容器默认以左上角为原点，通过 dx 来进行横向偏移 | number                      | 0      |      |\n| dy        | 纵向偏移量。HTML 容器默认以左上角为原点，通过 dy 来进行纵向偏移 | number                      | 0      |      |\n| innerHTML | HTML 内容，可以为字符串或者 `HTMLElement`                       | string &#124; `HTMLElement` | -      | ✓    |\n\n## 示例\n\n### 基础HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 带交互按钮的HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%;\n  height: 100%;\n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"display: flex; gap: 8px;\">\n    <button\n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >重启</button>\n    <button\n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >监控</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理按钮点击\nwindow.handleRestart = (nodeId) => {\n  console.log(`重启服务器: ${nodeId}`);\n  alert(`正在重启服务器 ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`打开监控面板: ${nodeId}`);\n  alert(`打开服务器 ${nodeId} 的监控面板`);\n};\n\ngraph.render();\n```\n\n### 表单输入HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: '用户信息', type: 'user-form' } },\n      { id: 'form-2', data: { title: '配置面板', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">姓名</label>\n    <input \n      type=\"text\" \n      placeholder=\"请输入姓名\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">邮箱</label>\n    <input \n      type=\"email\" \n      placeholder=\"请输入邮箱\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">角色</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>管理员</option>\n      <option>用户</option>\n      <option>访客</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >保存</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >取消</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理表单操作\nwindow.handleSave = (nodeId) => {\n  console.log(`保存表单: ${nodeId}`);\n  alert(`表单 ${nodeId} 已保存`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`取消表单: ${nodeId}`);\n  alert(`取消表单 ${nodeId} 操作`);\n};\n\ngraph.render();\n```\n\n## 使用注意事项\n\n### 1. 性能优化\n\n- HTML 节点相比普通图形节点有更高的渲染成本，建议在节点数量较少时使用\n- 复杂的 HTML 结构会影响性能，建议保持结构简洁\n- 避免在 HTML 中使用过多的动画效果\n\n### 2. 事件处理\n\n- HTML 节点中的事件处理需要通过全局函数或事件委托来实现\n- 建议将事件处理函数挂载到 `window` 对象上，确保在 HTML 字符串中可以访问\n- 注意防止事件冒泡影响图的交互行为\n\n### 3. 样式隔离\n\n- HTML 节点的样式可能会受到页面全局样式的影响\n- 建议使用内联样式或确保样式的特异性足够高\n- 考虑使用 CSS-in-JS 或样式命名空间来避免样式冲突\n\n### 4. 响应式设计\n\n- HTML 节点的尺寸是固定的，不会自动适应内容\n- 需要根据内容动态计算节点尺寸，或使用响应式布局\n- 考虑在不同缩放级别下的显示效果\n\n### 5. 框架集成建议\n\n- **React 项目**：推荐使用 [React Node](/manual/element/node/react-node)，可以直接使用 React 组件作为节点内容\n- **Vue 项目**：目前暂不支持 Vue Node，如有需求欢迎社区贡献\n- **原生项目**：HTML 节点是最佳选择，提供了最大的灵活性\n","frontmatter":{"title":"HTML节点 Html","order":"7"},"isInternal":false,"tokens":2564,"sizeBytes":11843},{"name":"Image.en.md","path":"packages/site/docs/manual/element/node/Image.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Image.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Image Node\norder: 8\n---\n\n## Overview\n\nThe image node is a rectangular area used to display images.\n\nApplicable scenarios:\n\n- Used to represent user avatars, product images, or icons.\n\n- Suitable for representing social networks, product catalogs, or icon collections.\n\n- Commonly used in social network graphs, product images, UI design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                          | Type   | Default | Required |\n| --------- | ------------------------------------ | ------ | ------- | -------- |\n| img       | Alias for the img attribute          | string | -       |          |\n| src       | Image source, i.e., image URL string | string | -       | ✓        |\n\n## Example\n\n### Built-in Image Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Image Node","order":"8"},"isInternal":false,"tokens":700,"sizeBytes":2801},{"name":"Image.zh.md","path":"packages/site/docs/manual/element/node/Image.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Image.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 图片节点 Image\norder: 8\n---\n\n## 概述\n\n图片节点是一个矩形区域，用于显示图像。\n\n适用场景：\n\n- 用于表示用户头像、产品图片或图标。\n\n- 适合表示社交网络、产品目录或图标集合。\n\n- 常用于社交网络图、产品图、UI 设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性 | 描述                       | 类型   | 默认值 | 必选 |\n| ---- | -------------------------- | ------ | ------ | ---- |\n| img  | 该属性为 img 的别名        | string | -      |      |\n| src  | 图片来源，即图片地址字符串 | string | -      | ✓    |\n\n## 示例\n\n### 内置图片节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"图片节点 Image","order":"8"},"isInternal":false,"tokens":588,"sizeBytes":2684},{"name":"overview.en.md","path":"packages/site/docs/manual/element/node/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/overview.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Node Overview\norder: 0\n---\n\n## What is a Node\n\nA node is one of the basic elements in a graph, representing an entity or an abstract concept, such as a person, a place, an organization, etc. Nodes can contain attributes like ID, name, type, etc. In G6, nodes can have various shapes and styles, and support rich interactions and customization.\n\nYou can create any number of nodes in a graph and connect them with edges to represent relationships.\n\n## Node System\n\nThe G6 node system includes three main categories: built-in nodes, extended nodes, and custom nodes. **In most cases, built-in nodes are sufficient.**\n\n### Built-in Nodes\n\nG6 provides a variety of built-in node types, **which can be used directly without registration**:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| Node Type      | Registration Name | Description                                     |\n| -------------- | ----------------- | ----------------------------------------------- |\n| Circle Node    | `circle`          | Commonly used for entities                      |\n| Rectangle Node | `rect`            | Suitable for more text and details              |\n| Ellipse Node   | `ellipse`         | A variant of the circle                         |\n| Diamond Node   | `diamond`         | Often used for decision points or special nodes |\n| Triangle Node  | `triangle`        | Can indicate direction or special marks         |\n| Hexagon Node   | `hexagon`         | Suitable for grid layouts and honeycomb charts  |\n| Star Node      | `star`            | Highlights important nodes                      |\n| Donut Node     | `donut`           | Can display proportions or progress             |\n| Image Node     | `image`           | Uses an image as the node body                  |\n| HTML Node      | `html`            | Supports custom HTML content                    |\n\n### 3D Nodes\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` provides 3D nodes:\n\n- `Capsule` - Capsule-shaped node\n- `Cone` - Cone-shaped node\n- `Cube` - Cube-shaped node\n- `Cylinder` - Cylinder-shaped node\n- `Plane` - Plane node\n- `Sphere` - Sphere node\n- `Torus` - Torus node\n\n### React Nodes\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` provides React nodes, supporting the use of React components as the node body. For detailed tutorials, please refer to the [Using React to Define Nodes](/en/manual/element/node/react-node) document.\n\n### Custom Nodes\n\nWhen built-in and extended nodes cannot meet the requirements, G6 offers powerful customization capabilities:\n\n- Extend built-in nodes\n- Create entirely new node types\n\nUnlike built-in nodes, **custom nodes need to be registered before use**. For detailed tutorials, please refer to the [Custom Nodes](/en/manual/element/node/custom-node) document.\n\n## Data Structure\n\nWhen defining nodes, you need to add a `nodes` field to the graph's data object. Each node is an object with the following structure:\n\n| Property | Description                                                                                                                             | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                     | string         | -       | ✓        |\n| type     | Node type, either a built-in node type name or a custom node name                                                                       | string         | -       |          |\n| data     | Node data, used to store custom data such as the node's name, description, etc. Can be accessed via callback functions in style mapping | object         | -       |          |\n| style    | Node style, including visual attributes like position, size, color, etc.                                                                | object         | -       |          |\n| states   | Initial states of the node, such as selected, active, hover, etc.                                                                       | string[]       | -       |          |\n| combo    | The ID of the combo to which the node belongs, used to organize hierarchical relationships. If none, it is null                         | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                         | string[]       | -       |          |\n\nAn example of a data item in the `nodes` array:\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure nodes, listed in order of priority from high to low:\n\n- Use `graph.setNode()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setNode()`\n\nAfter creating the graph instance, you can use `graph.setNode()` to dynamically set the node's style mapping logic.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nWhen instantiating the graph, you can configure node style mapping through `node`, which is a global configuration and will apply to all nodes.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different nodes, you can write the configuration into the node data. This configuration method can be directly written into the data in the following form:\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can do so as follows:\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### Dynamically Updating Nodes\n\nG6 supports dynamically updating the style and state of nodes at runtime:\n\n```typescript\n// Update the style of a single node\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// Set node state\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=Note}\nWhen updating nodes, only the specified attributes will be updated, and unspecified attributes will remain unchanged.\n:::\n\nFor more node-related APIs, please refer to [API - Element Operations](/en/api/element).\n\n## Node States\n\nNodes can have different states, such as selected, highlighted, disabled, etc. You can define the display effect of nodes in different states by configuring state styles:\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // Default style\n      fill: '#C6E5FF',\n    },\n    // State styles\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\nThe state system is the foundation for implementing node interaction effects. For more information on states, please refer to [Element States](/en/manual/element/state).\n","frontmatter":{"title":"Node Overview","order":"0"},"isInternal":false,"tokens":2146,"sizeBytes":8585},{"name":"overview.zh.md","path":"packages/site/docs/manual/element/node/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/overview.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 节点总览\norder: 0\n---\n\n## 什么是节点\n\n节点（Node）是图中的基本元素之一，表示图中的实体或者抽象概念，例如一个人、一个地点、一个组织等，节点可以包含一些属性，例如节点的 ID、名称、类型等。在 G6 中，节点可以具有多种形状和样式，并支持丰富的交互和自定义功能。\n\n你可以在图中创建任意数量的节点，并通过边连接它们以表示关系。\n\n## 节点体系\n\nG6 的节点体系包括三大类：内置节点、扩展节点和自定义节点。**大多数场景下，内置节点即可满足需求**。\n\n### 内置节点\n\nG6 提供了丰富的内置节点类型，**无需注册，直接配置即可使用**：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| 节点类型   | 注册名称   | 描述                     |\n| ---------- | ---------- | ------------------------ |\n| 圆形节点   | `circle`   | 常用于表示普通实体       |\n| 矩形节点   | `rect`     | 适合展示更多文本和细节   |\n| 椭圆节点   | `ellipse`  | 类似圆形的变体           |\n| 菱形节点   | `diamond`  | 常用于决策点或特殊节点   |\n| 三角形节点 | `triangle` | 可用于指示方向或特殊标记 |\n| 六边形节点 | `hexagon`  | 适合网格布局和蜂窝图     |\n| 星形节点   | `star`     | 突出显示重要节点         |\n| 甜甜圈节点 | `donut`    | 可展示比例或进度信息     |\n| 图片节点   | `image`    | 使用图片作为节点主体     |\n| HTML节点   | `html`     | 支持自定义HTML内容       |\n\n### 3D 节点\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` 提供了 3D 节点：\n\n- `Capsule` - 胶囊型节点\n- `Cone` - 圆锥型节点\n- `Cube` - 立方体节点\n- `Cylinder` - 圆柱型节点\n- `Plane` - 平面节点\n- `Sphere` - 球体节点\n- `Torus` - 圆环节点\n\n### React 节点\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` 提供了 React 节点，支持使用 React 组件作为节点的主体，详细教程请查看 [使用 React 定义节点](/manual/element/node/react-node) 文档。\n\n### 自定义节点\n\n当内置节点和扩展节点无法满足需求时，G6提供了强大的自定义能力：\n\n- 继承内置节点进行扩展\n- 创建全新的节点类型\n\n与内置节点不同，**自定义节点需要先注册后使用**。详细教程请参考 [自定义节点](/manual/element/node/custom-node) 文档。\n\n## 数据结构\n\n定义节点时，需要在图的数据对象中添加 `nodes` 字段。每个节点是一个对象，结构如下：\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n`nodes` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## 配置方法\n\n配置节点的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setNode()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setNode()`\n\n可在图实例创建后，使用 `graph.setNode()` 动态设置节点的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `node` 配置节点样式映射，这里的配置是全局的配置，将会在所有节点上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同节点进行不同的配置，可以将配置写入到节点数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### 动态更新节点\n\nG6 支持在运行时动态更新节点的样式和状态：\n\n```typescript\n// 更新单个节点样式\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// 设置节点状态\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=注意}\n更新节点时，只有指定的属性会被更新，未指定的属性保持不变。\n:::\n\n更多与节点相关的 API 请参考 [API - 元素操作](/api/element)。\n\n## 节点状态\n\n节点可以拥有不同的状态，例如选中、高亮、禁用等。可以通过配置状态样式来定义节点在不同状态下的显示效果：\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // 默认样式\n      fill: '#C6E5FF',\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n状态系统是实现节点交互效果的基础，更多状态的介绍，请参考 [元素状态](/manual/element/state)。\n","frontmatter":{"title":"节点总览","order":"0"},"isInternal":false,"tokens":1283,"sizeBytes":7601},{"name":"react-node.en.md","path":"packages/site/docs/manual/element/node/react-node.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/react-node.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Define Nodes with React\norder: 13\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the `@antv/g6-extension-react` ecosystem library, you can directly use React components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Ant Design\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing React design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a React project**: Ensure a React project is installed and created.\n- **React version requirement**: Ensure the React version used is >=16.8.0.\n\n### Install Dependencies\n\nTo use `@antv/g6-extension-react`, run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register React Node Type\n\nRegister the React node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `react-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: ReactNode is the implementation class exported by `@antv/g6-extension-react`\n\n#### 2. Define Business Component\n\nDefine a simple React component as the content of the node:\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. Use the Component\n\nUse the custom React node in the graph configuration. Specify the node type and style in the graph configuration to use the custom React component.\n\n- `type`: Specify the node type as `react-node` (use the name given during registration)\n- `style.component`: Define the React component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // Set border color based on selection state\n        cursor: 'pointer', // Add mouse pointer style\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","frontmatter":{"title":"Define Nodes with React","order":"13"},"isInternal":false,"tokens":3601,"sizeBytes":14600},{"name":"react-node.zh.md","path":"packages/site/docs/manual/element/node/react-node.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/react-node.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 使用 React 定义节点\norder: 13\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 `@antv/g6-extension-react` 一方生态库，可以直接使用 React 组件作为节点内容，提升开发效率与可维护性。\n\n## 自定义节点方案选择\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Ant Design 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 React 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 React 项目**：确保已安装并创建 React 项目。\n- **React 版本要求**：确保使用的 React 版本 >=16.8.0。\n\n### 安装依赖\n\n要使用 `@antv/g6-extension-react`，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 React 节点类型\n\n通过扩展机制注册 React 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`react-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：ReactNode 是 `@antv/g6-extension-react` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 React 组件作为节点的内容：\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 React 节点。通过在图配置中指定节点类型和样式，来使用自定义的 React 组件。\n\n- `type`：指定节点类型为 `react-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 React 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n        cursor: 'pointer', // 添加鼠标指针样式\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n","frontmatter":{"title":"使用 React 定义节点","order":"13"},"isInternal":false,"tokens":3124,"sizeBytes":14121},{"name":"Rect.en.md","path":"packages/site/docs/manual/element/node/Rect.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Rect.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Rect Node\norder: 9\n---\n\n## Overview\n\nA rectangle is a geometric shape with four equal sides and defined boundaries.\n\nApplicable scenarios:\n\n- Used to represent modules, components, or containers.\n\n- Suitable for representing hierarchies, such as organizational charts, file directory trees.\n\n- Commonly used in flowcharts, architecture diagrams, UML diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Rect Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Rect Node","order":"9"},"isInternal":false,"tokens":573,"sizeBytes":2290},{"name":"Rect.zh.md","path":"packages/site/docs/manual/element/node/Rect.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Rect.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 矩形节点 Rect\norder: 9\n---\n\n## 概述\n\n矩形是一个四边相等的几何形状，具有明确的边界。\n\n适用场景：\n\n- 用于表示模块、组件或容器。\n\n- 适合表示层次结构，如组织结构图、文件目录树。\n\n- 常用于流程图、架构图、UML 图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置矩形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"矩形节点 Rect","order":"9"},"isInternal":false,"tokens":483,"sizeBytes":2201},{"name":"Star.en.md","path":"packages/site/docs/manual/element/node/Star.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Star.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Star Node\norder: 10\n---\n\n## Overview\n\nA star is a polygonal geometric shape with prominent points.\n\nApplicable scenarios:\n\n- Used to represent important nodes, special markers, or decorative elements.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                           | Type   | Default                            | Required |\n| --------- | --------------------------------------------------------------------- | ------ | ---------------------------------- | -------- |\n| innerR    | Inner radius, the distance from the star's center to the inner vertex | number | Default is 3/8 of the outer radius |\n\nStructure Description:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## Example\n\n### Built-in Star Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Star Node","order":"10"},"isInternal":false,"tokens":712,"sizeBytes":2846},{"name":"Star.zh.md","path":"packages/site/docs/manual/element/node/Star.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Star.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 五角形节点 Star\norder: 10\n---\n\n## 概述\n\n星形是一个多角几何形状，具有突出的角。\n\n适用场景：\n\n- 用于表示重要节点、特殊标记或装饰性元素。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                 | 类型   | 默认值             | 必选 |\n| ------ | ------------------------------------ | ------ | ------------------ | ---- |\n| innerR | 内半径，是指从星形中心到内顶点的距离 | number | 默认为外半径的 3/8 |\n\n结构说明：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## 示例\n\n### 内置五角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"五角形节点 Star","order":"10"},"isInternal":false,"tokens":570,"sizeBytes":2631},{"name":"Triangle.en.md","path":"packages/site/docs/manual/element/node/Triangle.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Triangle.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Triangle Node\norder: 11\n---\n\n## Overview\n\nA triangle is a geometric shape with three sides, having a clear directionality.\n\nApplicable scenarios:\n\n- Used to represent directional nodes, warnings, or prompts.\n\n- Suitable for indicating direction or hierarchy in flowcharts.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description               | Type                                | Default | Required |\n| --------- | ------------------------- | ----------------------------------- | ------- | -------- |\n| direction | Direction of the triangle | `up` \\| `left` \\| `right` \\| `down` | `up`    |\n\n## Example\n\n### Built-in Triangle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Triangle Node","order":"11"},"isInternal":false,"tokens":661,"sizeBytes":2642},{"name":"Triangle.zh.md","path":"packages/site/docs/manual/element/node/Triangle.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/Triangle.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 三角形节点 Triangle\norder: 11\n---\n\n## 概述\n\n三角形是一个三边几何形状，具有明确的方向性。\n\n适用场景：\n\n- 用于表示方向性节点、警告或提示。\n\n- 适合表示流程图中的方向指示或层级关系。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述         | 类型                                | 默认值 | 必选 |\n| --------- | ------------ | ----------------------------------- | ------ | ---- |\n| direction | 三角形的方向 | `up` \\| `left` \\| `right` \\| `down` | `up`   |\n\n## 示例\n\n### 内置三角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"三角形节点 Triangle","order":"11"},"isInternal":false,"tokens":559,"sizeBytes":2544},{"name":"vue-node.en.md","path":"packages/site/docs/manual/element/node/vue-node.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/vue-node.en.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Define Nodes with Vue\norder: 14\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) ecosystem library, you can directly use Vue components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Element Plus / Ant Design Vue\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing Vue design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a Vue project**: Ensure a Vue project is installed and created.\n- **Vue version requirement**: Ensure the Vue version used is >=2.6.0. (Vue 3 is recommended)\n\n### Install Dependencies\n\nTo use [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue), run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register Vue Node Type\n\nRegister the Vue node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `vue-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: VueNode is the implementation class exported by `g6-extension-vue`\n\n#### 2. Define Business Component\n\nDefine a simple Vue component as the content of the node:\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. Use the Component\n\nUse the custom Vue node in the graph configuration. Specify the node type and style in the graph configuration to use the custom Vue component.\n\n- `type`: Specify the node type as `vue-node` (use the name given during registration)\n- `style.component`: Define the Vue component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // Set border color based on selection state\n          cursor: 'pointer', // Add mouse pointer style\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","frontmatter":{"title":"Define Nodes with Vue","order":"14"},"isInternal":false,"tokens":1912,"sizeBytes":7651},{"name":"vue-node.zh.md","path":"packages/site/docs/manual/element/node/vue-node.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/node/vue-node.zh.md","title":"Node Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 使用 Vue 定义节点\norder: 14\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) 社区生态库，可以直接使用 Vue 组件作为节点内容，提升开发效率与可维护性。\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Element Plus / Ant Design Vue 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 Vue 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 Vue 项目**：确保已安装并创建 Vue 项目。\n- **Vue 版本要求**：确保使用的 Vue 版本 >=2.6.0。(推荐使用 Vue 3)\n\n### 安装依赖\n\n要使用 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue)，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 Vue 节点类型\n\n通过扩展机制注册 Vue 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`vue-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：VueNode 是 `g6-extension-vue` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 Vue 组件作为节点的内容：\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 Vue 节点。通过在图配置中指定节点类型和样式，来使用自定义的 Vue 组件。\n\n- `type`：指定节点类型为 `vue-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 Vue 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n          cursor: 'pointer', // 添加鼠标指针样式\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n","frontmatter":{"title":"使用 Vue 定义节点","order":"14"},"isInternal":false,"tokens":1407,"sizeBytes":7133},{"name":"overview.en.md","path":"packages/site/docs/manual/element/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/overview.en.md","title":"Element Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Element Overview\norder: 1\n---\n\n## Element System\n\nThe core of G6 charts is composed of three basic elements: **Node**, **Edge**, and **Combo**. These elements are the fundamental units for building complex graphical networks.\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### Node\n\n[Nodes](/en/manual/element/node/overview) represent entities or concepts in the graph, such as people, places, objects, etc. G6 provides a rich set of built-in node types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 also supports [defining nodes using React](/en/manual/element/node/react-node) or [custom nodes](/en/manual/element/node/custom-node) to meet specific needs.\n\n### Edge\n\n[Edges](/en/manual/element/edge/overview) represent the connections between nodes, such as friendships, transactions, etc. G6 has multiple built-in edge types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nWhen built-in edges do not meet the requirements, complex connection expressions can be achieved through [custom edges](/en/manual/element/edge/custom-edge).\n\n### Combo\n\n[Combos](/en/manual/element/combo/overview) are special elements that can contain nodes and other combos, used to represent collections, groups, or hierarchical relationships. G6 has two built-in combo types:\n\n- **Circle Combo**(`circle`): Suitable for compact grouping\n- **Rectangle Combo**(`rect`): Suitable for regular layout grouping\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nCombos support nesting, dragging, expanding/collapsing, and other interactions, and more complex container behaviors can be achieved through [custom combos](/en/manual/element/combo/custom-combo).\n\n## Element Composition Principle\n\nEach element is composed of one or more basic shapes. Shapes are the smallest graphical units in G6, including [rectangle](/en/manual/element/shape/properties#rectstyleprops), [circle](/en/manual/element/shape/properties#circlestyleprops), [text](/en/manual/element/shape/properties#textstyleprops), [path](/en/manual/element/shape/properties#pathstyleprops), etc.\n\nFor example:\n\n- A node may consist of a background shape (such as a circle) and a text label\n- An edge may consist of a path, arrow, and text label\n- A combo may consist of a container shape, title text, and expand/collapse button\n\nFor more information about shapes, see [Shape Overview](/en/manual/element/shape/overview) and [Shape Style Properties](/en/manual/element/shape/properties).\n\n## Element State\n\n[Element State](/en/manual/element/state) is a powerful mechanism for displaying visual changes of elements in different interactions or business scenarios. G6 provides a complete state management system:\n\n- **Preset States**: `selected`, `highlight`, `active`, etc.\n- **State Overlay**: Elements can have multiple states simultaneously, with styles overlaying according to priority\n- **Custom States**: Any state can be defined according to business needs\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Configure Elements\n\nG6 5.x adopts a flat configuration structure, where all element configurations are at the same level, making it easy to find and manage:\n\n```typescript\n{\n  node: {\n    // Default node style\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // Node styles in different states\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // Default edge style\n    style: {\n      stroke: '#aaa',\n    },\n    // Edge styles in different states\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // Default combo style\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\nThere are three configuration methods, in order of priority from high to low:\n\n1. **Dynamic configuration using instance methods**: such as `graph.setNode()`, `graph.setEdge()`, `graph.setCombo()`\n2. **Global configuration when instantiating the graph**: specify configuration items in `new Graph()`\n3. **Configuration in data**: set in the data objects of nodes, edges, and combos\n\nIn editors like VSCode, you can see all configurable properties of elements and search based on keywords:\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Extension Capabilities\n\nG6 provides powerful extension capabilities to meet various customization needs:\n\n- **Custom Nodes**: [Custom Node Guide](/en/manual/element/node/custom-node)\n- **Custom Edges**: [Custom Edge Guide](/en/manual/element/edge/custom-edge)\n- **Custom Combos**: [Custom Combo Guide](/en/manual/element/combo/custom-combo)\n- **React Nodes**: [Define Nodes Using React](/en/manual/element/node/react-node)\n- **3D Extension**: Use 3D nodes through `@antv/g6-extension-3d`\n\n## Built-in Element Reference\n\n### Node Types\n\n- [Built-in Node Library](/en/manual/element/node/base-node)\n\n### Edge Types\n\n- [Built-in Edge Library](/en/manual/element/edge/base-edge)\n\n### Combo Types\n\n- [Built-in Combo Library](/en/manual/element/combo/base-combo)\n","frontmatter":{"title":"Element Overview","order":"1"},"isInternal":false,"tokens":1362,"sizeBytes":5447},{"name":"overview.zh.md","path":"packages/site/docs/manual/element/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/overview.zh.md","title":"Element Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 元素总览\norder: 1\n---\n\n## 元素体系\n\nG6 图表的核心是由三种基本元素构成：**节点(Node)**、**边(Edge)** 和 **组合(Combo)**。这些元素是构建复杂图形网络的基础单元。\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 节点 (Node)\n\n[节点](/manual/element/node/overview) 表示图中的实体或概念，如人物、地点、对象等。G6 提供了丰富的内置节点类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 还支持 [使用 React 定义节点](/manual/element/node/react-node) 或 [自定义节点](/manual/element/node/custom-node) 以满足特定需求。\n\n### 边 (Edge)\n\n[边](/manual/element/edge/overview)表示节点间的连接关系，如朋友关系、交易往来等。G6 内置多种边类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n当内置边不满足需求时，可以通过 [自定义边](/manual/element/edge/custom-edge) 来实现复杂的连接表现。\n\n### 组合 (Combo)\n\n[组合](/manual/element/combo/overview)是一种特殊元素，可以包含节点和其他组合，用于表示集合、分组或层级关系。G6 内置两种组合类型：\n\n- **圆形组合**(`circle`)：适合紧凑型分组\n- **矩形组合**(`rect`)：适合规则布局的分组\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n组合支持嵌套、拖拽、展开/收起等交互，可以通过 [自定义组合](/manual/element/combo/custom-combo) 来实现更复杂的容器行为。\n\n## 元素构成原理\n\n每个元素由一个或多个基础图形(Shape)组成。图形是 G6 中的最小图形单元，包括 [矩形](/manual/element/shape/properties#rectstyleprops)、[圆形](/manual/element/shape/properties#circlestyleprops)、[文本](/manual/element/shape/properties#textstyleprops)、[路径](/manual/element/shape/properties#pathstyleprops)等。\n\n例如：\n\n- 一个节点可能由背景图形(如圆形)和文本标签组成\n- 一条边可能由路径、箭头和文本标签组成\n- 一个组合可能由容器图形、标题文本和展开/收起按钮组成\n\n要了解更多关于图形的信息，请参阅 [图形 Shape 总览](/manual/element/shape/overview) 和 [Shape 样式属性](/manual/element/shape/properties)。\n\n## 元素状态\n\n[元素状态](/manual/element/state) 是一种强大的机制，用于展示元素在不同交互或业务场景下的视觉变化。G6 提供了一套完整的状态管理系统：\n\n- **预设状态**：`selected`(选中)、`highlight`(高亮)、`active`(激活)等\n- **状态叠加**：元素可同时拥有多个状态，样式按优先级叠加\n- **自定义状态**：可根据业务需求定义任意状态\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 配置元素\n\nG6 5.x 采用扁平化的配置结构，所有元素的配置都在同一层级，便于查找和管理：\n\n```typescript\n{\n  node: {\n    // 节点默认样式\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // 节点在不同状态下的样式\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // 边默认样式\n    style: {\n      stroke: '#aaa',\n    },\n    // 边在不同状态下的样式\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // 组合默认样式\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\n配置方式有三种，按优先级从高到低：\n\n1. **使用实例方法动态配置**：如 `graph.setNode()`、`graph.setEdge()`、`graph.setCombo()`\n2. **实例化图时全局配置**：在 `new Graph()` 时指定配置项\n3. **在数据中配置**：在节点、边、组合的数据对象中设置\n\n在 VSCode 等编辑器中，你可以看到元素的全部可配置属性，并基于关键字进行搜索：\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 扩展能力\n\nG6 提供了强大的扩展能力，满足各种自定义需求：\n\n- **自定义节点**：[自定义节点指南](/manual/element/node/custom-node)\n- **自定义边**：[自定义边指南](/manual/element/edge/custom-edge)\n- **自定义组合**：[自定义组合指南](/manual/element/combo/custom-combo)\n- **React 节点**：[使用 React 定义节点](/manual/element/node/react-node)\n- **3D 扩展**：通过 `@antv/g6-extension-3d` 使用 3D 节点\n\n## 内置元素参考\n\n### 节点类型\n\n- [内置节点库](/manual/element/node/base-node)\n\n### 边类型\n\n- [内置边库](/manual/element/edge/base-edge)\n\n### 组合类型\n\n- [内置组合库](/manual/element/combo/base-combo)\n","frontmatter":{"title":"元素总览","order":"1"},"isInternal":false,"tokens":843,"sizeBytes":5041},{"name":"label-shape.en.md","path":"packages/site/docs/manual/element/shape/label-shape.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/label-shape.en.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Design and Implementation of Composite Shape\norder: 3\n---\n\nG6 provides a flexible Shape mechanism, allowing developers to customize various graphics and efficiently reuse them in elements such as nodes, edges, and combos. This article uses Label as an example to explain how to customize a Shape and how to apply it in elements.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 1. Customization and Encapsulation of Shape\n\n### 1. Base Class Design of Shape\n\nAll Shapes inherit from `BaseShape`, which centrally manages the lifecycle (creation, update, destruction), property parsing, animation, event binding, etc. You only need to focus on implementing the `render` method.\n\n**Core Abstraction:**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // Lifecycle management, property parsing, animation, etc...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. Hierarchical Structure of Composite Shape\n\nA node usually contains multiple child Shapes, for example:\n\n```\nNode\n├── keyShape (main shape)\n├── label (label, auxiliary information)\n│   ├── text\n│   └── rect\n├── icon\n│   ├── text\n│   └── image\n├── badge\n│   ├── text\n│   └── rect\n└── port\n│   ├── circle\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Implementation of Label Shape\n\nLabel is a typical composite Shape, consisting of text (Text) and an optional background (Rect). The implementation idea is as follows:\n\n- **Property Separation**: The style properties of Label are divided into text style and background style, which are passed to Text and Rect respectively.\n- **Smart Layout**: The background automatically adjusts its size and position based on the text content, padding, border radius, etc.\n- **Reuse upsert**: The `upsert` method is used to automatically manage the creation, update, and destruction of child Shapes.\n\n**Main code snippet of Label:**\n\n```js\nimport { Text, Rect } from '@antv/g'; // Import atomic graphics\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... Omitted style extraction methods\n}\n```\n\n- `getTextStyle` and `getBackgroundStyle` extract the style properties for text and background respectively to avoid interference.\n- The `upsert` method ensures automatic CRUD of Shapes, greatly improving reusability and robustness.\n\n### 4. Complete Custom Shape Example\n\nBelow is an example of customizing a label with special decoration, demonstrating the complete definition, registration, and usage of a Shape:\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // Main text\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // Background\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // Extra decoration: small dot on the left\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...implement getTextStyle/getBackgroundStyle\n}\n\n// Register custom Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// Define custom node\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// Register custom node\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 2. Prefix Separation of Style Properties\n\nIn G6, elements such as nodes, edges, and combos often contain multiple child Shapes (such as main shape, label, badge, port, etc.). To ensure that the style of each child Shape does not interfere with each other, G6 adopts a **prefix separation** design for style properties.\n\n### 1. Significance of Prefix Separation\n\n- **Decoupling**: Each child Shape only cares about its own style properties, avoiding style pollution.\n- **Easy Expansion**: Adding a new child Shape only requires defining a new prefix, without modifying the original logic.\n- **Intuitive Configuration**: When configuring nodes/edges/combos, users can clearly set the style of each part.\n\n### 2. Code Implementation\n\nTake Label as an example:\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` means all properties starting with `background` belong to the label background style.\n- During rendering, tools such as `subStyleProps` and `subObject` are used to automatically extract prefixed styles and pass them to the corresponding Shape.\n\n**Label background style extraction example**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...Omitted layout calculation\n  return backgroundStyle;\n}\n```\n\n**Style configuration example**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 3. Relationship between Label and keyShape\n\n- **keyShape** is the main shape of a node/edge/combo, determining interaction picking, bounding box, main style, etc.\n- **Label**, icon, badge, port, etc. usually exist as auxiliary Shapes and are not used as keyShape.\n- When customizing a node, you can specify the keyShape via `drawKeyShape` or similar methods. Label is only responsible for displaying text information and does not affect the main interaction control of the node.\n\n## 4. How to Apply Custom Shape in Elements\n\nTake nodes as an example. The node base class `BaseNode` has built-in support for multiple child Shapes (keyShape, label, icon, badge, port, halo, etc.). You only need to focus on drawing the keyShape, and other child Shapes can be automatically managed through configuration and style prefixing.\n\n### 1. Node Rendering Process\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. Draw keyShape (main shape)\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. Draw halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. Draw icon\n  this.drawIconShape(attributes, container);\n\n  // 4. Draw badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. Draw label\n  this.drawLabelShape(attributes, container);\n\n  // 6. Draw ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- The style of each child Shape is automatically extracted by prefix separation and passed to the corresponding Shape instance.\n- You can flexibly control the display and style of each child Shape through configuration options.\n\n### 2. Example of Applying Label\n\nSuppose you want to add a label with a background to a node, just configure the label-related properties in the node data:\n\n```js\n{\n  label: true,\n  labelText: 'I am a label',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`, `labelFill`, `labelFontSize`, etc. will be automatically extracted and passed to the text part of the Label.\n- `labelBackground`, `labelBackgroundFill`, `labelBackgroundRadius`, `labelPadding`, etc. will be automatically extracted and passed to the background part of the Label.\n\nYou do not need to manually manage the creation, update, or destruction of the Label. G6 will handle it automatically.\n\n## 5. Common Issues and Debugging Suggestions\n\n### 1. Why is the label style not effective?\n\n- Check whether the style property prefix is correct (such as `labelFill`, `labelBackgroundFill`).\n- Make sure the `label` configuration of the node/edge/combo is `true` and `labelText` is set.\n- Check if it is overridden by other styles.\n\n### 2. How to debug the rendering of custom Shape?\n\n- Use the browser console to view `shapeMap` and confirm whether each child Shape is created correctly.\n\n### 3. How to make Label respond to node states (such as hover, selected)?\n\n- Directly set node state styles in the graph configuration (recommended)\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- Or listen for state changes in the implementation of Label and dynamically adjust the style. You can get the current state value through data.\n\n---\n\nFor more details, it is recommended to read the source code [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts), [`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts).\n","frontmatter":{"title":"Design and Implementation of Composite Shape","order":"3"},"isInternal":false,"tokens":2517,"sizeBytes":10154},{"name":"label-shape.zh.md","path":"packages/site/docs/manual/element/shape/label-shape.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/label-shape.zh.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 复合 Shape 的设计与实现\norder: 3\n---\n\nG6 提供了灵活的 Shape 机制，支持开发者自定义各种图形，并在节点、边、Combo 等元素中高效复用。本文将以 Label（标签）为例，讲解如何自定义 Shape、如何在元素中应用。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 一、Shape 的自定义与封装\n\n### 1. Shape 的基类设计\n\n所有 Shape 都继承自 `BaseShape`，它统一管理了 Shape 的生命周期（创建、更新、销毁）、属性解析、动画、事件绑定等。你只需关注如何实现 `render` 方法即可。\n\n**核心抽象：**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // 生命周期管理、属性解析、动画等...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. 复合 Shape 层级结构示意\n\n一个节点通常包含多个子 Shape，例如：\n\n```\n节点（Node）\n├── keyShape（主图形）\n├── label（标签，辅助信息）\n│   ├── text（文本）\n│   └── rect（背景）\n├── icon（图标）\n│   ├── text（文本）\n│   └── image（图片）\n├── badge（徽标）\n│   ├── text（文本）\n│   └── rect（背景）\n└── port（锚点）\n│   ├── circle（圆形）\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Label Shape 的实现\n\nLabel 是一个典型的复合 Shape，由文本（Text）和可选的背景（Rect）组成。其实现思路如下：\n\n- **属性分离**：Label 的样式属性分为文本样式和背景样式，分别传递给 Text 和 Rect。\n- **智能布局**：背景自动根据文本内容、内边距、圆角等动态调整尺寸和位置。\n- **复用 upsert**：通过 `upsert` 方法自动管理子 Shape 的创建、更新、销毁。\n\n**Label 主要代码片段：**\n\n```js\nimport { Text, Rect } from '@antv/g'; // 引入原子图形\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... 省略样式提取方法\n}\n```\n\n- `getTextStyle`、`getBackgroundStyle` 分别提取文本和背景的样式属性，避免相互干扰。\n- `upsert` 方法保证了 Shape 的自动增删改查，极大提升了复用性和健壮性。\n\n### 4. 完整自定义 Shape 示例\n\n下面以自定义一个带特殊装饰的标签为例，演示 Shape 的完整定义、注册与使用：\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // 主文本\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // 背景\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // 额外装饰：左侧小圆点\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...实现 getTextStyle/getBackgroundStyle\n}\n\n// 注册自定义 Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// 定义自定义节点\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// 注册自定义节点\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 二、样式属性的前缀分离\n\nG6 中节点、边、Combo 等元素往往包含多个子 Shape（如主图形、标签、徽标、锚点等）。为了让每个子 Shape 的样式互不干扰，G6 采用了**样式属性前缀分离**的设计。\n\n### 1. 前缀分离的意义\n\n- **解耦**：每个子 Shape 只关心属于自己的样式属性，避免样式污染。\n- **易扩展**：新增子 Shape 只需定义新的前缀，无需修改原有逻辑。\n- **配置直观**：用户在配置节点/边/Combo 时，可以一目了然地设置各部分样式。\n\n### 2. 代码实现\n\n以 Label 为例：\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` 表示所有以 `background` 开头的属性都属于标签背景样式。\n- 在实际渲染时，通过 `subStyleProps`、`subObject` 等工具函数，自动提取带前缀的样式，传递给对应的 Shape。\n\n**Label 背景样式提取示例**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...省略布局计算\n  return backgroundStyle;\n}\n```\n\n**样式配置示例**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 三、Label 与 keyShape 的关系\n\n- **keyShape** 是节点/边/Combo 的主图形，决定交互拾取、包围盒、主样式等。\n- **Label**、icon、badge、port 等通常作为辅助 Shape 存在，不会作为 keyShape。\n- 你可以在自定义节点时通过 `drawKeyShape` 或类似方法指定 keyShape，Label 只负责展示文本信息，不影响节点的交互主控。\n\n## 四、如何在元素中应用自定义 Shape\n\n以节点为例，节点基类 `BaseNode` 已经内置了对多种子 Shape 的支持（keyShape、label、icon、badge、port、halo 等）。你只需专注于 keyShape 的绘制，其他子 Shape 可以通过配置和样式前缀自动管理。\n\n### 1. 节点渲染流程\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. 绘制 keyShape（主图形）\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. 绘制 halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. 绘制 icon\n  this.drawIconShape(attributes, container);\n\n  // 4. 绘制 badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. 绘制 label\n  this.drawLabelShape(attributes, container);\n\n  // 6. 绘制 ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- 每个子 Shape 的样式都通过前缀分离自动提取，传递给对应的 Shape 实例。\n- 你可以通过配置项灵活控制每个子 Shape 的显示与样式。\n\n### 2. 应用 Label 的示例\n\n假设你要为节点添加带背景的标签，只需在节点数据中配置 label 相关属性：\n\n```js\n{\n  label: true,\n  labelText: '我是标签',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`、`labelFill`、`labelFontSize` 等会被自动提取并传递给 Label 的文本部分。\n- `labelBackground`、`labelBackgroundFill`、`labelBackgroundRadius`、`labelPadding` 等会被自动提取并传递给 Label 的背景部分。\n\n你无需手动管理 Label 的创建、更新、销毁，G6 会自动完成。\n\n## 五、常见问题与调试建议\n\n### 1. 为什么 label 样式没有生效？\n\n- 检查样式属性前缀是否正确（如 `labelFill`、`labelBackgroundFill`）。\n- 确认节点/边/Combo 的 `label` 配置为 `true`，且 `labelText` 已设置。\n- 检查是否被其他样式覆盖。\n\n### 2. 如何调试自定义 Shape 的渲染？\n\n- 使用浏览器控制台查看 `shapeMap`，确认各子 Shape 是否被正确创建。\n\n### 3. 如何让 Label 响应节点状态（如 hover、selected）？\n\n- 直接在图配置中设置节点状态样式（推荐）\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- 或者在 Label 的实现中监听状态变化，动态调整样式。可以通过 data 获取到当前的状态值\n\n---\n\n如需更深入了解，建议阅读源码 [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts)、[`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts)。\n","frontmatter":{"title":"复合 Shape 的设计与实现","order":"3"},"isInternal":false,"tokens":1680,"sizeBytes":9354},{"name":"overview.en.md","path":"packages/site/docs/manual/element/shape/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/overview.en.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Shape and KeyShape\norder: 1\n---\n\n## Shape\n\nA Shape in G6 refers to a graphical element, such as a circle, rectangle, or path. Shapes are generally associated with nodes, edges, or combos in G6. **💡 Every node/edge/combo in G6 is composed of one or more shapes. The style configuration of nodes, edges, and combos is reflected on their corresponding shapes.**\n\nFor example, in the images below: the node on the left contains a single circular shape; the node in the middle contains a circle and a text shape; the node on the right contains five circles (the blue-green main circle and four anchor points at the top, bottom, left, and right) and a text shape. Each node/edge/combo has its unique key shape (keyShape). In the examples below, the keyShape for all three nodes is the blue-green circle. The keyShape is mainly used for interaction detection and automatic style updates with [element states](/en/manual/element/state), see [keyShape](#keyshape).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> (Left) A node with only one circular shape, whose keyShape is the circle. (Middle) A node with a circle and a text shape, whose keyShape is the circle. (Right) A node with a main circle, text, and four small circles at the top, bottom, left, and right, whose keyShape is the main circle.\n\nG6 uses different combinations of shapes to design various built-in nodes/edges/combos. Built-in nodes include 'circle', 'rect', 'ellipse', ... (see [Built-in Nodes](/en/manual/element/node/base-node)); built-in edges include 'line', 'polyline', 'cubic', ... (see [Built-in Edges](/en/manual/element/edge/base-edge)); built-in combos include 'circle', 'rect', ... (see [Built-in Combos](/en/manual/element/combo/base-combo)).\n\nIn addition to using built-in nodes/edges/combos, G6 also allows users to customize nodes/edges/combos by combining shapes as needed. See [Custom Node](/en/manual/element/node/custom-node), [Custom Edge](/en/manual/element/edge/custom-edge), and [Custom Combo](/en/manual/element/combo/custom-combo) for details.\n\n## KeyShape\n\nIn G6, each node, edge, or combo consists of one or more shapes, but one of them is called the keyShape, which is the \"key graphical element\" of the item:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> The key graphical element of the node is the colored area in the image above.\n\n### Bounding Box Determination\n\n**Determines the bounding box of a node/combo**, which is used to calculate the connection point of related edges (the intersection with the edge). If the keyShape is different, the intersection calculation between the node and the edge will also differ.\n\n#### Example\n\nIn this example, a node consists of a rect shape and a circle shape with a gray stroke and transparent fill.\n\n- When the node's keyShape is the circle:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- When the node's keyShape is the rect:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape Lifecycle\n\n> If you need to [customize nodes](/en/manual/element/node/custom-node), [customize edges](/en/manual/element/edge/custom-edge), or [customize combos](/en/manual/element/combo/custom-combo), you need to understand the lifecycle of shapes. If you use built-in nodes/edges/combos, you can skip this section.\n\nThe shape lifecycle includes:\n\n- **Initial Rendering**: Draws the shape for the first time based on data and style configuration.\n- **Update**: Automatically updates the appearance of the shape when data or style changes.\n- **Operation**: Responds to interaction states (such as selected, active, hover, etc.) and dynamically adjusts the style.\n- **Destruction**: Cleans up when the shape is removed (usually managed automatically by the Graph, so users don't need to worry).\n\nWhen customizing shapes, the most common requirement is \"how to efficiently manage the creation, update, and destruction of shapes.\" For this, G6 provides a very useful method in BaseShape:\n\n### Principle and Advantages of upsert\n\nupsert is a combination of \"update\" and \"insert\", meaning \"update if exists, insert if not\". Its function can be simply understood as:\n\n- **Automatic Judgment**: You only need to describe the desired appearance of the shape. `upsert` will automatically determine whether the shape already exists. If not, it will create it; if it exists, it will update it; if it needs to be deleted, it will remove it automatically.\n- **Simplified Logic**: Developers do not need to manually manage the CRUD of shapes, avoiding duplicate code and state confusion.\n- **Improved Robustness**: Whether it's the initial rendering, data changes, or state switching, upsert ensures that the shape always stays in sync with the data and configuration.\n\n**Type Definition:**\n\n```js\n/**\n * Create, update, or delete a shape\n * @param className Shape name\n * @param Ctor Shape type\n * @param style Shape style. Pass false to delete the shape\n * @param container Container\n * @param hooks Hooks\n * @returns Shape instance\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\nYou only need to describe \"what kind of shape you want now\" without worrying about whether it is being created, updated, or deleted. upsert will handle it for you. This makes customizing and managing complex composite shapes very simple and safe.\n","frontmatter":{"title":"Shape and KeyShape","order":"1"},"isInternal":false,"tokens":1489,"sizeBytes":5957},{"name":"overview.zh.md","path":"packages/site/docs/manual/element/shape/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/overview.zh.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 图形 Shape 与 KeyShape\norder: 1\n---\n\n## 图形 Shape\n\nShape 指 G6 中的图形、形状，可以是圆形、矩形、路径等。它一般与 G6 中的节点、边、Combo 相关。**💡 G6 中的每一种节点/边/Combo 都是由一个或多个 Shape 组合而成。节点、边、Combo 的样式配置都会被体现到对应的图形上。**\n\n例如下图（左）的节点包含了一个圆形图形；下图（中）的节点含有一个圆形和一个文本图形；下图（右）的节点中含有 5 个圆形（蓝绿色的圆和上下左右四个锚点）、一个文本图形。但每种节点/边/Combo 都会有自己的唯一关键图形 keyShape，下图中三个节点的 keyShape 都是蓝绿色的圆，keyShape 主要用于交互检测、样式随 [元素状态](/manual/element/state) 自动更新等，见 [keyShape](#keyshape)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> （左）只含有一个圆形图形的节点，keyShape 是该圆形。（中）含有圆形和文本图形的节点，keyShape 是圆形。（右）含有主要圆形、文本、上下左右四个小圆形的节点，keyShape 是圆形。\n\nG6 使用不同的 shape 组合，设计了多种内置的节点/边/ Combo 。G6 内置节点的有 'circle'， 'rect'，'ellipse'，...（详见 [内置节点](/manual/element/node/base-node)）；内置边的有 'line'，'polyline'，'cubic'，...（详见 [内置边](/manual/element/edge/base-edge)）；内置 Combo 有 'circle'，'rect'，（详见 [内置 Combo](/manual/element/combo/base-combo)）。\n\n除了使用内置的节点/边/ Combo 外，G6 还允许用户通过自己搭配和组合 shape 进行节点/边/ Combo 的自定义，详见 [自定义节点](/manual/element/node/custom-node)，[自定义边](/manual/element/edge/custom-edge)，[自定义 Combo](/manual/element/combo/custom-combo)。\n\n## KeyShape\n\n在 G6 中，每个节点、边、Combo 都由一个或多个 Shape 组成，但其中有一个 Shape 被称为 keyShape，它是该元素的“关键图形”：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> 节点的关键图形就是上图的颜色区域\n\n### 包围盒确定\n\n**确定节点 / Combo 的包围盒（Bounding Box）** ，从而计算相关边的连入点（与相关边的交点）。若 keyShape 不同，节点与边的交点计算结果不同。\n\n#### 示例  \n\n本例中的一个节点由一个 rect 图形和一个带灰色描边、填充透明的 circle 图形构成。\n\n- 当节点的 keyShape 为 circle 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- 当节点的 keyShape 为 rect 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape 的生命周期\n\n> 当用户需要 [自定义节点](/manual/element/node/custom-node)、[自定义边](/manual/element/edge/custom-edge)、[自定义 Combo](/manual/element/combo/custom-combo) 时，需要了解 Shape 的生命周期。使用内置节点/边/Combo 则可以跳过这一部分内容。\n\n从整体来看，Shape 的生命周期分为：\n\n- **初始化渲染**：首次根据数据和样式配置绘制出 Shape。\n- **更新**：当数据或样式发生变化时，自动更新 Shape 的表现。\n- **操作**：响应交互状态（如 selected、active、hover 等），动态调整样式。\n- **销毁**：Shape 被移除时的清理（通常由 Graph 自动管理，用户无需关心）。\n\n在自定义 Shape 时，最常见的需求就是“如何高效地管理 Shape 的创建、更新和销毁”。G6 为此在 BaseShape 中设计了一个非常实用的方法：\n\n### upsert 的原理与优势\n\nupsert 是“update” 和 “insert” 的合成词，意思是“有则更新，无则创建”。它的作用可以简单理解为：\n\n- **自动判断**：你只需描述希望 Shape 呈现的样子，`upsert` 会自动判断当前 Shape 是否已存在。如果不存在则创建，如果已存在则更新，如果需要删除则自动移除。\n- **简化逻辑**：开发者无需手动管理 Shape 的增删改查，避免了重复代码和状态混乱。\n- **提升健壮性**：无论是初次渲染、数据变更还是状态切换，upsert 都能保证 Shape 始终与数据和配置保持同步。\n\n**类型定义：**\n\n```js\n/**\n * 创建、更新或删除图形\n * @param className 图形名称\n * @param Ctor 图形类型\n * @param style 图形样式。若要删除图形，传入 false\n * @param container 容器\n * @param hooks 钩子函数\n * @returns 图形实例\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\n你只需要描述“我现在想要什么样的图形”，不用关心它是新建、更新还是删除，upsert 都会帮你处理好。这让自定义和管理复杂的复合 Shape 变得非常简单和安全。\n","frontmatter":{"title":"图形 Shape 与 KeyShape","order":"1"},"isInternal":false,"tokens":819,"sizeBytes":5446},{"name":"properties.en.md","path":"packages/site/docs/manual/element/shape/properties.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/properties.en.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Atomic Shapes and Their Properties\norder: 2\n---\n\nElements (nodes/edges) in G6 are composed of **one or more [shapes](/en/manual/element/shape/overview)**, mainly added via `upsert` in the `render` method when customizing nodes or edges. G6 supports the following shapes:\n\n1. [Circle](#circlestyleprops)\n2. [Ellipse](#ellipsestyleprops)\n3. [Rect](#rectstyleprops)\n4. [HTML Element](#htmlstyleprops)\n5. [Image](#imagestyleprops)\n6. [Line](#linestyleprops)\n7. [Path](#pathstyleprops)\n8. [Polygon](#polygonstyleprops)\n9. [Polyline](#polylinestyleprops)\n10. [Text](#textstyleprops)\n\n## Common Properties of All Shapes\n\n### BaseShapeStyle\n\n| Property       | Description                                                                                      | Type                                     | Required |\n| -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------- | -------- |\n| x              | x coordinate                                                                                     | number                                   | ✓        |\n| y              | y coordinate                                                                                     | number                                   | ✓        |\n| width          | Width                                                                                            | number                                   | ✓        |\n| height         | Height                                                                                           | number                                   | ✓        |\n| fill           | Fill color                                                                                       | string \\| Pattern \\| null                |          |\n| stroke         | Stroke color                                                                                     | string \\| Pattern \\| null                |          |\n| opacity        | Overall opacity                                                                                  | number \\| string                         |          |\n| fillOpacity    | Fill opacity                                                                                     | number \\| string                         |          |\n| strokeOpacity  | Stroke opacity                                                                                   | number \\| string                         |          |\n| lineWidth      | Line width                                                                                       | number \\| string                         |          |\n| lineCap        | Line cap style                                                                                   | `butt` \\| `round` \\| `square`            |          |\n| lineJoin       | Line join style                                                                                  | `miter` \\| `round` \\| `bevel`            |          |\n| lineDash       | Dash array                                                                                       | number \\| string \\| (string \\| number)[] |          |\n| lineDashOffset | Dash offset                                                                                      | number                                   |          |\n| shadowBlur     | Shadow blur                                                                                      | number                                   |          |\n| shadowColor    | Shadow color                                                                                     | string                                   |          |\n| shadowOffsetX  | Shadow X offset                                                                                  | number                                   |          |\n| shadowOffsetY  | Shadow Y offset                                                                                  | number                                   |          |\n| cursor         | Mouse cursor, supports all [CSS cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) | string                                   |          |\n| zIndex         | Render z-index                                                                                   | number                                   |          |\n| visibility     | Visibility                                                                                       | `visible` \\| `hidden`                    |          |\n\n**Example:**\n\n```js\nconst shape = BaseShape.upsert(\n  // Specify the shape key, which must be unique within the same custom element type\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Common Methods of All Shapes\n\n### attr()\n\nSet or get the drawing attributes of the instance.\n\n### attr(name)\n\nGet the value of an attribute.\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\nUpdate a single drawing attribute.\n\n### attr({...})\n\nBatch update drawing attributes.\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## Circle Shape\n\n### CircleStyleProps\n\n| Property          | Description                               | Type             | Required |\n| ----------------- | ----------------------------------------- | ---------------- | -------- |\n| cx                | Center x coordinate                       | number \\| string | ✓        |\n| cy                | Center y coordinate                       | number \\| string | ✓        |\n| cz                | Center z coordinate                       | number \\| string |          |\n| r                 | Radius                                    | number \\| string | ✓        |\n| isBillboard       | Billboard mode (always faces camera)      | boolean          |          |\n| isSizeAttenuation | Size attenuation (size changes with view) | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Rect Shape\n\n### RectStyleProps\n\n| Property          | Description       | Type                         | Required |\n| ----------------- | ----------------- | ---------------------------- | -------- |\n| x                 | Rect x coordinate | number \\| string             |          |\n| y                 | Rect y coordinate | number \\| string             |          |\n| z                 | Rect z coordinate | number                       |          |\n| width             | Rect width        | number \\| string             | ✓        |\n| height            | Rect height       | number \\| string             | ✓        |\n| isBillboard       | Billboard mode    | boolean                      |          |\n| isSizeAttenuation | Size attenuation  | boolean                      |          |\n| radius            | Border radius     | number \\| string \\| number[] |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Ellipse Shape\n\n### EllipseStyleProps\n\n| Property          | Description         | Type             | Required |\n| ----------------- | ------------------- | ---------------- | -------- |\n| cx                | Center x coordinate | number \\| string | ✓        |\n| cy                | Center y coordinate | number \\| string | ✓        |\n| cz                | Center z coordinate | number \\| string |          |\n| rx                | X-axis radius       | number \\| string | ✓        |\n| ry                | Y-axis radius       | number \\| string | ✓        |\n| isBillboard       | Billboard mode      | boolean          |          |\n| isSizeAttenuation | Size attenuation    | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| Property  | Description       | Type                  | Required |\n| --------- | ----------------- | --------------------- | -------- |\n| x         | HTML x coordinate | number \\| string      |          |\n| y         | HTML y coordinate | number \\| string      |          |\n| innerHTML | HTML content      | string \\| HTMLElement | ✓        |\n| width     | HTML width        | number \\| string      |          |\n| height    | HTML height       | number \\| string      |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## Image Shape\n\n### ImageStyleProps\n\n| Property          | Description                      | Type                       | Required |\n| ----------------- | -------------------------------- | -------------------------- | -------- |\n| x                 | Image x coordinate               | number \\| string           |          |\n| y                 | Image y coordinate               | number \\| string           |          |\n| z                 | Image z coordinate               | number                     |          |\n| src               | Image source or HTMLImageElement | string \\| HTMLImageElement | ✓        |\n| width             | Image width                      | number \\| string           |          |\n| height            | Image height                     | number \\| string           |          |\n| isBillboard       | Billboard mode                   | boolean                    |          |\n| isSizeAttenuation | Size attenuation                 | boolean                    |          |\n| billboardRotation | Billboard rotation angle         | number                     |          |\n| keepAspectRatio   | Keep original aspect ratio       | boolean                    |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## Line Shape\n\n### LineStyleProps\n\n| Property          | Description         | Type                  | Required |\n| ----------------- | ------------------- | --------------------- | -------- |\n| x1                | Start x coordinate  | number                | ✓        |\n| y1                | Start y coordinate  | number                | ✓        |\n| x2                | End x coordinate    | number                | ✓        |\n| y2                | End y coordinate    | number                | ✓        |\n| z1                | Start z coordinate  | number                |          |\n| z2                | End z coordinate    | number                |          |\n| isBillboard       | Billboard mode      | boolean               |          |\n| isSizeAttenuation | Size attenuation    | boolean               |          |\n| markerStart       | Marker at start     | DisplayObject \\| null |          |\n| markerEnd         | Marker at end       | DisplayObject \\| null |          |\n| markerStartOffset | Start marker offset | number                |          |\n| markerEndOffset   | End marker offset   | number                |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Path Shape\n\n### PathStyleProps\n\n| Property          | Description          | Type                   | Required |\n| ----------------- | -------------------- | ---------------------- | -------- |\n| d                 | Path string or array | string \\| PathArray    | ✓        |\n| markerStart       | Marker at start      | DisplayObject \\| null  |          |\n| markerEnd         | Marker at end        | DisplayObject \\| null  |          |\n| markerMid         | Marker at middle     | DisplayObject \\| null  |          |\n| markerStartOffset | Start marker offset  | number                 |          |\n| markerEndOffset   | End marker offset    | number                 |          |\n| isBillboard       | Billboard mode       | boolean                |          |\n| isSizeAttenuation | Size attenuation     | boolean                |          |\n| fillRule          | Fill rule            | `nonzero` \\| `evenodd` |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Polygon Shape\n\n### PolygonStyleProps\n\n| Property          | Description             | Type                                             | Required |\n| ----------------- | ----------------------- | ------------------------------------------------ | -------- |\n| points            | Array of polygon points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start         | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end           | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle        | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset     | number                                           |          |\n| markerEndOffset   | End marker offset       | number                                           |          |\n| isClosed          | Is polygon closed       | boolean                                          |          |\n| isBillboard       | Billboard mode          | boolean                                          |          |\n| isSizeAttenuation | Size attenuation        | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Polyline Shape\n\n### PolylineStyleProps\n\n| Property          | Description              | Type                                             | Required |\n| ----------------- | ------------------------ | ------------------------------------------------ | -------- |\n| points            | Array of polyline points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start          | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end            | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle         | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset      | number                                           |          |\n| markerEndOffset   | End marker offset        | number                                           |          |\n| isBillboard       | Billboard mode           | boolean                                          |          |\n| isSizeAttenuation | Size attenuation         | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Text\n\n### TextStyleProps\n\n| Property            | Description              | Type                                                                        | Required |\n| ------------------- | ------------------------ | --------------------------------------------------------------------------- | -------- |\n| x                   | Text x coordinate        | number \\| string                                                            |          |\n| y                   | Text y coordinate        | number \\| string                                                            |          |\n| z                   | Text z coordinate        | number \\| string                                                            |          |\n| text                | Text content             | number \\| string                                                            | ✓        |\n| fontSize            | Font size                | number \\| string                                                            |          |\n| fontFamily          | Font family              | string                                                                      |          |\n| fontStyle           | Font style               | `normal` \\| `italic` \\| `oblique`                                           |          |\n| fontWeight          | Font weight              | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |          |\n| fontVariant         | Font variant             | `normal` \\| `small-caps` \\| string                                          |          |\n| textAlign           | Text horizontal align    | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |          |\n| textBaseline        | Text baseline            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |          |\n| textOverflow        | Text overflow            | `clip` \\| `ellipsis` \\| string                                              |          |\n| lineHeight          | Line height              | number \\| string                                                            |          |\n| letterSpacing       | Letter spacing           | number \\| string                                                            |          |\n| maxLines            | Max lines                | number                                                                      |          |\n| textPath            | Text path                | Path                                                                        |          |\n| textPathSide        | Text path side           | `left` \\| `right`                                                           |          |\n| textPathStartOffset | Text path start offset   | number \\| string                                                            |          |\n| textDecorationLine  | Text decoration line     | string                                                                      |          |\n| textDecorationColor | Text decoration color    | string                                                                      |          |\n| textDecorationStyle | Text decoration style    | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |          |\n| isBillboard         | Billboard mode           | boolean                                                                     |          |\n| billboardRotation   | Billboard rotation angle | number                                                                      |          |\n| isSizeAttenuation   | Size attenuation         | boolean                                                                     |          |\n| wordWrap            | Word wrap                | boolean                                                                     |          |\n| wordWrapWidth       | Word wrap width          | number                                                                      |          |\n| dx                  | X offset                 | number \\| string                                                            |          |\n| dy                  | Y offset                 | number \\| string                                                            |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n**Display in multiply line:**\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","frontmatter":{"title":"Atomic Shapes and Their Properties","order":"2"},"isInternal":false,"tokens":4937,"sizeBytes":19794},{"name":"properties.zh.md","path":"packages/site/docs/manual/element/shape/properties.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/shape/properties.zh.md","title":"Shape Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 原子 Shape 以及其属性\norder: 2\n---\n\nG6 中的元素（节点/边）是由**一个或多个 [图形 Shape](/manual/element/shape/overview)** 组成，主要通过自定义节点或自定义边时在 `render` 方法中使用 `upsert` 添加，G6 中支持以下的图形 Shape：\n\n1. [Circle - 圆形](#circlestyleprops)\n2. [Ellipse - 椭圆](#ellipsestyleprops)\n3. [Rect - 矩形](#rectstyleprops)\n4. [HTML - HTML元素](#htmlstyleprops)\n5. [Image - 图片](#imagestyleprops)\n6. [Line - 线](#linestyleprops)\n7. [Path - 路径](#pathstyleprops)\n8. [Polygon - 多边形](#polygonstyleprops)\n9. [Polyline - 折线](#polylinestyleprops)\n10. [Text - 文本](#textstyleprops)\n\n## 各图形 Shape 的通用属性\n\n### BaseShapeStyle\n\n| 属性           | 描述                                                                                          | 类型                                     | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------- | ---- |\n| x              | x 坐标                                                                                        | number                                   | ✓    |\n| y              | y 坐标                                                                                        | number                                   | ✓    |\n| width          | 宽度                                                                                          | number                                   | ✓    |\n| height         | 高度                                                                                          | number                                   | ✓    |\n| fill           | 填充颜色                                                                                      | string \\| Pattern \\| null                |      |\n| stroke         | 描边颜色                                                                                      | string \\| Pattern \\| null                |      |\n| opacity        | 整体透明度                                                                                    | number \\| string                         |      |\n| fillOpacity    | 填充透明度                                                                                    | number \\| string                         |      |\n| strokeOpacity  | 描边透明度                                                                                    | number \\| string                         |      |\n| lineWidth      | 线宽度                                                                                        | number \\| string                         |      |\n| lineCap        | 线段端点样式                                                                                  | `butt` \\| `round` \\| `square`            |      |\n| lineJoin       | 线段连接处样式                                                                                | `miter` \\| `round` \\| `bevel`            |      |\n| lineDash       | 虚线配置                                                                                      | number \\| string \\| (string \\| number)[] |      |\n| lineDashOffset | 虚线偏移量                                                                                    | number                                   |      |\n| shadowBlur     | 阴影模糊程度                                                                                  | number                                   |      |\n| shadowColor    | 阴影颜色                                                                                      | string                                   |      |\n| shadowOffsetX  | 阴影 X 方向偏移                                                                               | number                                   |      |\n| shadowOffsetY  | 阴影 Y 方向偏移                                                                               | number                                   |      |\n| cursor         | 鼠标样式，[CSS 的 cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) 选项都支持 | string                                   |      |\n| zIndex         | 渲染层级                                                                                      | number                                   |      |\n| visibility     | 可见性                                                                                        | `visible` \\| `hidden`                    |      |\n\n**示例：**\n\n```js\nconst shape = BaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 各图形 Shape 的通用方法\n\n### attr()\n\n设置或获取实例的绘图属性。\n\n### attr(name)\n\n获取实例的属性值。\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\n更新实例的单个绘图属性。\n\n### attr({...})\n\n批量更新实例绘图属性。\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## 圆图形 Circle\n\n### CircleStyleProps\n\n| 属性              | 描述                               | 类型             | 必选 |\n| ----------------- | ---------------------------------- | ---------------- | ---- |\n| cx                | 圆心 x 坐标                        | number \\| string | ✓    |\n| cy                | 圆心 y 坐标                        | number \\| string | ✓    |\n| cz                | 圆心 z 坐标                        | number \\| string |      |\n| r                 | 圆的半径                           | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式（始终面向相机） | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减（随视距变化大小） | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 矩形图形 Rect\n\n### RectStyleProps\n\n| 属性              | 描述               | 类型                         | 必选 |\n| ----------------- | ------------------ | ---------------------------- | ---- |\n| x                 | 矩形 x 坐标        | number \\| string             |      |\n| y                 | 矩形 y 坐标        | number \\| string             |      |\n| z                 | 矩形 z 坐标        | number                       |      |\n| width             | 矩形宽度           | number \\| string             | ✓    |\n| height            | 矩形高度           | number \\| string             | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean                      |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                      |      |\n| radius            | 矩形圆角半径       | number \\| string \\| number[] |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 椭圆图形 Ellipse\n\n### EllipseStyleProps\n\n| 属性              | 描述               | 类型             | 必选 |\n| ----------------- | ------------------ | ---------------- | ---- |\n| cx                | 椭圆中心 x 坐标    | number \\| string | ✓    |\n| cy                | 椭圆中心 y 坐标    | number \\| string | ✓    |\n| cz                | 椭圆中心 z 坐标    | number \\| string |      |\n| rx                | 椭圆 x 轴半径      | number \\| string | ✓    |\n| ry                | 椭圆 y 轴半径      | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| 属性      | 描述             | 类型                  | 必选 |\n| --------- | ---------------- | --------------------- | ---- |\n| x         | HTML 元素 x 坐标 | number \\| string      |      |\n| y         | HTML 元素 y 坐标 | number \\| string      |      |\n| innerHTML | HTML 内容        | string \\| HTMLElement | ✓    |\n| width     | HTML 元素宽度    | number \\| string      |      |\n| height    | HTML 元素高度    | number \\| string      |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## 图片图形 Image\n\n### ImageStyleProps\n\n| 属性              | 描述                         | 类型                       | 必选 |\n| ----------------- | ---------------------------- | -------------------------- | ---- |\n| x                 | 图片 x 坐标                  | number \\| string           |      |\n| y                 | 图片 y 坐标                  | number \\| string           |      |\n| z                 | 图片 z 坐标                  | number                     |      |\n| src               | 图片资源路径或 HTML 图片元素 | string \\| HTMLImageElement | ✓    |\n| width             | 图片宽度                     | number \\| string           |      |\n| height            | 图片高度                     | number \\| string           |      |\n| isBillboard       | 是否启用公告牌模式           | boolean                    |      |\n| isSizeAttenuation | 是否启用大小衰减             | boolean                    |      |\n| billboardRotation | 公告牌模式下的旋转角度       | number                     |      |\n| keepAspectRatio   | 是否保持图片原有宽高比       | boolean                    |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## 直线 Line\n\n### LineStyleProps\n\n| 属性              | 描述               | 类型                  | 必选 |\n| ----------------- | ------------------ | --------------------- | ---- |\n| x1                | 线段起点 x 坐标    | number                | ✓    |\n| y1                | 线段起点 y 坐标    | number                | ✓    |\n| x2                | 线段终点 x 坐标    | number                | ✓    |\n| y2                | 线段终点 y 坐标    | number                | ✓    |\n| z1                | 线段起点 z 坐标    | number                |      |\n| z2                | 线段终点 z 坐标    | number                |      |\n| isBillboard       | 是否启用公告牌模式 | boolean               |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean               |      |\n| markerStart       | 线段起点的标记     | DisplayObject \\| null |      |\n| markerEnd         | 线段终点的标记     | DisplayObject \\| null |      |\n| markerStartOffset | 起点标记的偏移量   | number                |      |\n| markerEndOffset   | 终点标记的偏移量   | number                |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 路径 Path\n\n### PathStyleProps\n\n| 属性              | 描述                 | 类型                   | 必选 |\n| ----------------- | -------------------- | ---------------------- | ---- |\n| d                 | 路径定义字符串或数组 | string \\| PathArray    | ✓    |\n| markerStart       | 路径起点的标记       | DisplayObject \\| null  |      |\n| markerEnd         | 路径终点的标记       | DisplayObject \\| null  |      |\n| markerMid         | 路径中间点的标记     | DisplayObject \\| null  |      |\n| markerStartOffset | 起点标记的偏移量     | number                 |      |\n| markerEndOffset   | 终点标记的偏移量     | number                 |      |\n| isBillboard       | 是否启用公告牌模式   | boolean                |      |\n| isSizeAttenuation | 是否启用大小衰减     | boolean                |      |\n| fillRule          | 填充规则             | `nonzero` \\| `evenodd` |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 多边形图形 Polygon\n\n### PolygonStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 多边形的顶点数组   | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 多边形起点的标记   | DisplayObject \\| null                            |      |\n| markerEnd         | 多边形终点的标记   | DisplayObject \\| null                            |      |\n| markerMid         | 多边形中间点的标记 | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isClosed          | 是否闭合多边形     | boolean                                          |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 折线 Polyline\n\n### PolylineStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 折线的顶点数组     | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 折线起点的标记     | DisplayObject \\| null                            |      |\n| markerEnd         | 折线终点的标记     | DisplayObject \\| null                            |      |\n| markerMid         | 折线中间点的标记   | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 文字 Text\n\n### TextStyleProps\n\n| 属性                | 描述               | 类型                                                                        | 必选 |\n| ------------------- | ------------------ | --------------------------------------------------------------------------- | ---- |\n| x                   | 文本 x 坐标        | number \\| string                                                            |      |\n| y                   | 文本 y 坐标        | number \\| string                                                            |      |\n| z                   | 文本 z 坐标        | number \\| string                                                            |      |\n| text                | 文本内容           | number \\| string                                                            | ✓    |\n| fontSize            | 字体大小           | number \\| string                                                            |      |\n| fontFamily          | 字体族             | string                                                                      |      |\n| fontStyle           | 字体样式           | `normal` \\| `italic` \\| `oblique`                                           |      |\n| fontWeight          | 字体粗细           | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |      |\n| fontVariant         | 字体变种           | `normal` \\| `small-caps` \\| string                                          |      |\n| textAlign           | 文本水平对齐方式   | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |      |\n| textBaseline        | 文本基线           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |      |\n| textOverflow        | 文本溢出处理方式   | `clip` \\| `ellipsis` \\| string                                              |      |\n| lineHeight          | 行高               | number \\| string                                                            |      |\n| letterSpacing       | 字间距             | number \\| string                                                            |      |\n| maxLines            | 最大行数           | number                                                                      |      |\n| textPath            | 文本路径           | Path                                                                        |      |\n| textPathSide        | 文本路径侧边       | `left` \\| `right`                                                           |      |\n| textPathStartOffset | 文本路径起始偏移   | number \\| string                                                            |      |\n| textDecorationLine  | 文本装饰线         | string                                                                      |      |\n| textDecorationColor | 文本装饰线颜色     | string                                                                      |      |\n| textDecorationStyle | 文本装饰线样式     | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |      |\n| isBillboard         | 是否启用公告牌模式 | boolean                                                                     |      |\n| billboardRotation   | 公告牌旋转角度     | number                                                                      |      |\n| isSizeAttenuation   | 是否启用大小衰减   | boolean                                                                     |      |\n| wordWrap            | 是否自动换行       | boolean                                                                     |      |\n| wordWrapWidth       | 自动换行宽度       | number                                                                      |      |\n| dx                  | X 方向偏移         | number \\| string                                                            |      |\n| dy                  | Y 方向偏移         | number \\| string                                                            |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n多行文字显示：\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n","frontmatter":{"title":"原子 Shape 以及其属性","order":"2"},"isInternal":false,"tokens":4468,"sizeBytes":20591},{"name":"state.en.md","path":"packages/site/docs/manual/element/state.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/state.en.md","title":"Element Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Element State\norder: 2\n---\n\n## What is Element State\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\nElement State refers to the visual representation of elements (nodes, edges, combos) in a graph under different interaction scenarios. For example, when a user clicks on a node, the node might enter a \"selected\" state and change color; when the mouse hovers over an edge, the edge might enter a \"highlight\" state and become bold.\n\n**Simply put, states allow elements to dynamically change their appearance based on user operations or business logic.**\n\n### Characteristics of States\n\n- **Multiple State Coexistence**: An element can have multiple states simultaneously, such as being both \"selected\" and \"highlighted\"\n- **Style Stacking**: Styles from multiple states are stacked together, with later-set state styles having higher priority\n- **Complete Customization**: Besides built-in states, you can create any custom states that meet your business requirements\n\n## Built-in State Types\n\nG6 provides some commonly used built-in states that you can use directly:\n\n| State Name  | Description     | Typical Use Cases                    |\n| ----------- | --------------- | ------------------------------------ |\n| `selected`  | Selected state  | When user clicks to select elements  |\n| `active`    | Active state    | Currently interacting element        |\n| `highlight` | Highlight state | Elements that need emphasis          |\n| `inactive`  | Inactive state  | Dimmed display of unfocused elements |\n| `disabled`   | Disabled state  | Non-interactive elements             |\n\n> 💡 **Tip**: These built-in states are not mandatory. You can completely define your own state names according to business requirements.\n\n## Configuring State Styles\n\n### Basic Configuration\n\nConfigure corresponding styles for different states when creating a graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Node state style configuration\n  node: {\n    // Default style (style when no state is applied)\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // Styles for various states\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // Edge state style configuration\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // Combo state style configuration\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### Custom States\n\nYou can create any custom states that meet your business requirements:\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // Custom state: error\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // Dashed border\n      },\n      // Custom state: success\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // Custom state: warning\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // Add icon\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## Setting Element States\n\n### Setting Initial States in Data\n\nSet initial states for elements in data:\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // Initially in selected state\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // Initially in disabled state\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // Initially has multiple states\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // Initial state of the edge\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### Dynamic State Setting\n\nDynamically change element states through API:\n\n```javascript\n// Set a single state for a single element\ngraph.setElementState('node1', 'selected');\n\n// Set multiple states for a single element\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// Batch set states for multiple elements\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### State Stacking Effect\n\nWhen an element has multiple states, styles are stacked in order:\n\n```javascript\n// Assume a node has both selected and highlight states\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// Final style = default style + selected state style + highlight state style\n// If there are style conflicts, later state styles will override earlier ones\n```\n\n## Clearing Element States\n\n### Clear All States\n\nRestore elements to default state (no states):\n\n```javascript\n// Clear all states of a single element\ngraph.setElementState('node1', []);\n\n// Batch clear states of multiple elements\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### Clear Specific States\n\nIf an element has multiple states, you can clear only some of them:\n\n```javascript\n// Assume node1 currently has ['selected', 'highlight', 'active'] three states\n// Now only want to keep 'selected' state, clear other states\ngraph.setElementState('node1', ['selected']);\n\n// Or get current states, then filter out unwanted states\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### Clear Specific States from All Elements\n\n```javascript\n// Clear 'highlight' state from all nodes\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## Querying Element States\n\n### Get Element States\n\n```javascript\n// Get all states of a specified element\nconst states = graph.getElementState('node1');\nconsole.log(states); // For example: ['selected', 'highlight']\n\n// If element has no states, returns empty array\nconsole.log(states); // []\n```\n\n### Find Elements with Specific States\n\n```javascript\n// Get all node data in 'selected' state\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// Get all edge data in 'highlight' state\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### Check if Element is in Specific State\n\n```javascript\n// Check if element is in specific state\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('Is node selected:', isSelected);\nconsole.log('Is node highlighted:', isHighlight);\n```\n","frontmatter":{"title":"Element State","order":"2"},"isInternal":false,"tokens":1865,"sizeBytes":7466},{"name":"state.zh.md","path":"packages/site/docs/manual/element/state.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/element/state.zh.md","title":"Element Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 元素状态\norder: 2\n---\n\n## 什么是元素状态\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n元素状态(State)是指图中元素（节点、边、组合）在不同交互场景下的视觉表现形式。比如当用户点击一个节点时，节点可能会变成\"选中\"状态并改变颜色；当鼠标悬停在边上时，边可能会进入\"高亮\"状态并加粗显示。\n\n**简单来说，状态让元素能够根据用户的操作或业务逻辑动态改变外观。**\n\n### 状态的特点\n\n- **多状态共存**：一个元素可以同时拥有多个状态，比如既是\"选中\"又是\"高亮\"\n- **样式叠加**：多个状态的样式会叠加在一起，后设置的状态样式优先级更高\n- **完全自定义**：除了内置状态，您可以创建任何符合业务需求的自定义状态\n\n## 内置状态类型\n\nG6 提供了一些常用的内置状态，您可以直接使用：\n\n| 状态名      | 说明       | 典型使用场景       |\n| ----------- | ---------- | ------------------ |\n| `selected`  | 选中状态   | 用户点击选择元素时 |\n| `active`    | 激活状态   | 当前正在交互的元素 |\n| `highlight` | 高亮状态   | 需要强调显示的元素 |\n| `inactive`  | 非活跃状态 | 淡化显示非关注元素 |\n| `disabled`   | 禁用状态   | 不可交互的元素     |\n\n> 💡 **提示**：这些内置状态并非必须使用，您完全可以根据业务需求定义自己的状态名称。\n\n## 配置状态样式\n\n### 基础配置\n\n在创建图实例时，为不同状态配置相应的样式：\n\n```javascript\nconst graph = new Graph({\n  // 节点的状态样式配置\n  node: {\n    // 默认样式（无状态时的样式）\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // 各种状态下的样式\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // 边的状态样式配置\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // 组合的状态样式配置\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### 自定义状态\n\n您可以创建任何符合业务需求的自定义状态：\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // 自定义状态：错误\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // 虚线边框\n      },\n      // 自定义状态：成功\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // 自定义状态：警告\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // 添加图标\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## 设置元素状态\n\n### 数据中设置初始状态\n\n在数据中为元素设置初始状态：\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // 初始为选中状态\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // 初始为禁用状态\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // 初始有多个状态\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // 边的初始状态\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### 动态设置状态\n\n通过 API 动态改变元素状态：\n\n```javascript\n// 设置单个元素的单个状态\ngraph.setElementState('node1', 'selected');\n\n// 设置单个元素的多个状态\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// 批量设置多个元素的状态\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### 状态的叠加效果\n\n当元素有多个状态时，样式会按顺序叠加：\n\n```javascript\n// 假设节点同时有 selected 和 highlight 状态\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// 最终样式 = 默认样式 + selected状态样式 + highlight状态样式\n// 如果有样式冲突，后面的状态样式会覆盖前面的\n```\n\n## 清除元素状态\n\n### 清除所有状态\n\n将元素恢复到默认状态（无任何状态）：\n\n```javascript\n// 清除单个元素的所有状态\ngraph.setElementState('node1', []);\n\n// 批量清除多个元素的状态\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### 清除特定状态\n\n如果元素有多个状态，您可以只清除其中的某些状态：\n\n```javascript\n// 假设 node1 当前有 ['selected', 'highlight', 'active'] 三个状态\n// 现在只想保留 'selected' 状态，清除其他状态\ngraph.setElementState('node1', ['selected']);\n\n// 或者获取当前状态，然后过滤掉不需要的状态\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### 清除所有元素的特定状态\n\n```javascript\n// 清除所有节点的 'highlight' 状态\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## 查询元素状态\n\n### 获取元素状态\n\n```javascript\n// 获取指定元素的所有状态\nconst states = graph.getElementState('node1');\nconsole.log(states); // 例如：['selected', 'highlight']\n\n// 如果元素没有任何状态，返回空数组\nconsole.log(states); // []\n```\n\n### 查找特定状态的元素\n\n```javascript\n// 获取所有处于 'selected' 状态的节点数据\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// 获取所有处于 'highlight' 状态的边数据\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### 判断元素是否处于某状态\n\n```javascript\n// 检查元素是否处于特定状态\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('节点是否选中:', isSelected);\nconsole.log('节点是否高亮:', isHighlight);\n```\n","frontmatter":{"title":"元素状态","order":"2"},"isInternal":false,"tokens":1295,"sizeBytes":7072},{"name":"3d.en.md","path":"packages/site/docs/manual/extension/3d.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/extension/3d.en.md","title":"Extension Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: g6-extension-3d\n---\n","frontmatter":{"title":"g6-extension-3d"},"isInternal":false,"tokens":8,"sizeBytes":31},{"name":"3d.zh.md","path":"packages/site/docs/manual/extension/3d.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/extension/3d.zh.md","title":"Extension Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: g6-extension-3d\n---\n","frontmatter":{"title":"g6-extension-3d"},"isInternal":false,"tokens":8,"sizeBytes":31},{"name":"faq.en.md","path":"packages/site/docs/manual/faq.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/faq.en.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: FAQ\norder: 13\n---\n\n### What is the Difference Between Extension and Plugin?\n\n`Extension` is a concept in G6 that collectively refers to all types of registrable content, including elements, behaviors, layouts, and plugins, among others.\n\n`Plugin` represents a flexible extension mechanism provided by G6 and is a special type of `Extension`.\n\n### Set Text Overflow Ellipsis\n\nTaking `label` as an example, you can set `labelWordWrap` and `labelWordWrapWidth` to achieve text overflow ellipsis.\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### Key Press Not Working\n\nSome plugins or behaviors support configuring key press triggers. Please use standard key names, such as `Control`, `Shift`, `Alt`, `Meta`, as well as letters, numbers, symbols, and so on.\n\n### Canvas Not Updating After Data Update\n\nEnsure that you call `graph.draw()` or `graph.render()` to update the canvas after updating the data.\n\n> G6 merges differences and updates the canvas uniformly after `draw` or `render` for multiple data updates to improve performance.\n\n### How to Resolve Interaction Conflicts\n\nWhen multiple interactions conflict with each other, you can set the enable timing of interactions to avoid multiple interactions being triggered simultaneously.\n\nTaking `drag-canvas` and `brush-select` as an example, if you directly configure these two interactions, dragging on the canvas will cause interaction exceptions. You can disable the `drag-canvas` interaction when the `shift` key is pressed.\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\nAt this point, when the `shift` key is pressed, the `drag-canvas` interaction will be disabled, and the `brush-select` interaction will not be affected.\n\n### Difference Between `draw` and `render`\n\nBoth `draw` and `render` execute drawing operations, but `render` additionally performs **layout** and **auto fit** operations based on `draw`.\n\nYou can simply understand it as: `render` = `draw` + `layout` + `fitView`/`fitCenter`.\n\n### Style in Data Not Effective\n\nReason 1: The style in the data is overridden by the style in the style mapping.\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // No matter what the style in the data is, it will be overridden by the style here\n    }\n  }\n}\n```\n\nSolution: Use a callback method to prioritize obtaining styles from the data to improve data priority.\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### Residual content in the canvas\n\nWhen using the Canvas renderer for drawing, residual content may appear in the canvas, which is referred to as \"dirty rectangles\". This phenomenon occurs because the underlying rendering engine improves performance by only drawing the parts that have changed each time, rather than clearing the entire canvas.\n\nHowever, when the graphics in the canvas change, there may be cases where some graphics are not correctly cleared, resulting in residual content.\n\nYou can solve this issue by:\n\n1. Using the SVG or WebGL renderer;\n2. Checking whether there are illegal values in the element of the nodes, such as null, NaN, and so on;\n3. Using integers as much as possible for numeric style values, such as r, width, height, fontSize, and so on.\n\n### Use Vanilla JavaScript Object Data\n\nPlease avoid using Vue reactive data, Immer.js, and other wrapped objects as the data source for G6, as these objects will be deeply monitored internally, and even freeze the data object, causing G6 to fail to operate normally.\n\n### G6 project startup Warning during compilation Type mapping points to non-existent path\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> Explanation: [@antv/util](https://github.com/antvis/util) is a tool library that AntV relies on at the bottom.\n\nFrom the partial warning message above, we can see that there is a problem with the type declaration file of the `@antv/util` tool library that G6 depends on.**This warning does not affect the normal operation of the project**.\n\nThis message will only appear in TypeScript projects. The following are ways to turn it off:\n\n1. Turn off TypeScript sourcemap\n\nCreate a `.env` file in the root directory of the project and add the following content:\n\ntext\nGENERATE_SOURCEMAP=false\ntext\n\n2. Disable sourcemapping for specific modules\n\nDisabling sourcemapping directly is too simple and crude, and is not user-friendly for developers who may have debugging needs. Therefore, sourcemapping can be disabled for specific modules by configuring the build tool separately.\n\na. webpack configuration\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite configuration\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // Ignore warnings for specific modules\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // For other warnings, use the default warning handling\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### Manually configuring the color palette does not take effect\n\n> In v5, the built-in colors are: export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\nThe solution is as follows:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line plugin does not take effect\n\n> In v5, built-in plugins include `bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [Detailed reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\nActual reason: The parent container of the `graph` instance, `<div ref={containerRef} />`, does not have a height set, so the G6 Graph may not be able to calculate the correct size.**If you want to enable the `grid-line` canvas plugin, you need to set the width and height of the parent element, which is not valid in the graph configuration**.\n\n### v5 cannot use the tree layout\n\nUse `new Graph({xxx})` uniformly.\n\n> In v5, built-in layouts include `antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [Specific reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5 merges the graph and tree graph, no longer creates the tree graph layout by instantiating `G6.TreeGraph`, and removes this method. For details, see [Features - Merge Graph and Tree Graph](https://g6.antv.antgroup.com/manual/feature#-%E5%90%88%E5%B9%B6%E5%9B%BE%E4%B8%8E%E6%A0%91%E5%9B%BE)\n\n### edge does not have a connection at the center of the node\n\nis configured [portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter) to `true`.\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### How to dynamically set the width of a node based on the length of the label content\n\nImplementation solution: [#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent node event object type is not complete\n\nYou can manually specify the `IPointerEvent` type. For details, see [#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### Remove the parent combo of the node\n\nUpdate the node data, set the `combo` value to `null`.\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","frontmatter":{"title":"FAQ","order":"13"},"isInternal":false,"tokens":2644,"sizeBytes":10581},{"name":"faq.zh.md","path":"packages/site/docs/manual/faq.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/faq.zh.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 常见问题\norder: 13\n---\n\n### Extension 和 Plugin 有什么区别？\n\n`Extension` 是 G6 中的一个概念，是所有可注册内容的统称，包含元素、交互、布局、插件等。\n\n`Plugin` 是 G6 提供的灵活扩展机制，是一种特殊的 `Extension`。\n\n### 设置文本超出省略\n\n以 label 为例，设置 `labelWordWrap` 和 `labelWordWrapWidth` 即可实现文本超出省略。\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### 按键不生效\n\n一些插件或交互支持配置触发按键，请使用标准按键名：如 `Control`, `Shift`, `Alt`, `Meta`，以及字母、数字、符号等。\n\n### 更新数据后画布不更新\n\n请确保数据更新后调用 `graph.draw()` 或者 `graph.render()` 更新画布。\n\n> G6 对于多次数据更新，会在 `draw` 或 `render` 后合并差异并统一更新画布，以提高性能。\n\n### 交互有冲突如何解决\n\n当多个交互之间存在冲突时，你可以设置交互的启用时机来避免多个交互被同时触发。\n\n以 `drag-canvas` 和 `brush-select` 为例，如果直接配置这两个交互，当指针在画布上进行拖拽时，会导致交互异常。可以设置为在按下 `shift` 键时禁用 `drag-canvas` 交互。\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\n此时，当按下 `shift` 键时，`drag-canvas` 交互会被禁用，`brush-select` 交互会不会受到影响。\n\n### draw 和 render 的区别\n\n`draw` 和 `render` 都会执行绘制操作，但 `render` 会在 `draw` 的基础上额外进行**布局**、**视图自适应**操作。\n\n可以简单理解为：`render` = `draw` + `layout` + `fitView`/`fitCenter`。\n\n### 数据中的样式不生效\n\n原因一：被样式映射中的样式覆盖\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // 无论数据中的样式如何，都会被这里的样式覆盖\n    }\n  }\n}\n```\n\n解决方式：使用回调方法，优先从数据中获取样式以提高数据优先级\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### 画布中出现残影\n\n在使用 Canvas 渲染器进行绘制时，可能会出现残影现象，这些图形被称为“脏矩形”。该现象出现的原因是底层渲染引擎为了提高性能，每次绘制时只会绘制发生变化的部分，而不会清空整个画布。\n\n但是，当画布中的图形发生变化时，可能会出现部分图形未被正确清除的情况，从而导致残影现象。\n\n可以通过以下方式解决：\n\n1. 使用 SVG 或 WebGL 渲染器；\n2. 检查节点中的图形样式中是否存在非法值，例如 null、NaN 等；\n3. 尽量使用整数作为数值型的样式值，例如 r、width、height、fontSize 等；\n\n### 使用原生 JavaScript 对象数据\n\n请避免使用 Vue 响应式数据、Immer.js 等包装过的对象作为 G6 的数据源，因为这些对象会在内部进行深度监听，甚至冻结数据对象，导致 G6 无法正常操作数据。\n\n### G6 项目启动在编译时警告类型映射指向不存在路径\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> 解释: [@antv/util](https://github.com/antvis/util) 是 AntV 底层依赖的工具库。\n\n从上面部分警告信息中我们可以得知是 G6 依赖的 `@antv/util` 工具库的类型声明文件存在问题，**该警告不影响项目正常运行**。\n\n该信息只会在 TypeScript 项目中出现，关闭办法如下:\n\n1. 关闭TypeScript 的sourcemap源码映射\n\n在项目根目录下创建`.env`文件，并添加以下内容:\n\n```text\nGENERATE_SOURCEMAP=false\n```\n\n2. 单独禁用指定模块的源码映射\n\n直接禁用sourcemap映射的方式过于简单粗暴，对于部分可能有调试需求的开发者不太友好，所以也可以通过在构建工具单独配置，单独禁用这些特定模块的源码映射。\n\na. webpack配置\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite配置\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // 忽略特定模块的警告\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // 对于其他警告,使用默认的警告处理\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### 手动配置色板颜色不生效\n\n> 在 v5 中内置颜色有：export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\n解决办法如下:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line 插件不生效\n\n> 在 v5 中内置插件有`bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\n实际原因: `graph`实例的父容器`<div ref={containerRef} />`本身没有设置高度，G6 Graph图 可能无法正确计算出合适的大小。**如果要启用`grid-line`画布插件，需要给父元素 div 设置宽高，在 graph 配置中是无效的**。\n\n### v5无法使用树图布局\n\n统一使用`new Graph({xxx})`。\n\n> 在 v5 中内置布局有`antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5合并了图和树图，不再通过实例化`G6.TreeGraph`创建树图布局，并且移除该方式。具体参考[特性-合并图与树图](/manual/whats-new/feature#🌲-合并图与树图)\n\n### edge 没有连接在 node 的边缘中心\n\n配置[portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter)为 `true`。\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### 如何根据label内容长度动态设置node宽度\n\n参考方案：[#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent节点事件对象类型不齐全问题\n\n可以手动指定`IPointerEvent`类型。具体参考[#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### 解除节点所在组合\n\n更新节点数据，`combo` 值设置为 `null`。\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n","frontmatter":{"title":"常见问题","order":"13"},"isInternal":false,"tokens":1789,"sizeBytes":9563},{"name":"3d.en.md","path":"packages/site/docs/manual/further-reading/3d.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/3d.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Use 3D\norder: 5\n---\n\n## Install Dependencies\n\nBefore using 3D capabilities, please install the 3D extension package first:\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\nThe extension package exports the following:\n\n- renderer: 3D renderer\n\n**Elements**\n\n- Capsule: capsule node\n- Cone: cone node\n- Cube: cube node\n- Cylinder: cylinder node\n- Sphere: sphere node\n- Torus: torus node\n- Line3D: 3D line\n\n**Layout**\n\n- D3Force3DLayout: 3D force-directed layout\n\n**Behaviors**\n\n- DragCanvas3D: drag canvas\n- ObserveCanvas3D: observe canvas\n- RollCanvas3D: rotate canvas\n- ZoomCanvas3D: zoom canvas\n\n**Plugin**\n\n- Light: light source\n\n## Register Extensions\n\nThe following extensions are required:\n\n- renderer\n- at least one 3D node\n- Line3D\n- Light\n\n> The renderer does not need to be registered, it can be passed in during the instantiation of Graph.\n\nRegister as follows:\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## Create 3D Graph\n\nAfter completing the above steps, you can create a 3D graph:\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... other options\n  // use 3d renderer\n  renderer,\n  node: {\n    type: 'sphere', // use 3d node\n    style: {\n      materialType: 'phong', // use Phong material\n    },\n  },\n  edge: {\n    type: 'line3d', // use 3D edge\n  },\n  plugins: [\n    {\n      type: 'light', // Add light source\n      // configure directional light\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\nYou can also refer to:\n\n- [Lite Solar System](/examples/feature/default/#lite-solar-system)\n- [3D Force Layout](/examples/layout/force-directed/#3d-force)\n\n## Tips\n\n`@antv/g6` has a built-in registered plugin for CameraSetting for camera configuration, refer to [plugin](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts).\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","frontmatter":{"title":"Use 3D","order":"5"},"isInternal":false,"tokens":585,"sizeBytes":2337},{"name":"3d.zh.md","path":"packages/site/docs/manual/further-reading/3d.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/3d.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 使用 3D\norder: 5\n---\n\n## 安装依赖\n\n在使用 3D 能力之前，请首先安装 3D 扩展包：\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\n该扩展包导出了以下内容：\n\n- renderer：3D 渲染器\n\n**元素**\n\n- Capsule：胶囊节点\n- Cone：圆锥节点\n- Cube：立方体节点\n- Cylinder：圆柱节点\n- Sphere：球体节点\n- Torus：圆环节点\n- Line3D：3D 线\n\n**布局**\n\n- D3Force3DLayout：3D 力导向布局\n\n**交互**\n\n- DragCanvas3D：拖拽画布\n- ObserveCanvas3D：观察画布\n- RollCanvas3D：旋转画布\n- ZoomCanvas3D：缩放画布\n\n**插件**\n\n- Light：光源\n\n## 注册扩展\n\n其中下列扩展是必须的：\n\n- renderer\n- 至少一个 3D 节点\n- Line3D\n- Light\n\n> renderer 无需注册，实例化 Graph 过程中传入即可。\n\n使用如下方式进行注册：\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## 创建 3D 图\n\n完成上述步骤后，即可创建 3D 图：\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 3D 渲染器\n  renderer,\n  node: {\n    type: 'sphere', // 使用 3D 节点\n    style: {\n      materialType: 'phong', // 使用 Phong 材质\n    },\n  },\n  edge: {\n    type: 'line3d', // 使用 3D 边\n  },\n  plugins: [\n    {\n      type: 'light', // 添加光源\n      // 配置方向光\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n你可以参考以下示例：\n\n- [精简太阳系](/examples/feature/default/#lite-solar-system)\n- [3D 力导向布局](/examples/layout/force-directed/#3d-force)\n\n## 其他\n\n`@antv/g6` 中内置注册了 `CameraSetting` 插件，可用于配置相机，具体可参考[插件](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts)。\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n","frontmatter":{"title":"使用 3D","order":"5"},"isInternal":false,"tokens":443,"sizeBytes":2271},{"name":"bundle.en.md","path":"packages/site/docs/manual/further-reading/bundle.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/bundle.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Bundle Project\norder: 6\n---\n\nIn general, if you are using modern build tools such as Webpack, Rollup, or ESBuild, you can easily build projects that depend on `@antv/g6`.\n\nSome build tools, such as Vite, use ESBuild as the underlying tool, so you can refer to ESBuild's configuration.\n\nBelow are some example configurations that you can refer to when building your project. If you find that these configurations do not work properly, make sure that your build tool version is up to date.\n\n## Bundle Project with Webpack\n\n1. Make sure that `webpack` and `webpack-cli` are installed in your project:\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. Refer to the following `webpack.config.js` for configuration:\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx webpack\n```\n\n> The above configuration works with `\"webpack\": \"^5.94.0\"`, `\"webpack-cli\": \"^5.1.4\"`.\n\n:::error{title=Webpack4}\n⚠️ It is strongly recommended that projects use Webpack 5. If you are using Webpack 4, follow the steps below to configure:\n\n1. Install the necessary dependencies: `babel-loader` (<9), `@babel/preset-env`, `@open-wc/webpack-import-meta-loader`\n\n> If you are using TypeScript, you also need to install `ts-loader`.\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. Modify the `webpack.config.js` configuration:\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> This configuration is for a standard webpack project. If you are using vue-cli, you should REMOVE the `mode: 'production'` option as it is unnecessary.\n\n## Bundle Project with Rollup\n\n1. First, make sure that `rollup` and the necessary plugins are installed in your project:\n\n- `@rollup/plugin-commonjs`: Used to load CommonJS modules\n- `@rollup/plugin-node-resolve`: Used to load Node.js modules\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. Refer to the following `rollup.config.js` for configuration:\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx rollup -c\n```\n\n## Bundle Project with ESBuild\n\n1. First, make sure that `esbuild` is installed in your project:\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. Run the build command:\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","frontmatter":{"title":"Bundle Project","order":"6"},"isInternal":false,"tokens":693,"sizeBytes":2774},{"name":"bundle.zh.md","path":"packages/site/docs/manual/further-reading/bundle.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/bundle.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 项目打包\norder: 6\n---\n\n通常情况下，如果你使用的现代构建工具，如 Webpack、Rollup 或 ESBuild，你可以很容易地构建依赖于 `@antv/g6` 的项目。\n\n一些构建工具例如 Vite，其底层是使用 ESBuild，因此你可以参考 ESBuild 的配置。\n\n下面是一些示例配置，你可以参考这些配置来构建你的项目。如果你发现这些配置无法正常工作，请确保你的构建工具版本较新。\n\n## 使用 Webpack 打包项目\n\n1. 确保你的项目中已经安装了 `webpack` 和 `webpack-cli`：\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. 参考下面的 `webpack.config.js` 进行配置：\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx webpack\n```\n\n> 上述配置在：\"webpack\": \"^5.94.0\"，\"webpack-cli\": \"^5.1.4\" 可以正常工作。\n\n:::error{title=Webpack4}\n⚠️ 强烈建议项目使用 Webpack 5，如果你使用的是 Webpack 4，按以下步骤配置：\n\n1. 安装相关依赖：babel-loader(<9)、@babel/preset-env、@open-wc/webpack-import-meta-loader\n\n> 如果你使用的 typescript，还需要安装 ts-loader\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. 修改 `webpack.config.js` 配置：\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> 如果你使用的是 vue-cli，请移除 mode: 'production' 配置，否则可能会影响开发模式下的构建性能。\n\n## 使用 Rollup 打包项目\n\n1. 首先，确保你的项目中已经安装了 `rollup` 及必要的插件：\n\n- `@rollup/plugin-commonjs`：用于加载 CommonJS 模块\n- `@rollup/plugin-node-resolve`：用于加载 Node.js 模块\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. 参考下面的 `rollup.config.js` 进行配置：\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx rollup -c\n```\n\n## 使用 ESBuild 打包项目\n\n1. 首先，确保你的项目中已经安装了 `esbuild`：\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. 执行构建命令：\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n","frontmatter":{"title":"项目打包","order":"6"},"isInternal":false,"tokens":478,"sizeBytes":2612},{"name":"coordinate.en.md","path":"packages/site/docs/manual/further-reading/coordinate.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/coordinate.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: coordinate\norder: 2\n---\n\n## Overview\n\nThere are three coordinate systems in G6 5.0: Canvas, Viewport, and Client.\n\n### Canvas Coordinate System\n\nThe coordinate system used when drawing G6 elements is not affected by camera zooming or panning. To change the position of an element, you need to directly modify the element's position properties (x/y/z).\n\nThe canvas space is theoretically infinite. In the initial state (no panning, zoom ratio is 1), the origin of the canvas coordinate system is located at the upper-left corner of the viewport.\n\n### Viewport Coordinate System\n\nThe viewport coordinate system is the projection of the camera coordinate system. When the camera pans or zooms, the position of elements in the canvas will also change in the viewport coordinate system.\n\nThe size of the viewport is the size of the canvas DOM container. The origin of the viewport coordinate system is located at the upper-left corner of the viewport, with the x-axis pointing to the right and the y-axis pointing down.\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### Client Coordinate System\n\nThe client coordinate system has the browser's upper-left corner as the origin, with the x-axis pointing to the right and the y-axis pointing down.\n\nThe following figure describes the relationship between the viewport coordinate system and the client coordinate system:\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Coordinate System Conversion\n\nG6 provides methods for coordinate system conversion, making it easy to convert between different coordinate systems.\n\n- Canvas coordinate system to viewport coordinate system: [getViewportByCanvas](/en/api/coordinate#graphgetviewportbycanvaspoint)\n- Client coordinate system to canvas coordinate system: [getCanvasByClient](/en/api/coordinate#graphgetcanvasbyclientpoint)\n- Viewport coordinate system to canvas coordinate system: [getCanvasByViewport](/en/api/coordinate#graphgetcanvasbyviewportpoint)\n- Canvas coordinate system to client coordinate system: [getClientByCanvas](/en/api/coordinate#graphgetclientbycanvaspoint)\n\nOther related APIs are also provided:\n\n- Get the viewport center in viewport coordinates: [getCanvasCenter](/en/api/viewport#graphgetcanvascenter)\n- Get the viewport center in canvas coordinates: [getViewportCenter](/en/api/viewport#graphgetviewportcenter)\n- Get the position of the graph origin in the viewport coordinate system: [getPosition](/en/api/viewport#graphgetposition)\n","frontmatter":{"title":"coordinate","order":"2"},"isInternal":false,"tokens":652,"sizeBytes":2608},{"name":"coordinate.zh.md","path":"packages/site/docs/manual/further-reading/coordinate.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/coordinate.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 坐标系\norder: 2\n---\n\n## 概述\n\n在 G6 5.0 中主要会涉及三个坐标系：画布坐标系(Canvas)、视口坐标系(Viewport)和浏览器坐标系(Client)。\n\n### 画布坐标系\n\nG6 元素绘制时所使用的坐标系，其不受相机缩放、平移的影响，要改变一个元素的位置，需要直接修改元素的位置属性(x/y/z)。\n\n画布空间理论上是无限大的，在初始状态下（无平移、缩放倍率为1），画布坐标系的原点位于视口左上角位置。\n\n### 视口坐标系\n\n视口坐标系是相机坐标系的投影，当相机发生平移、缩放时，画布中元素位置在视口坐标系中的位置也会发生变化。\n\n视口的大小即画布 DOM 容器的大小，视口坐标系的原点位于视口左上角位置，x 轴正方向向右，y 轴正方向向下。\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### 浏览器坐标系\n\n浏览器坐标系以浏览器左上角为原点，x 轴正方向向右，y 轴正方向向下。\n\n下图描述了视口坐标系和浏览器坐标系之间的关系：\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 坐标系转换\n\nG6 提供了坐标系转换的方法，可以方便地在不同坐标系之间进行转换。\n\n- 画布坐标系转视口坐标系：[getViewportByCanvas](/api/coordinate#graphgetviewportbycanvaspoint)\n- 浏览器坐标系转画布坐标系：[getCanvasByClient](/api/coordinate#graphgetcanvasbyclientpoint)\n- 视口坐标系转画布坐标系：[getCanvasByViewport](/api/coordinate#graphgetcanvasbyviewportpoint)\n- 画布坐标系转浏览器坐标系：[getClientByCanvas](/api/coordinate#graphgetclientbycanvaspoint)\n\n另外还提供了其他相关 API：\n\n- 获取视口中心的视口坐标：[getCanvasCenter](/api/viewport#graphgetcanvascenter)\n- 获取视口中心的画布坐标：[getViewportCenter](/api/viewport#graphgetviewportcenter)\n- 获取图原点在视口坐标系中的位置：[getPosition](/api/viewport#graphgetposition)\n","frontmatter":{"title":"坐标系","order":"2"},"isInternal":false,"tokens":315,"sizeBytes":2140},{"name":"download-image.en.md","path":"packages/site/docs/manual/further-reading/download-image.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/download-image.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: download-image\norder: 3\n---\n\nG6 5.0 only provides an API for exporting the canvas as a Base64 image ([toDataURL](/en/api/export-image#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=note}\nThe exported image may not contain the complete canvas content; the export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., and this content will not appear in the exported image.\n:::\n","frontmatter":{"title":"download-image","order":"3"},"isInternal":false,"tokens":267,"sizeBytes":1067},{"name":"download-image.zh.md","path":"packages/site/docs/manual/further-reading/download-image.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/download-image.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 下载图片\norder: 3\n---\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](/api/export-image#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n","frontmatter":{"title":"下载图片","order":"3"},"isInternal":false,"tokens":200,"sizeBytes":1010},{"name":"event.en.md","path":"packages/site/docs/manual/further-reading/event.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/event.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Event\norder: 0\n---\n\n## Overview\n\nThe event system in G6 is encapsulated based on the event system of [G](https://g.antv.antgroup.com/en/api/event/intro), providing a wider range of event types and more convenient methods for event binding and unbinding.\n\n## Event Types\n\nThe event types in G6 are mainly divided into the following categories:\n\n1. Graph events\n2. Canvas events\n3. Element events\n\n### Graph Events\n\nGraph events refer to events associated with the entire graph instance, such as the graph's rendering completion event, the graph's update event, etc. The complete list of graph events can be found at [GraphEvent](/en/api/event#graph-lifecycle-events-graphevent).\n\n#### Listening to Graph Events\n\nListening to graph events is consistent with the default event listening method. For example, to listen to the graph's rendering completion event:\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### Canvas Events\n\nCanvas events refer to events associated with the canvas, such as the canvas's click event, the canvas's drag event, etc. The complete list of canvas events can be found at [CanvasEvent](/en/api/event#canvas-events-canvasevent).\n\n#### Listening to Canvas Events\n\nFor example, to listen to the canvas's click event:\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### Element Events\n\nElement events primarily refer to events that are triggered on element objects, such as a node's drag event, an edge's click event, etc. Elements are categorized into three types: nodes (`node`), edges (`edge`), and combos (`combo`). The complete list of corresponding events can be found at: [NodeEvent](/en/api/event#node-events-nodeevent), [EdgeEvent](/en/api/event#edge-events-edgeevent), [ComboEvent](/en/api/event#combo-events-comboevent).\n\n#### Listening to Element Events\n\nSimilar to canvas events, for example, to listen to a node's drag event and an edge's click event:\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## Event Listening and Unlistening\n\nG6 provides the following APIs for event listening and unlistening:\n\n### on\n\nAdd an event listener\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\nRemove an event listener\n\n```typescript\ngraph.off('event_name', handler);\n```\n\nWhen no arguments are passed, it will remove all event listeners:\n\n```typescript\ngraph.off();\n```\n\n### once\n\nAdd a one-time event listener, which means the event listener will be automatically removed after the event is triggered\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\nIf you want to manually trigger an event, you can use the `emit` method:\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","frontmatter":{"title":"Event","order":"0"},"isInternal":false,"tokens":805,"sizeBytes":3218},{"name":"event.zh.md","path":"packages/site/docs/manual/further-reading/event.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/event.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 事件\norder: 0\n---\n\n## 概述\n\nG6 中的事件系统是在 [G](https://g.antv.antgroup.com/api/event/intro) 的事件系统基础上进行了封装，提供了更多的事件类型，以及更加方便的事件绑定和解绑方法。\n\n## 事件类型\n\nG6 中的事件类型主要分为以下几类：\n\n1. 图(Graph)事件\n2. 画布(Canvas)事件\n3. 元素(Element)事件\n\n### 图事件\n\n图事件是指与整个图实例相关的事件，例如图的渲染完成事件、图的更新事件等。图事件的完整列表见[GraphEvent](/api/event#图表生命周期事件-graphevent)。\n\n#### 监听图事件\n\n图事件的监听与默认的事件监听方式一致，例如监听图的渲染完成事件：\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### 画布事件\n\n画布事件是指与画布相关的事件，例如画布的点击事件、画布的拖拽事件等。画布事件的完整列表见[CanvasEvent](/api/event#画布事件-canvasevent)。\n\n#### 监听画布事件\n\n例如监听画布的点击事件：\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### 元素事件\n\n元素事件主要指在元素对象上触发的事件，例如节点的拖拽事件、边的点击事件等。元素分为节点(`node`)、边(`edge`)、组合(`combo`)三类，对应的事件完整列表分别见：[NodeEvent](/api/event#节点事件-nodeevent) 、[EdgeEvent](/api/event#边事件-edgeevent)、[ComboEvent](/api/event#combo事件-comboevent)。\n\n#### 监听元素事件\n\n与画布事件类似，例如监听节点的拖拽和边的点击事件：\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## 事件监听与解除\n\nG6 提供以下 API 用于事件监听和解除：\n\n### on\n\n添加事件监听\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\n移除事件监听\n\n```typescript\ngraph.off('event_name', handler);\n```\n\n当不传入任何参数时，会移除所有事件监听：\n\n```typescript\ngraph.off();\n```\n\n### once\n\n添加一次性事件监听，即事件触发后会自动移除事件监听\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\n如果你想手动触发一个事件，可以使用 `emit` 方法：\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n","frontmatter":{"title":"事件","order":"0"},"isInternal":false,"tokens":470,"sizeBytes":2795},{"name":"iconfont.en.md","path":"packages/site/docs/manual/further-reading/iconfont.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/iconfont.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Using Iconfont\norder: 4\n---\n\n## Overview\n\nWhy use iconfont? It offers great compatibility, a wide variety of icons, and multicolor options. For more details, please visit the [Alibaba Iconfont Platform](https://www.iconfont.cn).\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## Usage\n\n### Download Font Icons\n\nFirst, you need to download the desired font icons from the [iconfont](https://www.iconfont.cn) website. Create a project, select the required icons, and then download the generated icon files.\n\n### Add Font Icons\n\nAfter downloading, place the directory containing the icon font files (typically including `.eot`, `.woff`, `.ttf`, and `.svg` files, as well as the `iconfont.css` stylesheet) into your project.\n\nYou can choose how to include them. Below is an example of how to include them in HTML:\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### Using the Font\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // Corresponds to the `font-family` value in iconfont.css\n      iconText: '\\ue7f1', // Corresponds to the `content` value in iconfont.css, make sure to add `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### Utility Function `getIcon()`\n\nTo make it easier to retrieve icons, you can create a utility function `getIcon`. This function reads the icon information from the `iconfont.json` file and returns the corresponding Unicode character. Note that manually concatenating Unicode (`\\\\u${icon.unicode}`) won't work. Refer to [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) for details.\n\nFirst, ensure you have an `iconfont.json` file containing the detailed icon information.\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\nUse it in your project:\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","frontmatter":{"title":"Using Iconfont","order":"4"},"isInternal":false,"tokens":591,"sizeBytes":2363},{"name":"iconfont.zh.md","path":"packages/site/docs/manual/further-reading/iconfont.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/iconfont.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 使用 iconfont\norder: 4\n---\n\n## 概述\n\n为什么使用 iconfont？ 兼容性好、种类多、多色等。在此不做过多介绍，请直接移步 [阿里巴巴-iconfont 平台](https://www.iconfont.cn)。\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## 使用\n\n### 下载字体图标\n\n首先，你需要从 [iconfont](https://www.iconfont.cn) 网站下载所需的图标字体。创建一个项目并选择所需的图标，然后下载生成的图标文件。\n\n### 添加字体图标\n\n下载完成后，将包含图标字体文件的目录（通常包括 `.eot`、`.woff`、`.ttf` 和 `.svg` 文件，以及 `iconfont.css` 样式文件）放入你的项目中。\n\n引入方式可自行选择，下面为在 HTML 中引入的例子：\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### 使用字体\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // 对应 iconfont.css 中的 `font-family` 属性值\n      iconText: '\\ue7f1', // 对应 iconfont.css 中的 `content` 属性值，注意加 `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### 工具函数 `getIcon()`\n\n为了更方便地获取图标，可以创建一个工具函数 `getIcon`。该函数会从图标文件 `iconfont.json` 中读取图标信息并返回相应的 Unicode 字符。这里注意，手动拼接 unicode 是不行的（`\\\\u${icon.unicode}`）。详细参考 [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)。\n\n首先，确保你有一个 `iconfont.json` 文件，包含图标的详细信息。\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type: string) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\n在项目中使用：\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n","frontmatter":{"title":"使用 iconfont","order":"4"},"isInternal":false,"tokens":416,"sizeBytes":2246},{"name":"renderer.en.md","path":"packages/site/docs/manual/further-reading/renderer.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/renderer.en.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: renderer\norder: 1\n---\n\nG6 uses Canvas as the default renderer, but also supports rendering with SVG and WebGL. To switch to the SVG or WebGL renderer, simply pass the `renderer` parameter during initialization.\n\n## Using the SVG Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the SVG renderer here\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## Using the WebGL Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the WebGL renderer here\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## Using Different Renderers for Different Layers\n\nG6 uses layered canvases for rendering, so `renderer` is a callback function that takes the canvas type as a parameter and returns the renderer instance. If you want to use different renderers on different canvases, you can configure it like this:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // The main canvas uses the WebGL renderer, and the other canvases use the SVG renderer\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## Switch Renderers Dynamically\n\nG6 does not provide a API to switch the renderer, but you can still update the `renderer` option through the `setOptions` method.\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// Use the WebGL renderer by default\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// Switch to the SVG renderer\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","frontmatter":{"title":"renderer","order":"1"},"isInternal":false,"tokens":556,"sizeBytes":2222},{"name":"renderer.zh.md","path":"packages/site/docs/manual/further-reading/renderer.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/further-reading/renderer.zh.md","title":"Further-reading Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 渲染器\norder: 1\n---\n\nG6 默认使用 Canvas 作为渲染器，但也支持通过 SVG 和 WebGL 进行渲染，要切换到 SVG 或 WebGL 渲染器，只需在初始化时传入 `renderer` 参数即可。\n\n## 使用 SVG 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 SVG 渲染器\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## 使用 WebGL 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 WebGL 渲染器\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## 分层使用不同的渲染器\n\nG6 采用了分层画布进行渲染，因此 `renderer` 是一个回调函数，参数是画布类型，返回渲染器实例，如果你想在不同的画布上使用不同的渲染器，可以这样配置：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // 主画布使用 WebGL 渲染器，其他画布使用 SVG 渲染器\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## 动态切换渲染器\n\nG6 没有提供单独的 API 来切换渲染器，但你仍可以通过 `setOptions` 方法来更新 `renderer` 参数：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// 初始化时使用 WebGL 渲染器\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// 切换到 SVG 渲染器\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n","frontmatter":{"title":"渲染器","order":"1"},"isInternal":false,"tokens":398,"sizeBytes":2108},{"name":"installation.en.md","path":"packages/site/docs/manual/getting-started/installation.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/installation.en.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Installation\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\nImport G6 in the code:\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\nVisit [G6 npm Example](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) to view the complete example code.\n\n## CDN\n\n`@antv/g6` Available on multiple CDNs:\n\n- unpkg: https://unpkg.com/@antv/g6@5/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\nImport G6 using a `script` tag:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\nVisit [G6 CDN Example](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) to view the complete example code.\n","frontmatter":{"title":"Installation","order":"1"},"isInternal":false,"tokens":202,"sizeBytes":808},{"name":"installation.zh.md","path":"packages/site/docs/manual/getting-started/installation.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/installation.zh.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 安装\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\n在代码中引入 G6：\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\n访问 [G6 npm 示例](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) 查看完整示例代码。\n\n## CDN\n\n`@antv/g6` 在多个 CDN 上提供：\n\n- unpkg: https://unpkg.com/@antv/g6@latest/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\n使用 `script` 标签引入 G6：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n访问 [G6 CDN 示例](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) 查看完整示例代码。\n","frontmatter":{"title":"安装","order":"1"},"isInternal":false,"tokens":175,"sizeBytes":797},{"name":"angular.en.md","path":"packages/site/docs/manual/getting-started/integration/angular.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/angular.en.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: angular\norder: 2\n---\n\nRefer to the example below, you can use G6 in Angular, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","frontmatter":{"title":"angular","order":"2"},"isInternal":false,"tokens":60,"sizeBytes":242},{"name":"angular.zh.md","path":"packages/site/docs/manual/getting-started/integration/angular.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/angular.zh.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 在 Angular 中使用\norder: 2\n---\n\n参考下面的示例，你可以在 Angular 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n","frontmatter":{"title":"在 Angular 中使用","order":"2"},"isInternal":false,"tokens":48,"sizeBytes":251},{"name":"react.en.md","path":"packages/site/docs/manual/getting-started/integration/react.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/react.en.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: react\norder: 0\n---\n\n## Non-Strict Mode\n\nRefer to the example below, you can use G6 in React, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## Strict Mode\n\nIn strict mode, React intentionally mounts, unmounts, and remounts components in development. Create the Graph instance inside an effect, keep it in a ref, and destroy it in the cleanup callback so the first development-only mount does not leave a stale graph behind. The following complete example also shows how to register and render a React node.\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","frontmatter":{"title":"react","order":"0"},"isInternal":false,"tokens":168,"sizeBytes":674},{"name":"react.zh.md","path":"packages/site/docs/manual/getting-started/integration/react.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/react.zh.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 在 React 中使用\norder: 0\n---\n\n:::info{title=建议}\n如果你需要更完善的 React 与 G6 集成解决方案，可以使用 AntV 官方封装库 [`@antv/graphin`](https://github.com/antvis/graphin)。\n:::\n\n## 非严格模式\n\n参考下面的示例，你可以在 React 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## 严格模式\n\n在严格模式下，React 会在开发环境中有意执行挂载、卸载、再挂载。请把 Graph 实例放在 effect 里创建，用 ref 保存，并在清理函数中销毁，这样第一次开发态挂载不会留下旧实例。下面的完整示例同时演示了如何注册和渲染 React 节点。\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n","frontmatter":{"title":"在 React 中使用","order":"0"},"isInternal":false,"tokens":126,"sizeBytes":822},{"name":"vue.en.md","path":"packages/site/docs/manual/getting-started/integration/vue.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/vue.en.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: vue\norder: 1\n---\n\n:::warning\nPlease do not pass Vue reactive data directly to the G6 instance, which may cause G6 to fail to render correctly, or even cause the page to crash.\n:::\n\nRefer to the example below, you can use G6 in Vue, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","frontmatter":{"title":"vue","order":"1"},"isInternal":false,"tokens":97,"sizeBytes":387},{"name":"vue.zh.md","path":"packages/site/docs/manual/getting-started/integration/vue.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/integration/vue.zh.md","title":"Integration Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 在 Vue 中使用\norder: 1\n---\n\n:::warning{title=注意}\n请不要将 Vue 响应式数据直接传递给 G6 实例，这可能会导致 G6 无法正确渲染，甚至导致页面崩溃。\n:::\n\n参考下面的示例，你可以在 Vue 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n","frontmatter":{"title":"在 Vue 中使用","order":"1"},"isInternal":false,"tokens":63,"sizeBytes":394},{"name":"quick-start.en.md","path":"packages/site/docs/manual/getting-started/quick-start.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/quick-start.en.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Quick Start\norder: 0\n---\n\n## Online Experience with G6\n\nVisit [Chart Examples](/en/examples) to experience G6 online without any environment setup.\n\n## Creating a Simple Graph\n\nIn this example, we will create a simple graph using G6 based on an HTML page.\n\nCopy the following code into an HTML file and then open this file in a browser:\n\n```html\n<!-- Prepare a container -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- Import G6's JS file -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\nYou will get a graph as shown below:\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\nLet's analyze the following code snippet:\n\n1. First, we create a `div` element to serve as the container for the graph:\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. Then, include the G6's JS file:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. Use the `fetch` method to obtain the graph's data:\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. Finally, create an instance of the graph, pass in the configuration object, and call the `render` method to render the graph:\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\nIf you are using frameworks such as React, Vue, Angular, etc., you can refer to:\n\n- [Using G6 in React](./integration/react)\n- [Using G6 in Vue](./integration/vue)\n- [Using G6 in Angular](./integration/angular)\n","frontmatter":{"title":"Quick Start","order":"0"},"isInternal":false,"tokens":632,"sizeBytes":2525},{"name":"quick-start.zh.md","path":"packages/site/docs/manual/getting-started/quick-start.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/quick-start.zh.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 快速开始\norder: 0\n---\n\n## 在线体验 G6\n\n访问 [图表示例](/examples) 无需任何环境配置即可在线体验 G6。\n\n## 创建一个简单的图\n\n在本例子中，我们将基于 HTML 页面使用 G6 创建一个简单的图。\n\n将下面的代码复制到一个 HTML 文件中，然后在浏览器中打开这个文件：\n\n```html\n<!-- 准备一个容器 -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- 引入 G6 的 JS 文件 -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\n会得到如下所示的图：\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\n下面分析一下这段代码：\n\n1. 首先我们创建一个 `div` 元素作为图的容器：\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. 然后引入 G6 的 JS 文件：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. 使用 `fetch` 方法获取图的数据：\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. 最后创建一个图实例，传入配置对象，并调用 `render` 方法渲染图：\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n如果你使用 React、Vue、Angular 等框架，可以查看：\n\n- [在 React 中使用 G6](./integration/react)\n- [在 Vue 中使用 G6](./integration/vue)\n- [在 Angular 中使用 G6](./integration/angular)\n","frontmatter":{"title":"快速开始","order":"0"},"isInternal":false,"tokens":508,"sizeBytes":2455},{"name":"step-by-step.en.md","path":"packages/site/docs/manual/getting-started/step-by-step.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/step-by-step.en.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Step-by-step guide\norder: 3\n---\n\nThis tutorial will guide you through the development of a G6 chart from scratch, and along the way, you will learn and understand the main concepts of G6.\n\n## Create Application\n\nWe will use Vite to create a simple front-end application.\n\n### Initialization\n\nFirst, create an empty directory:\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\nInitialize the project:\n\n```bash\nnpm init -y\n```\n\nInstall G6:\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite is a new type of front-end build tool that is based on ESModule and can quickly start up projects.\n\nInstall Vite:\n\n```bash\nnpm install vite --save-dev\n```\n\nAdd a start script to the `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### Create Files\n\nCreate the `index.html` and `main.ts` files with the following content:\n\n**index.html**:\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### Start project\n\n```bash\nnpm run dev\n```\n\nOpen a web browser and visit the address output in the terminal (typically: http://127.0.0.1:5173/), and you will see a pop-up displaying \"Hello, G6!\".\n\n## Creating a Simple Graph\n\nNext, we will create a simple chart using G6.\n\n### Preparing the Data\n\nG6 uses JSON-formatted data to describe the graph, which usually includes nodes and edges. We will use the following prepared data:\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\nThe data includes two nodes and one edge. The `id` attribute for nodes is mandatory, and the position of each node is set in the `style`. The `source` and `target` attributes of the edge represent the `id` of the starting node and the ending node, respectively.\n\n### Creating and Drawing the Graph\n\nCreate an instance of the Graph, pass in a configuration object that includes the container and data, and then call the `render` method to draw the Graph:\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\nAs shown below, you can see that the chart has been successfully drawn:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### Element\n\nNext, we will introduce how to configure the style and types of elements in the canvas.\n\nG6 provides various mechanisms to configure element styles, which can be done in the data itself or within the chart instance. In the previous example, we configured the position of the nodes in the data. Next, we will configure the styles of nodes and edges in the graph configuration options:\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\nAs the code shows, we have configured the fill color of the nodes to be pink and the stroke color of the edges to be light green within the chart instance. You can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\nThe key parts are the `node.style` and `edge.style` options, which are used to configure the styles of nodes and edges, respectively.\n\n> In the subsequent code examples, we will only display the parts of the options. For the complete code of this project, please refer to the [Complete Example](https://codesandbox.io/s/g6-tutorial).\n\nNext, we will demonstrate more types of nodes by setting the node type:\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\nIn the code above, we set the `type` attribute of the node, which can be a string or a function. When `type` is a function, the argument of the function is the current node's data object, and the return value is the type of the node.\n\n> Similarly, each attribute under the `style` style of an element can also be a function, with the argument being the current element's data object.\n\n> You can even set the entire `style` property as a function, allowing you to dynamically set the element's style based on the data object.\n\nThe circular node (`circle`) is the default node type in G6. Here, we set the type of the first node to a circle and the type of the second node to a rectangle.\n\nAt the same time, we also set the size of the nodes to 20, so the first node is a circle with a radius of 10, and the second node is a square with a side length of 20.\n\n> If you want to set the size of the rectangular node to 20x10, you can set `size` to an array `[20, 10]`.\n\nYou can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### Behaviors\n\nThe chart provided in the previous example is static. Next, we will add some interactive behaviors.\n\nG6 offers a variety of interactive behaviors. We will add a few commonly used Behaviors to allow users to drag, zoom the canvas, and drag nodes.\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\nTry dragging nodes and the canvas in the example below, and use the scroll wheel to zoom in and out on the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### Layout\n\nIn the previous example, we manually set the positions of the nodes. However, this can become very difficult when there are many nodes.\n\nLayout algorithms can automatically adjust the positions of nodes based on certain rules. G6 provides a variety of layout algorithms, such as tree layout, force-directed layout, and so on.\n\nFirst, generate a set of data that does not include position information:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nBy default, if a node does not have position information, G6 will place the node at the top-left corner, that is, at the coordinates `(0, 0)`.\n\nNext, we will use the `d3-force` layout algorithm, which is a force-directed layout algorithm that can simulate the forces of attraction and repulsion between nodes, allowing the nodes to automatically adjust to suitable positions.\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\nView the example below, and you can see that the nodes have automatically adjusted to suitable positions:\n\n<details>\n<summary>Complete Code</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### Palette\n\nSimilarly, when there are many nodes, manually setting the color of each node can become difficult. G6 provides a palette mechanism that makes it easy to assign colors to elements.\n\nPalettes typically assign colors to elements based on a specific field in the data, such as the type of node, the weight of an edge, etc.\n\nBelow, we add a `category` field in the data:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nThen, use the `tableau` palette to set the colors for the nodes, where the `field` attribute specifies the field in the data, and the `color` attribute specifies the name of the palette.\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> It is important to note that the `fill` style in `node.style` should be removed, as its priority is higher than the colors assigned by the palette.\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### Plugins\n\nThe plugin mechanism is an important feature of G6, which allows you to extend the functionality of G6 through plugins. G6 provides a wealth of built-in plugins, such as `tooltip`, `legend`, etc., and also supports user-defined plugins.\n\nBelow, we will use the `grid-line` plugin to add grid lines to the canvas:\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\nYou can see that grid lines have been added to the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\nThe plugin configuration mentioned above used a shorthand form. Most plugins support the passing of additional parameters. For example, the `grid-line` plugin allows you to configure the `follow` property to specify whether the grid lines should follow the canvas when it is dragged.\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\nTry dragging the canvas in the example below, and you will see that the grid lines move along with the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## Summary\n\nIn this tutorial, we created a G6 chart from scratch and became acquainted with the main concepts of G6. We learned how to create a simple chart, how to configure the style and types of elements, how to add interactive behaviors, how to use layout algorithms, how to use palettes, and how to use plugins.\n\nFor a more detailed introduction to the concepts of G6, you can refer to [Core Concepts](/en/manual/graph/graph).\n\nDetailed explanations of options such as elements, layouts, and plugins can be found in the [API](/en/api/data).\n","frontmatter":{"title":"Step-by-step guide","order":"3"},"isInternal":false,"tokens":2639,"sizeBytes":10555},{"name":"step-by-step.zh.md","path":"packages/site/docs/manual/getting-started/step-by-step.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/getting-started/step-by-step.zh.md","title":"Getting-started Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 详细教程\norder: 3\n---\n\n本教程将引导你从头开始完成一个 G6 图表开发，并在过程中了解和学习 G6 的主要概念。\n\n## 创建应用\n\n我们将使用 Vite 来创建一个简单的前端应用。\n\n### 初始化\n\n首先创建一个空目录：\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\n初始化项目：\n\n```bash\nnpm init -y\n```\n\n安装 G6：\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite 是一个新型的前端构建工具，它基于 ESModule，可以快速启动项目。\n\n安装 Vite：\n\n```bash\nnpm install vite --save-dev\n```\n\n在 `package.json` 中添加启动脚本：\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### 创建文件\n\n创建 `index.html` 和 `main.ts` 文件，内容如下：\n\n**index.html**：\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### 启动项目\n\n```bash\nnpm run dev\n```\n\n打开浏览器访问终端中输出的地址（通常为：http://127.0.0.1:5173/ ），你将看到一个弹窗显示 \"Hello, G6!\"。\n\n## 创建一个简单的图表\n\n接下来，我们将使用 G6 创建一个简单的图表。\n\n### 准备数据\n\nG6 使用 JSON 格式的数据来描述图，通常包括节点和边。我们将使用下面准备的数据：\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\n数据中包括两个节点和一条边，节点的 `id` 属性是必须的，并在 `style` 设置了每个节点的位置。边的 `source` 和 `target` 属性分别表示边的起始节点 `id` 和结束节点 `id`。\n\n### 创建并绘制图表\n\n创建一个图表实例，传入一个配置对象，包括容器和数据，然后调用 `render` 方法渲染图表：\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\n如下所示，可以看到图表已经顺利绘制出来：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### 元素\n\n接下来将介绍如何配置画布中的元素样式和种类。\n\nG6 提供了多种机制来配置元素样式，可以在数据中进行配置，也可以在图表实例中进行配置。前面的示例中，我们在数据中配置了节点的位置，接下来我们在图配置项中配置节点和边的样式：\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\n正如代码所示，我们在图表实例中配置了节点的填充颜色为粉色，边的描边颜色为浅绿色。你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\n其中的关键部分是 `node.style` 和 `edge.style` 配置项，分别用来配置节点和边的样式。\n\n> 在后续的代码示例中，我们仅展示配置项的部分代码，本项目的完整代码请查看 [完整示例](https://codesandbox.io/s/g6-tutorial)。\n\n下面我们将通过设置节点的类型来展示更多的节点种类：\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\n上面的代码中，我们设置了节点的 `type` 属性，其值可以是一个字符串，也可以是一个函数。当 `type` 是一个函数时，函数的参数是当前节点的数据对象，函数的返回值是节点的类型。\n\n> 同样的，元素中 `style` 样式下的每个属性都可以是一个函数，函数的参数是当前元素的数据对象。\n\n> 你甚至可以将整个 `style` 属性设置为一个函数，这样你可以根据数据对象动态设置元素的样式。\n\n圆形节点(`circle`)是 G6 的默认节点类型，这里我们将第一个节点的类型设置为圆形，第二个节点的类型设置为矩形。\n\n同时我们还将节点的大小设置为 20，因此第一个节点是一个半径为 10 的圆形，第二个节点是一个边长为 20 的正方形。\n\n> 如果你想将矩形节点的大小设置为 20x10，可以将 `size` 设置为一个数组 `[20, 10]`。\n\n你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### 交互\n\n在上面的例子中提供的图表是静态的，接下来我们将添加一些交互行为。\n\nG6 提供了多种交互行为，我们添加几个常用的交互，使得用户可以拖拽、缩放画布，拖拽节点。\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\n尝试在下面的示例中拖拽节点和画布，并使用滚轮缩放画布：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### 布局\n\n在上面的示例中，我们手动设置了节点的位置。但当节点数量较多时，这会变得非常困难。\n\n布局算法可以基于一定的规则自动调整节点的位置，G6 提供了多种布局算法，例如树形布局、力导向布局等。\n\n首先生成一组不包括位置信息的数据：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n默认情况下，如果节点没有位置信息，G6 会将节点放置在左上角，即 `(0, 0)`。\n\n接下来我们使用 `d3-force` 布局算法，它是一种力导向布局算法，可以模拟节点之间的引力和斥力，使得节点自动调整到合适的位置。\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\n查看下面的示例，可以看到节点已经自动调整到合适的位置：\n\n<details>\n<summary>完整代码</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### 色板\n\n同样的，当节点数量较多时，手动设置节点的颜色也会变得困难。G6 提供了色板机制，可以便捷地为元素设置颜色。\n\n色板通常会基于数据的某个字段为元素设置颜色，例如节点的类型、边的权重等。\n\n下面我们在数据中的添加 `category` 字段：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n然后使用 `tableau` 色板为节点设置颜色，`field` 属性指定了数据中的字段，`color` 属性指定了色板的名称。\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> 需要注意将 `node.style` 中的 `fill` 样式移除，因为其优先级高于色板分配的颜色。\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### 插件\n\n插件机制是 G6 的一个重要特性，可以通过插件扩展 G6 的功能。G6 提供了丰富的内置插件，例如 `tooltip`、`legend` 等，也支持用户自定义插件。\n\n下面我们将使用 `grid-line` 插件为画布添加网格线：\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\n可以看到画布已经添加了网格线：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\n上面的插件配置项中使用了简写形式，大部分的插件都支持传递额外的参数，例如 `grid-line` 插件可以配置 `follow` 属性来指定拖拽画布时网格线是否跟随画布移动。\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\n尝试在下面的示例中拖拽画布，可以看到网格线跟随画布移动：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## 小结\n\n在本教程中，我们从头开始创建了一个 G6 图表，并了解了 G6 的主要概念。我们学习了如何创建一个简单的图表，如何配置元素的样式和种类，如何添加交互行为，如何使用布局算法，如何使用色板，如何使用插件。\n\n关于 G6 更加详细的概念介绍可以在 [核心概念](/manual/graph/graph) 中查看。\n\n图的 API 详细说明可以在 [API](/api/graph) 中查看。\n","frontmatter":{"title":"详细教程","order":"3"},"isInternal":false,"tokens":1527,"sizeBytes":9518},{"name":"extension.en.md","path":"packages/site/docs/manual/graph/extension.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/extension.en.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: extension\norder: 9\n---\n\n## Concept\n\nExtension is an important concept in G6, it is a general term for all expandable parts in G6, including the following types:\n\n- Animation\n- Behavior\n- Element\n  - Node\n  - Edge\n  - Combo\n- Layout\n- Palette\n- Plugin\n- Theme\n- Transform\n\n## Register Extension\n\nG6 provides the `register` function for registering extensions, for example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// # Registering Nodes\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\nThe first parameter of the `register` function is the type of the extension, the second parameter is the name of the extension, and the third parameter is the implementation of the extension(refer to the custom-related sections in the documentation for each extension type).\n\nDifferent types of extensions **can** use the same extension name, but when registering extensions of the same type, only the first registration will take effect.\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## Use Extension\n\nThe configuration location for different types of extensions varies, but all are used by specifying the name that was used during registration, for example:\n\n- Using node extensions: `options.node.type`\n- Using edge extensions: `options.edge.type`\n- Using combo extensions: `options.combo.type`\n- Using behavior extensions: `options.behaviors`\n- Using layout extensions: `options.layout.type`\n- Using plugin extensions: `options.plugins`\n- Using theme extensions: `options.theme`\n- Using data transform extensions: `options.transform`\n- Using palette extensions: `options.node.palette`, `options.edge.palette`, etc.\n- Using animation extensions: `options.node.animate`, `options.edge.animate`, etc.\n\n## Get Extension\n\nG6 provides the `getExtension` and `getExtensions` methods to obtain a single extension and all extensions of a specified type, respectively, for example:\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// To get the implementation of the node extension registered with the name 'custom-node'\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// Retrieve all registered node extension implementations\ngetExtensions(ExtensionCategory.NODE);\n```\n","frontmatter":{"title":"extension","order":"9"},"isInternal":false,"tokens":634,"sizeBytes":2538},{"name":"extension.zh.md","path":"packages/site/docs/manual/graph/extension.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/extension.zh.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Extension - 扩展\norder: 9\n---\n\n## 概念\n\n扩展 (Extension) 是 G6 中的一个重要概念，它是 G6 中所有可扩展部分的统称，包括以下几种：\n\n- 动画 (Animation)\n- 交互 (Behavior)\n- 元素 (Element)\n- 节点 (Node)\n  - 边 (Edge)\n  - 组合 (Combo)\n- 布局 (Layout)\n- 色板 (Palette)\n- 插件 (Plugin)\n- 主题 (Theme)\n- 数据转换 (Transform)\n\n## 注册扩展\n\nG6 提供了 `register` 函数用于注册扩展，例如：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// 注册节点\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\n`register` 函数的第一个参数是扩展的类型，第二个参数是扩展的名称，第三个参数是扩展的实现(扩展实现参考各扩展类型所在文档的自定义相关章节)。\n\n不同的扩展类型之间**可以**使用相同的扩展名称，但同一类型的扩展重复注册时仅会在第一次注册时生效。\n\n<!-- TODO: 详细的参数签名见：[API 文档](/api/reference/g6/register) -->\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## 使用扩展\n\n不同的扩展类型的配置位置有所不同，但都是通过指定注册时所使用的名称来使用扩展，例如：\n\n- 使用节点扩展：`options.node.type`\n- 使用边扩展：`options.edge.type`\n- 使用组合扩展：`options.combo.type`\n- 使用交互扩展：`options.behaviors`\n- 使用布局扩展：`options.layout.type`\n- 使用插件扩展：`options.plugins`\n- 使用主题扩展：`options.theme`\n- 使用数据转换扩展：`options.transform`\n- 使用色板扩展：`options.node.palette` `options.edge.palette` 等\n- 使用动画扩展：`options.node.animate` `options.edge.animate` 等\n\n## 获取扩展\n\nG6 提供了 `getExtension` 和 `getExtensions` 方法分别用于获取指定扩展类型下的单个扩展和所有扩展，例如：\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// 获取注册的名称为 'custom-node' 的节点扩展实现\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// 获取所有注册的节点扩展实现\ngetExtensions(ExtensionCategory.NODE);\n```\n","frontmatter":{"title":"Extension - 扩展","order":"9"},"isInternal":false,"tokens":421,"sizeBytes":2459},{"name":"extensions.en.md","path":"packages/site/docs/manual/graph/extensions.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/extensions.en.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\n\ntitle: Built-in Extensions\norder: 4\n\nThe G6 built-in extensions and registered types are as follows:\n\n## Animations\n\n| Extension     | Registration Type |\n| ------------- | ----------------- |\n| ComboCollapse | 'combo-collapse'  |\n| ComboExpand   | 'combo-expand'    |\n| NodeCollapse  | 'node-collapse'   |\n| NodeExpand    | 'node-expand'     |\n| PathIn        | 'path-in'         |\n| PathOut       | 'path-out'        |\n| Fade          | 'fade'            |\n| Translate     | 'translate'       |\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].animation.[stage]`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    animation: {\n      update: 'translate', // Only use translation animation in the update stage\n    },\n  },\n});\n```\n\n## Behaviors\n\n| Extension                 | Registration Type             | Description                                    |\n| ------------------------- | ----------------------------- | ---------------------------------------------- |\n| BrushSelect               | 'brush-select'                | /                                              |\n| ClickSelect               | 'click-select'                | /                                              |\n| CollapseExpand            | 'collapse-expand'             | /                                              |\n| CreateEdge                | 'create-edge'                 | /                                              |\n| DragCanvas                | 'drag-canvas'                 | /                                              |\n| DragElementForce          | 'drag-element-force'          | Drag element when use d3-force layout          |\n| DragElement               | 'drag-element'                | /                                              |\n| FixElementSize            | 'fix-element-size'            | Keep the size of element during zooming canvas |\n| FocusElement              | 'focus-element'               | /                                              |\n| HoverActivate             | 'hover-activate'              | /                                              |\n| LassoSelect               | 'lasso-select'                | /                                              |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | Hide elements during manipulate the canvas     |\n| ScrollCanvas              | 'scroll-canvas'               | /                                              |\n| ZoomCanvas                | 'zoom-canvas'                 | /                                              |\n\nUsage:\n\nIn `GraphOptions.behaviors`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## Elements\n\n### Nodes\n\n| Extension | Registration Type |\n| --------- | ----------------- |\n| circle    | Circle            |\n| diamond   | Diamond           |\n| ellipse   | Ellipse           |\n| hexagon   | Hexagon           |\n| html      | HTML              |\n| image     | Image             |\n| rect      | Rect              |\n| star      | Star              |\n| donut     | Donut             |\n| triangle  | Triangle          |\n\nUsage:\n\n1. In `GraphOptions.data.nodes[number].type`;\n2. In `GraphOptions.node.type`;\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### Edges\n\n| Extension       | Registration Type  | Description                   |\n| --------------- | ------------------ | ----------------------------- |\n| Cubic           | 'cubic'            | Cubic Bezier Curve            |\n| Line            | 'line'             | /                             |\n| Polyline        | 'polyline'         | /                             |\n| Quadratic       | 'quadratic'        | Quadratic Bezier Curve        |\n| CubicHorizontal | 'cubic-horizontal' | Horizontal Cubic Bezier Curve |\n| CubicVertical   | 'cubic-vertical'   | Vertical Cubic Bezier Curve   |\n| CubicRadial     | 'cubic-radial'     | Radial Cubic Bezier Curve     |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.edges[number].type`;\n2. In `GraphOptions.edge.type`;\n\n### Combos\n\n| Extension   | Registration Type |\n| ----------- | ----------------- |\n| CircleCombo | 'circle'          |\n| RectCombo   | 'rect'            |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.combos[number].type`;\n2. In `GraphOptions.combo.type`;\n\n## Layouts\n\n| Extension           | Registration Type | Description                     |\n| ------------------- | ----------------- | ------------------------------- |\n| AntVDagreLayout     | 'antv-dagre'      | /                               |\n| ComboCombinedLayout | 'combo-combined'  | /                               |\n| CompactBoxLayout    | 'compact-box'     | /                               |\n| ForceAtlas2Layout   | 'force-atlas2'    | /                               |\n| CircularLayout      | 'circular'        | /                               |\n| ConcentricLayout    | 'concentric'      | /                               |\n| D3ForceLayout       | 'd3-force'        | /                               |\n| DagreLayout         | 'dagre'           | /                               |\n| DendrogramLayout    | 'dendrogram'      | /                               |\n| ForceLayout         | 'force'           | /                               |\n| FruchtermanLayout   | 'fruchterman'     | /                               |\n| GridLayout          | 'grid'            | /                               |\n| IndentedLayout      | 'indented'        | /                               |\n| MDSLayout           | 'mds'             | Multidimensional Scaling Layout |\n| MindmapLayout       | 'mindmap'         | /                               |\n| RadialLayout        | 'radial'          | /                               |\n| RandomLayout        | 'random'          | /                               |\n\nUsage:\n\nIn `GraphOptions.layout`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## Palettes\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].palette`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## Themes\n\n| Registration Type |\n| ----------------- |\n| dark              |\n| light             |\n\nUsage:\n\nIn `GraphOptions.theme`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  theme: 'dark',\n});\n```\n\n## Plugins\n\n| Extension      | Registration Type  |\n| -------------- | ------------------ |\n| BubbleSets     | 'bubble-sets'      |\n| EdgeFilterLens | 'edge-filter-lens' |\n| GridLine       | 'grid-line'        |\n| Background     | 'background'       |\n| Contextmenu    | 'contextmenu'      |\n| Fisheye        | 'fisheye'          |\n| Fullscreen     | 'fullscreen'       |\n| History        | 'history'          |\n| Hull           | 'hull'             |\n| Legend         | 'legend'           |\n| Minimap        | 'minimap'          |\n| Snapline       | 'snapline'         |\n| Timebar        | 'timebar'          |\n| Toolbar        | 'toolbar'          |\n| Tooltip        | 'tooltip'          |\n| Watermark      | 'watermark'        |\n\nUsage:\n\nIn `GraphOptions.plugins`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## Transforms\n\n| Extension            | Registration Type        | Description |\n| -------------------- | ------------------------ | ----------- |\n| ProcessParallelEdges | 'process-parallel-edges' | /           |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签    |\n\nUsage:\n\nIn `GraphOptions.transform`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## Shapes\n\n| Registration Type |\n| ----------------- |\n| circle            |\n| ellipse           |\n| group             |\n| html              |\n| image             |\n| line              |\n| path              |\n| polygon           |\n| polyline          |\n| rect              |\n| text              |\n| label             |\n| badge             |\n\nUsage:\n\nIn the [upsert](http://localhost:8000/en/manual/custom-extension/element#methods) method of the element class when customizing the shape, pass the second parameter:\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","isInternal":false,"tokens":2129,"sizeBytes":8521},{"name":"extensions.zh.md","path":"packages/site/docs/manual/graph/extensions.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/extensions.zh.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 内置扩展\norder: 4\n---\n\nG6 内置扩展及注册扩展类型如下：\n\n## 动画\n\n| 扩展          | 注册类型         | 描述     |\n| ------------- | ---------------- | -------- |\n| ComboCollapse | 'combo-collapse' | 组合收起 |\n| ComboExpand   | 'combo-expand'   | 组合展开 |\n| NodeCollapse  | 'node-collapse'  | 节点收起 |\n| NodeExpand    | 'node-expand'    | 节点展开 |\n| PathIn        | 'path-in'        | 路径进入 |\n| PathOut       | 'path-out'       | 路径退出 |\n| Fade          | 'fade'           | 渐变     |\n| Translate     | 'translate'      | 平移     |\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].animation.[stage]` 中使用，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    animation: {\n      update: 'translate', // 更新阶段仅使用平移动画\n    },\n  },\n});\n```\n\n## 交互\n\n| 扩展                      | 注册类型                      | 描述                   |\n| ------------------------- | ----------------------------- | ---------------------- |\n| BrushSelect               | 'brush-select'                | 框选                   |\n| ClickSelect               | 'click-select'                | 点击选中               |\n| CollapseExpand            | 'collapse-expand'             | 展开/收起元素          |\n| CreateEdge                | 'create-edge'                 | 创建边                 |\n| DragCanvas                | 'drag-canvas'                 | 拖拽画布               |\n| DragElementForce          | 'drag-element-force'          | 力导向拖拽元素         |\n| DragElement               | 'drag-element'                | 拖拽元素               |\n| FixElementSize            | 'fix-element-size'            | 缩放画布时固定元素大小 |\n| FocusElement              | 'focus-element'               | 聚焦元素               |\n| HoverActivate             | 'hover-activate'              | 悬停激活               |\n| LassoSelect               | 'lasso-select'                | 套索选择               |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | 操作画布时隐藏元素     |\n| ScrollCanvas              | 'scroll-canvas'               | 滚动画布               |\n| ZoomCanvas                | 'zoom-canvas'                 | 缩放画布               |\n\n配置方式：\n\n在 `GraphOptions.behaviors` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## 元素\n\n### 节点\n\n| 扩展     | 注册类型 | 描述       |\n| -------- | -------- | ---------- |\n| circle   | Circle   | 圆形节点   |\n| diamond  | Diamond  | 菱形节点   |\n| ellipse  | Ellipse  | 椭圆节点   |\n| hexagon  | Hexagon  | 六边形节点 |\n| html     | HTML     | HTML节点   |\n| image    | Image    | 图片节点   |\n| rect     | Rect     | 矩形节点   |\n| star     | Star     | 星形节点   |\n| donut    | Donut    | 甜甜圈节点 |\n| triangle | Triangle | 三角形节点 |\n\n配置方式：\n\n1. 在 `GraphOptions.data.nodes[number].type` 中配置；\n2. 在 `GraphOptions.node.type` 中配置；\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### 边\n\n| 扩展            | 注册类型           | 描述               |\n| --------------- | ------------------ | ------------------ |\n| Cubic           | 'cubic'            | 三次贝塞尔曲线     |\n| Line            | 'line'             | 直线               |\n| Polyline        | 'polyline'         | 折线               |\n| Quadratic       | 'quadratic'        | 二次贝塞尔曲线     |\n| CubicHorizontal | 'cubic-horizontal' | 水平三次贝塞尔曲线 |\n| CubicVertical   | 'cubic-vertical'   | 垂直三次贝塞尔曲线 |\n| CubicRadial     | 'cubic-radial'     | 径向三次贝塞尔曲线 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.edges[number].type` 中配置；\n2. 在 `GraphOptions.edge.type` 中配置；\n\n### 组合\n\n| 扩展        | 注册类型 | 描述     |\n| ----------- | -------- | -------- |\n| CircleCombo | 'circle' | 圆形组合 |\n| RectCombo   | 'rect'   | 矩形组合 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.combos[number].type` 中配置；\n2. 在 `GraphOptions.combo.type` 中配置；\n\n## 布局\n\n| 扩展                | 注册类型         | 描述                   |\n| ------------------- | ---------------- | ---------------------- |\n| AntVDagreLayout     | 'antv-dagre'     | AntV Dagre 布局        |\n| ComboCombinedLayout | 'combo-combined' | 组合布局               |\n| CompactBoxLayout    | 'compact-box'    | 紧凑树                 |\n| ForceAtlas2Layout   | 'force-atlas2'   | ForceAlas2 力导向布局  |\n| CircularLayout      | 'circular'       | 环形布局               |\n| ConcentricLayout    | 'concentric'     | 同心圆布局             |\n| D3ForceLayout       | 'd3-force'       | D3 力导向布局          |\n| DagreLayout         | 'dagre'          | Dagre 布局             |\n| DendrogramLayout    | 'dendrogram'     | 生态树                 |\n| ForceLayout         | 'force'          | 力导向布局             |\n| FruchtermanLayout   | 'fruchterman'    | Fruchterman 力导向布局 |\n| GridLayout          | 'grid'           | 网格布局               |\n| IndentedLayout      | 'indented'       | 缩进树                 |\n| MDSLayout           | 'mds'            | 高维数据降维布局       |\n| MindmapLayout       | 'mindmap'        | 脑图树                 |\n| RadialLayout        | 'radial'         | 径向布局               |\n| RandomLayout        | 'random'         | 随机布局               |\n\n配置方式：\n\n在 `GraphOptions.layout` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## 色板\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].palette` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## 主题\n\n| 注册类型 | 描述     |\n| -------- | -------- |\n| dark     | 深色主题 |\n| light    | 浅色主题 |\n\n配置方式：\n\n在 `GraphOptions.theme` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  theme: 'dark',\n});\n```\n\n## 插件\n\n| 扩展           | 注册类型           | 描述       |\n| -------------- | ------------------ | ---------- |\n| BubbleSets     | 'bubble-sets'      | 气泡集     |\n| EdgeFilterLens | 'edge-filter-lens' | 边过滤镜   |\n| GridLine       | 'grid-line'        | 网格线     |\n| Background     | 'background'       | 背景       |\n| Contextmenu    | 'contextmenu'      | 上下文菜单 |\n| Fisheye        | 'fisheye'          | 鱼眼放大镜 |\n| Fullscreen     | 'fullscreen'       | 全屏展示   |\n| History        | 'history'          | 历史记录   |\n| Hull           | 'hull'             | 轮廓包围   |\n| Legend         | 'legend'           | 图例       |\n| Minimap        | 'minimap'          | 小地图     |\n| Snapline       | 'snapline'         | 对齐线     |\n| Timebar        | 'timebar'          | 时间条     |\n| Toolbar        | 'toolbar'          | 工具栏     |\n| Tooltip        | 'tooltip'          | 提示框     |\n| Watermark      | 'watermark'        | 水印       |\n\n配置方式：\n\n在 `GraphOptions.plugins` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## 数据转换\n\n| 扩展                 | 注册类型                 | 描述     |\n| -------------------- | ------------------------ | -------- |\n| ProcessParallelEdges | 'process-parallel-edges' | 平行边   |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签 |\n\n配置方式：\n\n在 `GraphOptions.transforms` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## 图形\n\n| 注册类型 | 描述   |\n| -------- | ------ |\n| circle   | 圆形   |\n| ellipse  | 椭圆   |\n| group    | 分组   |\n| html     | HTML   |\n| image    | 图片   |\n| line     | 直线   |\n| path     | 路径   |\n| polygon  | 多边形 |\n| polyline | 折线   |\n| rect     | 矩形   |\n| text     | 文本   |\n| label    | 标签   |\n| badge    | 徽标   |\n\n使用方式：\n\n自定义图形时，元素类成员方法 [upsert](/manual/element/node/custom-node) 方法第二个参数传入：\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n","frontmatter":{"title":"内置扩展","order":"4"},"isInternal":false,"tokens":1851,"sizeBytes":8778},{"name":"graph.en.md","path":"packages/site/docs/manual/graph/graph.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/graph.en.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Graph\norder: 0\n---\n\n## Overview\n\n### Definition of Graph\n\nIn Chinese, the character \"图\" (Graph) can often be used to represent many different concepts, such as image,shape,and chart or diagram,etc.\n\nIn Graph Theory, a graph is a mathematical structure used to model pairwise relationships between objects, which we typically represent with nodes (or Vertex) and edges (or Link) to denote the objects and the relationships between them.\n\nThe \"graph\" in G6:\n\n- Conceptually, it is the \"graph\" from Graph Theory, a data structure composed of nodes and edges.\n- Visually, a \"graph\" is a figure composed of a set of graphical elements representing nodes and edges.\n- In terms of code implementation, a \"graph\" is a class capable of transforming data into a graphical display.\n\n### Types of Graph\n\nGraph Theory categorizes graphs into many different types based on their structure and properties, such as:\n\n- Directed Graph and Undirected Graph\n- Weighted Graph and Unweighted Graph\n- Simple Graph and Multigraph\n- Cyclic Graph and Acyclic Graph\n- Connected Graph and Disconnected Graph\n- Complete Graph and Non-Complete Graph\n- Sparse Graph and Dense Graph\n- ...\n\nIn G6, we provide a universal graph representation capable of depicting the various types of graphs mentioned above, for example:\n\n- Directed Graph and Undirected Graph: Defined by the start and end points of the edges.\n- Weighted Graph and Unweighted Graph: Defined by the `weight` data on the edges.\n- Simple Graph and Multigraph: Defined by the uniqueness of the edges.\n- ...\n\n### Use Scenarios\n\nGraphs are a very versatile data structure that can be used to represent a variety of scenarios, such as:\n\n- Social Networks\n- Knowledge Graphs\n- Traffic Networks\n- Power Grids\n\nIn G6, we provide a rich expression capability for graphs that can meet the needs of different scenarios. We also offer a wealth of interactive and animated effects to make the graphs more vivid and intuitive.\n\n## Use G6 Graph\n\nTo create a Graph with G6, you first need to import the `@antv/g6` library, and then instantiate the Graph class.\n\n> For installation instructions, refer to: [Getting Started - Installation](/en/manual/getting-started/installation)\n\nThe Graph class accepts an instantiation argument object, known as **options** (Options, in visualization theory it is referred to as: `Specification`), which is used to configure the graph's data, element styles, layout, interactions, etc.\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  // ... other other options\n});\n```\n\n:::warning{title=note}\nThe instantiation process only configures the basic information of the graph. To render the graph onto the page, you still need to call the `render` method.\n:::\n\n- To learn how to quickly create a graph, please refer to [Quick Start](/en/manual/getting-started/quick-start).\n- For more detailed information about the configuration options, please refer to [Options](/en/manual/graph/option).\n- To gain an in-depth understanding of the concepts within the configuration options, please read the rest of the content in this section.\n","frontmatter":{"title":"Graph","order":"0"},"isInternal":false,"tokens":793,"sizeBytes":3174},{"name":"graph.zh.md","path":"packages/site/docs/manual/graph/graph.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/graph.zh.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Graph - 图\norder: 0\n---\n\n## 什么是 Graph\n\n中文字“图”在大家的传统认知里指的是图画、图像，而图论与可视化中的“图”—— Graph 则有着更精确的定位：主体（objects）与关系（relationships）的组成。它甚至不局限于视觉，主体与关系的数据也可以称为图。\n\n> —— 摘自 [AntV 专栏](https://zhuanlan.zhihu.com/aiux-antv) 文章：[Graph Visualization · 知多少 之 《HelloWorld 图可视化》](https://zhuanlan.zhihu.com/p/83685690)。\n\n在 G6 中，Graph 对象是图的载体，它包含了图上的所有元素（节点、边等），同时挂载了图的相关操作（如交互监听、元素操作、渲染等）。\n\nGraph 对象的完整生命周期包括：\n\n1. **创建**: 通过 `new Graph(options)` 实例化\n2. **初始化**: 在创建时进行内部初始化\n3. **渲染**: 调用 `graph.render()` 进行首次渲染\n4. **更新**: 通过各种 API 更新图的数据和配置\n5. **销毁**: 调用 `graph.destroy()` 销毁实例并释放资源\n\n## 使用 G6 Graph\n\n要使用 G6 创建 Graph，首先需要引入 `@antv/g6` 库，然后实例化 Graph 类。\n\n> 安装教程参考：[开始使用 - 安装](/manual/getting-started/installation)\n\nGraph 类接收一个实例化参数对象，称之为**配置项**(Options，在可视化理论中将其称为：`Specification`)，用于配置图的数据、元素样式、布局、交互等。\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container', // 通过 DOM ID 指定容器\n  width: 800, // 画布宽高（若容器已设尺寸可省略）\n  height: 600,\n  data: {\n    // 初始数据\n    nodes: [{ id: 'start', data: { label: 'Hello G6!' } }],\n  },\n});\n```\n\n:::warning{title=注意}\n实例化过程仅是配置图的基本信息，要将图渲染到页面上，还需要调用 `render` 方法\n:::\n\n## 图配置项\n\n通过下表速查图的配置项，更多类型定义说明和详细用法请参考 [API - 图配置项](/manual/graph/option)。\n\n| 属性             | 类型                               | 默认值      | 描述                                                          |\n| ---------------- | ---------------------------------- | ----------- | ------------------------------------------------------------- |\n| container        | string \\| HTMLElement \\| Canvas    | -           | 图容器，可以是 DOM 元素 ID、DOM 元素实例或 Canvas 实例        |\n| width            | number                             | 容器宽度    | 画布宽度(像素)                                                |\n| height           | number                             | 容器高度    | 画布高度(像素)                                                |\n| autoFit          | 'view' \\| 'center' \\| object       | -           | 自动适配策略，'view'(适应视图)或'center'(居中)                |\n| autoResize       | boolean                            | false       | 是否在窗口大小变化时自动调整画布大小                          |\n| background       | string                             | -           | 画布背景色，也作为导出图片时的背景色                          |\n| canvas           | CanvasConfig                       | -           | 画布配置                                                      |\n| cursor           | Cursor                             | `'default'` | 指针样式                                                      |\n| devicePixelRatio | number                             | 2           | 设备像素比                                                    |\n| padding          | number \\| number[]                 | -           | 画布内边距，在自适应时会根据内边距进行适配                    |\n| renderer         | (layer: string) => IRenderer       | -           | 手动指定渲染器                                                |\n| rotation         | number                             | 0           | 旋转角度(弧度)                                                |\n| zoom             | number                             | 1           | 缩放比例                                                      |\n| zoomRange        | [number, number]                   | [0.01, 10]  | 缩放比例的限制范围                                            |\n| x                | number                             | -           | 视口 x 坐标                                                   |\n| y                | number                             | -           | 视口 y 坐标                                                   |\n| data             | GraphData                          | -           | 图数据，详见 [数据](/manual/data)                             |\n| node             | NodeOptions                        | -           | 节点全局配置，详见 [节点](/manual/element/node/overview)      |\n| edge             | EdgeOptions                        | -           | 边全局配置，详见 [边](/manual/element/edge/overview)          |\n| combo            | ComboOptions                       | -           | 组合全局配置，详见 [组合](/manual/element/combo/overview)     |\n| animation        | boolean \\| AnimationEffectTiming   | -           | 全局动画配置，详见 [动画](/manual/animation/animation)        |\n| theme            | string \\| false                    | `'light'`   | 主题配置，支持 `'light'`、`'dark'` 或自定义主题名             |\n| layout           | LayoutOptions \\| LayoutOptions[]   | -           | 布局配置，详见 [布局](/manual/layout/overview)                |\n| behaviors        | (string \\| CustomBehaviorOption)[] | -           | 交互行为配置，详见 [交互](/manual/behavior/overview)          |\n| plugins          | (string \\| CustomPluginOption)[]   | -           | 插件配置，详见 [插件](/manual/plugin/overview)                |\n| transforms       | TransformOptions                   | -           | 数据转换器配置，详见 [数据转换器](/manual/transform/overview) |\n\n## 图属性\n\n图实例提供了一些只读属性，用于获取图的状态信息：\n\n| 属性      | 类型    | 描述                     |\n| --------- | ------- | ------------------------ |\n| destroyed | boolean | 当前图实例是否已被销毁   |\n| rendered  | boolean | 当前图实例是否已完成渲染 |\n\n## 参考示例\n\n### 完整的创建和配置示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\ngraph.render();\n```\n\n```typescript\nimport { Graph } from '@antv/g6';\n\n// 创建图实例\nconst graph = new Graph({\n  // 基础配置\n  container: 'container',\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\n// 渲染图\ngraph.render();\n```\n\n- 要了解如何快速创建一个图，请参考[快速上手](/manual/getting-started/quick-start)。\n- 要深入了解配置项中个部分的概念，请阅读本章节的其他内容。\n","frontmatter":{"title":"Graph - 图","order":"0"},"isInternal":false,"tokens":1731,"sizeBytes":8718},{"name":"option.en.md","path":"packages/site/docs/manual/graph/option.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/option.en.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Options\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\nWhether to automatically fit the canvas. ⚠️ **Note**: Each time `render` is executed, it will adapt according to `autoFit`.\n\nTwo basic adaptation modes:\n\n- `'view'` - Automatically scale to ensure all content is visible within the view\n- `'center'` - Center the content without changing the zoom level\n\nMore precise adaptation control can be achieved through object form:\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // Adaptation type: 'view' or 'center'\n    options: {\n      // Only applicable to 'view' type\n      when: 'overflow', // When to adapt: 'overflow' (only when content overflows) or 'always' (always adapt)\n      direction: 'x', // Adaptation direction: 'x', 'y', or 'both'\n    },\n    animation: {\n      // Adaptation animation effect\n      duration: 1000, // Animation duration (milliseconds)\n      easing: 'ease-in-out', // Animation easing function\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| Property  | Description                                                                                                                                                             | Type                       | Default    | Required |\n| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | -------- |\n| when      | Adaptation occurs under the following conditions <br/> - `'overflow'` adapt only when content overflows <br/> - `'always'` always adapt                                 | `'overflow'` \\| `'always'` | `'always'` |          |\n| direction | Adapt only in the specified direction <br/> - `'x'` adapt only in x direction <br/> - `'y'` adapt only in y direction <br/> - `'both'` adapt in both x and y directions | `'x'` \\| `'y'` \\| `'both'` | `'both'`   |          |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## autoResize\n\n> _boolean_ **Default:** `false`\n\nWhether to automatically resize the canvas.\n\nImplemented based on the `window.onresize` event. When the browser window size changes, the canvas will automatically resize to fit the container.\n\n## background\n\n> _string_\n\nCanvas background color.\n\nThis color is used as the background color when exporting images. Any valid CSS color value can be used, such as hexadecimal, RGB, RGBA, etc.\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\nCanvas configuration. Related configuration items under GraphOptions (such as `container`, `width`, `height`, `devicePixelRatio`, `background`, `cursor`) are shortcut configuration items and will be converted to canvas configuration items.\n\n#### CanvasConfig\n\n| Property         | Description                                                                                | Type                                                                           | Default | Required |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------- | -------- |\n| container        | Canvas container                                                                           | string \\| HTMLElement                                                          | -       |          |\n| devicePixelRatio | Device pixel ratio                                                                         | number                                                                         | -       |          |\n| width            | Canvas width                                                                               | number                                                                         | -       |          |\n| height           | Canvas height                                                                              | number                                                                         | -       |          |\n| cursor           | Cursor style, same as [GraphOptions.cursor](#cursor)                                       | string                                                                         | -       |          |\n| background       | Canvas background color                                                                    | string                                                                         | -       |          |\n| renderer         | Renderer, same as [GraphOptions.renderer](#renderer)                                       | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -       |          |\n| enableMultiLayer | Whether to enable multi-layer. Non-dynamic parameter, effective only during initialization | boolean                                                                        | -       |          |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\nCanvas container, can be one of the following three assignments:\n\n- ID string of the DOM element, such as `'container'`\n- HTML element object, such as `document.getElementById('container')`\n- Canvas instance, such as `new Canvas(options)`, where `options` is of type [CanvasConfig](#canvasconfig).\n\n## cursor\n\n> string\n\nCursor style, controls the cursor shape when hovering over the canvas. Any valid CSS cursor value can be used.\n\nSupported values include: `'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'.\n\nCursor values are referenced from [MDN - cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n\n## devicePixelRatio\n\n> _number_\n\nDevice pixel ratio.\n\nUsed for high-definition screens, the default is [window.devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio).\n\n## width\n\n> _number_\n\nCanvas width. If not set, the container width will be automatically obtained.\n\n## height\n\n> _number_\n\nCanvas height. If not set, the container height will be automatically obtained.\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\nManually specify the renderer\n\nG6 uses a layered rendering approach, divided into four layers: `background`, `main`, `label`, `transient`. Users can set the renderer for each layer of the canvas through this configuration item.\n\n**Example**: Use SVG renderer for rendering\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\nCanvas padding\n\nUsually, during adaptation, it will be adapted according to the padding. It can be a single value (same padding on all sides) or an array form (specify the padding for top, right, bottom, left in order).\n\n**Example:**\n\n```javascript\n// Single value\nconst graph1 = new Graph({\n  padding: 20, // 20 pixels of padding on all sides\n});\n\n// Array form\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // Padding for top, right, bottom, left\n});\n```\n\n## rotation\n\n> _number_ **Default:** `0`\n\nRotation angle (in radians)\n\n## x\n\n> _number_\n\nViewport x coordinate, sets the initial horizontal position of the viewport.\n\n## y\n\n> _number_\n\nViewport y coordinate, sets the initial vertical position of the viewport.\n\n## zoom\n\n> _number_ **Default:** `1`\n\nSets the initial zoom level of the viewport, 1 means 100% (original size).\n\n## zoomRange\n\n> _[number, number]_ **Default:** `[0.01, 10]`\n\nZoom range, limits the minimum and maximum scale that users can zoom.\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\nEnable or disable global animation\n\nWhen configured as an animation option, animation will be enabled, and this animation configuration will be used as the base configuration for global animation.\n\n#### AnimationEffectTiming\n\n| Property   | Description                    | Type                                                                | Default     | Required |\n| ---------- | ------------------------------ | ------------------------------------------------------------------- | ----------- | -------- |\n| delay      | Animation delay time           | number                                                              | -           |          |\n| direction  | Animation direction            | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |          |\n| duration   | Animation duration             | number                                                              | -           |          |\n| easing     | Animation easing function      | string                                                              | -           |          |\n| fill       | Fill mode after animation ends | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |          |\n| iterations | Animation iteration count      | number                                                              | -           |          |\n\n**Example:**\n\n```javascript\n// Simple enable\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// Detailed configuration\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // Animation duration (milliseconds)\n    easing: 'ease-in-out', // Easing function\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\nData.\n\n#### GraphData\n\n| Property | Description | Type                      | Default | Required |\n| -------- | ----------- | ------------------------- | ------- | -------- |\n| nodes    | Node data   | [NodeData](#nodedata)[]   | -       | ✓        |\n| edges    | Edge data   | [EdgeData](#edgedata)[]   | -       | ✓        |\n| combos   | Combo data  | [ComboData](#combodata)[] | -       | ✓        |\n\n#### NodeData\n\n| Property | Description                                                                                                                                         | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                                 | string         | -       | ✓        |\n| type     | Node type, built-in node type name or custom node name                                                                                              | string         | -       |          |\n| data     | Node data, used to store custom data for the node, such as node name, description, etc. Can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Node style, including visual attributes such as position, size, color, etc.                                                                         | object         | -       |          |\n| states   | Initial state of the node, such as selected, activated, hovered, etc.                                                                               | string[]       | -       |          |\n| combo    | ID of the combo to which it belongs, used to organize the hierarchical relationship of nodes, if none, it is null                                   | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                                     | string[]       | -       |          |\n\n#### EdgeData\n\n| Property | Description                                                                                                    | Type     | Default | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source   | Starting node ID of the edge                                                                                   | string   | -       | ✓        |\n| target   | Target node ID of the edge                                                                                     | string   | -       | ✓        |\n| id       | Unique identifier for the edge                                                                                 | string   | -       |          |\n| type     | Edge type, built-in edge type name or custom edge name                                                         | string   | -       |          |\n| data     | Edge data, used to store custom data for the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style    | Edge style, including visual attributes such as line color, width, arrow, etc.                                 | object   | -       |          |\n| states   | Initial state of the edge                                                                                      | string[] | -       |          |\n\n#### ComboData\n\n| Property | Description                                                                                                      | Type           | Default | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the combo                                                                                  | string         | -       | ✓        |\n| type     | Combo type, built-in combo type name or custom combo name                                                        | string         | -       |          |\n| data     | Combo data, used to store custom data for the combo, can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Combo style                                                                                                      | object         | -       |          |\n| states   | Initial state of the combo                                                                                       | string[]       | -       |          |\n| combo    | Parent combo ID. If there is no parent combo, it is null                                                         | string \\| null | -       |          |\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- Read [Data](/en/manual/data) to learn more about graph data, including but not limited to data formats, how to manipulate data, etc.\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\nNode configuration options.\n\n#### NodeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default  | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name                           | [Type](/en/manual/element/node/base-node#type)           | `circle` |          |\n| style     | Node style, including color, size, etc.                                          | [Style](/en/manual/element/node/base-node#style)         | -        |          |\n| state     | Define the style of the node in different states                                 | [State](/en/manual/element/node/base-node#state)         | -        |          |\n| palette   | Define the color palette of the node, used to map colors based on different data | [Palette](/en/manual/element/node/base-node#palette)     | -        |          |\n| animation | Define the animation effect of the node                                          | [Animation](/en/manual/element/node/base-node#animation) | -        |          |\n\nSee [Node](/en/manual/element/node/base-node) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {\n      fill: '#e6f7ff', // Fill color\n      stroke: '#91d5ff', // Border color\n      lineWidth: 1, // Border width\n      r: 20, // Radius\n      labelText: (d) => d.id, // Label text\n    },\n    // Node state style\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\nEdge configuration options\n\n#### EdgeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name                           | [Type](/en/manual/element/edge/base-edge#type)           | `line`  |          |\n| style     | Edge style, including color, size, etc.                                          | [Style](/en/manual/element/edge/base-edge#style)         | -       |          |\n| state     | Define the style of the edge in different states                                 | [State](/en/manual/element/edge/base-edge#state)         | -       |          |\n| palette   | Define the color palette of the edge, used to map colors based on different data | [Palette](/en/manual/element/edge/base-edge#palette)     | -       |          |\n| animation | Define the animation effect of the edge                                          | [Animation](/en/manual/element/edge/base-edge#animation) | -       |          |\n\nSee [Edge](/en/manual/element/edge/base-edge) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // Edge type\n    style: {\n      stroke: '#91d5ff', // Edge color\n      lineWidth: 2, // Edge width\n      endArrow: true, // Whether there is an arrow\n    },\n    // Edge state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\nCombo configuration options\n\n| Property  | Description                                                                       | Type                                                       | Default  | Required |\n| --------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name                         | [Type](/en/manual/element/combo/base-combo#type)           | `circle` |          |\n| style     | Combo style, including color, size, etc.                                          | [Style](/en/manual/element/combo/base-combo#style)         | -        |          |\n| state     | Define the style of the combo in different states                                 | [State](/en/manual/element/combo/base-combo#state)         | -        |          |\n| palette   | Define the color palette of the combo, used to map colors based on different data | [Palette](/en/manual/element/combo/base-combo#palette)     | -        |          |\n| animation | Define the animation effect of the combo                                          | [Animation](/en/manual/element/combo/base-combo#animation) | -        |          |\n\nSee [Combo](/en/manual/element/combo/base-combo) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {\n      fill: '#f0f0f0', // Background color\n      stroke: '#d9d9d9', // Border color\n      lineWidth: 1, // Border width\n    },\n    // Combo state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\nLayout configuration options, can be an object (normal layout) or an array (pipeline layout).\n\n**Example**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // Force-directed layout\n    preventOverlap: true, // Prevent node overlap\n    nodeStrength: -50, // Repulsion between nodes\n    edgeStrength: 0.5, // Elastic coefficient of edges\n    iterations: 200, // Number of iterations\n    animation: true, // Enable layout animation\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\nSet the theme of the chart, can be the built-in `'light'`, `'dark'` theme, or the name of a custom theme. Set to `false` to use no theme.\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure the interaction behaviors of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // Enable canvas dragging with default configuration\n    'zoom-canvas', // Enable canvas zooming with default configuration\n    {\n      type: 'drag-element', // Custom configuration for dragging elements\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // Only allow dragging nodes\n    },\n    function () {\n      console.log(this); // Output graph instance\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- View [Interaction Overview](/en/manual/behavior/overview) to learn more about interaction principles\n- Browse [Built-in Interactions](/en/manual/behavior/auto-adapt-label) to get a list of all built-in interactions and their configuration options\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nSet the plugins of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // Enable minimap with default configuration\n    {\n      type: 'grid', // Enable grid background\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // Enable toolbar\n      key: 'graph-toolbar',\n      position: 'top-right', // Position\n    },\n  ],\n});\n```\n\n- View [Plugin Overview](/en/manual/plugin/overview) to learn more about plugin principles\n- Browse [Built-in Plugins](/en/manual/plugin/background) to get a list of all built-in plugins and their configuration options\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure data processing, used to process data before rendering, does not affect the original data. Can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // Process parallel edges with default configuration\n    {\n      type: 'map-node-size', // Map node size based on node data\n      field: 'value', // Use the value of the field\n      max: 50, // Maximum radius\n      min: 20, // Minimum radius\n    },\n  ],\n});\n```\n\n- View [Data Processing Overview](/en/manual/transform/overview) to learn more about data processing principles\n- Browse [Built-in Data Processing](/en/manual/transform/map-node-size) to get a list of all built-in data processing and their configuration options\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** Extension type */\n  type: string;\n  /** Extension key, i.e., unique identifier */\n  key?: string;\n}\n```\n","frontmatter":{"title":"Options","order":"0"},"isInternal":false,"tokens":6341,"sizeBytes":25379},{"name":"option.zh.md","path":"packages/site/docs/manual/graph/option.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/graph/option.zh.md","title":"Graph Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Options 配置项\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\n是否自动适应画布。⚠️ **注意**：每次执行 `render` 时，都会根据 `autoFit` 进行自适应。\n\n两种基本自适应模式：\n\n- `'view'` - 自动缩放，确保所有内容都在视图内可见\n- `'center'` - 内容居中显示，但不改变缩放比例\n\n还可通过对象形式实现更精细的自适应控制：\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // 自适应类型：'view' 或 'center'\n    options: {\n      // 仅适用于 'view' 类型\n      when: 'overflow', // 何时适配：'overflow'(仅当内容溢出时) 或 'always'(总是适配)\n      direction: 'x', // 适配方向：'x'、'y' 或 'both'\n    },\n    animation: {\n      // 自适应动画效果\n      duration: 1000, // 动画持续时间(毫秒)\n      easing: 'ease-in-out', // 动画缓动函数\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| 属性      | 描述                                                                                                           | 类型                       | 默认值     | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | ---- |\n| when      | 在以下情况下进行适配 <br/> - `'overflow'` 仅当图内容超出视口时进行适配 <br/> - `'always'` 总是进行适配         | `'overflow`' \\| `'always'` | `'always'` |      |\n| direction | 仅对指定方向进行适配 <br/> - `'x'` 仅适配 x 方向 <br/> - `'y'` 仅适配 y 方向 <br/> - `'both'` 适配 x 和 y 方向 | `'x`' \\| `'y`' \\| `'both'` | `'both'`   |      |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## autoResize\n\n> _boolean_ **默认值:** `false`\n\n是否自动调整画布大小。\n\n基于 `window.onresize` 事件实现。当浏览器窗口大小变化时，画布将自动调整大小以适应容器。\n\n## background\n\n> _string_\n\n画布背景色。\n\n该颜色作为导出图片时的背景色。可以使用任何有效的 CSS 颜色值，如十六进制、RGB、RGBA 等。\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\n画布配置。GraphOptions 下相关配置项（如 `container`、`width`、`height`、`devicePixelRatio`、`background`、`cursor`）为快捷配置项，会被转换为 canvas 配置项。\n\n#### CanvasConfig\n\n| 属性             | 描述                                                   | 类型                                                                           | 默认值 | 必填 |\n| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------ | ------ | ---- |\n| container        | 画布容器                                               | string \\| HTMLElement                                                          | -      |      |\n| devicePixelRatio | 设备像素比                                             | number                                                                         | -      |      |\n| width            | 画布宽度                                               | number                                                                         | -      |      |\n| height           | 画布高度                                               | number                                                                         | -      |      |\n| cursor           | 指针样式，与 [GraphOptions.cursor](#cursor) 配置相同   | string                                                                         | -      |      |\n| background       | 画布背景色                                             | string                                                                         | -      |      |\n| renderer         | 渲染器，与 [GraphOptions.renderer](#renderer) 配置相同 | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -      |      |\n| enableMultiLayer | 是否启用多图层。非动态参数，仅在初始化时生效           | boolean                                                                        | -      |      |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\n画布容器，可以是以下三种赋值之一：\n\n- DOM 元素的 ID 字符串，如 `'container'`\n- HTML 元素对象，如 `document.getElementById('container')`\n- Canvas 实例，如 `new Canvas(options)`，其中 `options` 为 [CanvasConfig](#canvasconfig) 类型。\n\n## cursor\n\n> string\n\n指针样式，控制鼠标悬停在画布上时的光标形状。可以使用任何有效的 CSS cursor 值。\n\n支持的值有： `'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'`。\n\n这里的 Cursor 值参考 [MDN - cursor](https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor)。\n\n## devicePixelRatio\n\n> _number_\n\n设备像素比。\n\n用于高清屏的设备像素比，默认为 [window.devicePixelRatio](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio)。\n\n## width\n\n> _number_\n\n画布宽度。如果未设置，则会自动获取容器宽度。\n\n## height\n\n> _number_\n\n画布高度。如果未设置，则会自动获取容器高度。\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\n手动指定渲染器\n\nG6 采用了分层渲染的方式，分为 `background`、`main`、`label`、`transient` 四层，用户可以通过该配置项分别设置每层画布的渲染器。\n\n**示例**: 使用 SVG 渲染器进行渲染\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\n画布内边距\n\n通常在自适应时，会根据内边距进行适配。可以是单个数值（四边相同）或者数组形式（按顺序指定上、右、下、左的内边距）。\n\n**示例：**\n\n```javascript\n// 单个数值\nconst graph1 = new Graph({\n  padding: 20, // 四边均为 20 像素的内边距\n});\n\n// 数组形式\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // 上、右、下、左的内边距\n});\n```\n\n## rotation\n\n> _number_ **默认值:** `0`\n\n旋转角度（以弧度为单位）\n\n## x\n\n> _number_\n\n视口 x 坐标，设置视口的初始水平位置。\n\n## y\n\n> _number_\n\n视口 y 坐标，设置视口的初始垂直位置。\n\n## zoom\n\n> _number_ **默认值:** `1`\n\n设置视口的初始缩放级别，1 表示 100%（原始大小）。\n\n## zoomRange\n\n> _[number, number]_ **默认值:** `[0.01, 10]`\n\n缩放范围，限制用户可以缩放的最小和最大比例。\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\n启用或关闭全局动画\n\n为动画配置项时，会启用动画，并将该动画配置作为全局动画的基础配置。\n\n#### AnimationEffectTiming\n\n| 属性       | 描述                 | 类型                                                                | 默认值      | 必选 |\n| ---------- | -------------------- | ------------------------------------------------------------------- | ----------- | ---- |\n| delay      | 动画延迟时间         | number                                                              | -           |      |\n| direction  | 动画方向             | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |      |\n| duration   | 动画持续时间         | number                                                              | -           |      |\n| easing     | 动画缓动函数         | string                                                              | -           |      |\n| fill       | 动画结束后的填充模式 | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |      |\n| iterations | 动画迭代次数         | number                                                              | -           |      |\n\n**示例：**\n\n```javascript\n// 简单启用\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// 详细配置\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // 动画持续时间（毫秒）\n    easing: 'ease-in-out', // 缓动函数\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\n数据。\n\n#### GraphData\n\n| 属性   | 描述     | 类型                      | 默认值 | 必选 |\n| ------ | -------- | ------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#nodedata)[]   | -      | ✓    |\n| edges  | 边数据   | [EdgeData](#edgedata)[]   | -      | ✓    |\n| combos | 组合数据 | [ComboData](#combodata)[] | -      | ✓    |\n\n#### NodeData\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n#### EdgeData\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n#### ComboData\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- 阅读 [数据](/manual/data) 深入了解图数据，包括不限于数据格式、如何操作数据等。\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\n节点配置项。\n\n#### NodeOptions\n\n| 属性      | 描述                                         | 类型                                                  | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------------------------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](/manual/element/node/base-node#type)           | `circle` |      |\n| style     | 节点样式，包括颜色、大小等                   | [Style](/manual/element/node/base-node#style)         | -        |      |\n| state     | 定义节点在不同状态下的样式                   | [State](/manual/element/node/base-node#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/node/base-node#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](/manual/element/node/base-node#animation) | -        |      |\n\n详见 [Node](/manual/element/node/base-node)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {\n      fill: '#e6f7ff', // 填充色\n      stroke: '#91d5ff', // 边框色\n      lineWidth: 1, // 边框宽度\n      r: 20, // 半径\n      labelText: (d) => d.id, // 标签文本\n    },\n    // 节点状态样式\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\n边配置项\n\n#### EdgeOptions\n\n| 属性      | 描述                                   | 类型                                                  | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------------------------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](/manual/element/edge/base-edge#type)           | `line` |      |\n| style     | 边样式，包括颜色、大小等               | [Style](/manual/element/edge/base-edge#style)         | -      |      |\n| state     | 定义边在不同状态下的样式               | [State](/manual/element/edge/base-edge#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](/manual/element/edge/base-edge#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](/manual/element/edge/base-edge#animation) | -      |      |\n\n详见 [Edge](/manual/element/edge/base-edge)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // 边类型\n    style: {\n      stroke: '#91d5ff', // 边的颜色\n      lineWidth: 2, // 边的宽度\n      endArrow: true, // 是否有箭头\n    },\n    // 边的状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\n组合配置项\n\n| 属性      | 描述                                         | 类型                                                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ------------------------------------------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](/manual/element/combo/base-combo#type)           | `circle` |      |\n| style     | 组合样式，包括颜色、大小等                   | [Style](/manual/element/combo/base-combo#style)         | -        |      |\n| state     | 定义组合在不同状态下的样式                   | [State](/manual/element/combo/base-combo#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/combo/base-combo#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](/manual/element/combo/base-combo#animation) | -        |      |\n\n详见 [Combo](/manual/element/combo/base-combo)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {\n      fill: '#f0f0f0', // 背景色\n      stroke: '#d9d9d9', // 边框色\n      lineWidth: 1, // 边框宽度\n    },\n    // 组合状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\n布局配置项，可以是对象（普通布局）或数组（流水线布局）。\n\n**示例**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // 力导向布局\n    preventOverlap: true, // 防止节点重叠\n    nodeStrength: -50, // 节点之间的斥力\n    edgeStrength: 0.5, // 边的弹性系数\n    iterations: 200, // 迭代次数\n    animation: true, // 启用布局动画\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\n设置图表的主题，可以是内置的 `'light'`、`'dark'` 主题，也可以是自定义主题的名称。设为 `false` 则不使用任何主题。\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置图表的交互行为，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // 使用默认配置启用画布拖拽\n    'zoom-canvas', // 使用默认配置启用画布缩放\n    {\n      type: 'drag-element', // 自定义配置拖拽元素\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // 只允许拖拽节点\n    },\n    function () {\n      console.log(this); // 输出 graph 实例\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- 查看 [交互总览](/manual/behavior/overview) 深入了解交互原理\n- 浏览 [内置交互](/manual/behavior/auto-adapt-label) 获取所有内置交互列表及其配置选项\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n设置图表的插件，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // 启用小地图，使用默认配置\n    {\n      type: 'grid', // 启用网格背景\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // 启用工具栏\n      key: 'graph-toolbar',\n      position: 'top-right', // 位置\n    },\n  ],\n});\n```\n\n- 查看 [插件总览](/manual/plugin/overview) 深入了解插件原理\n- 浏览 [内置插件](/manual/plugin/background) 获取所有内置插件列表及其配置项\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置数据处理，用于在渲染前对数据进行处理，不会影响原始数据。可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // 处理平行边，使用默认配置\n    {\n      type: 'map-node-size', // 根据节点数据映射节点大小\n      field: 'value', // 使用 value 字段的值\n      max: 50, // 最大半径\n      min: 20, // 最小半径\n    },\n  ],\n});\n```\n\n- 查看 [数据处理总览](/manual/transform/overview) 深入了解数据处理原理\n- 浏览 [内置数据处理](/manual/transform/map-node-size) 获取所有内置数据处理列表及其配置项\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** 拓展类型 */\n  type: string;\n  /** 拓展 key，即唯一标识 */\n  key?: string;\n}\n```\n","frontmatter":{"title":"Options 配置项","order":"0"},"isInternal":false,"tokens":4356,"sizeBytes":22095},{"name":"introduction.en.md","path":"packages/site/docs/manual/introduction.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/introduction.en.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Introduction\norder: 0\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 is a graph visualization engine. It provides capabilities for graph drawing, layout, analysis, interaction, animation, and other aspects of graph visualization. It aims to offer developers a set of tools that are easy to use, professionally reliable, and highly customizable for graph visualization development.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Rich Elements</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ elements to meet the needs of common scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Flexible Interactions</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ interactions that can be freely combined according to different scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High-Performance Layout Algorithms</h4>\n\n<p style=\"text-align: center;\">High-performance layouts, built-in 10+ common graph layouts, with support for WebGPU and WASM computational acceleration.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Multicolor Themes for Various Scenarios</h4>\n\n<p style=\"text-align: center;\"><img height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D Scenes</h4>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">Supports 3D elements and layouts to create immersive graph visualization scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High Customizability</h4>\n\n<p style=\"text-align: center;\">Elements, layouts, interactions, and plugins are all customizable, enabling every creative idea you have.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Start Your G6 Journey in Just 3 Minutes</h4>\n\n<p style=\"text-align: center;\">Click to enter 👉 <a href=\"/manual/getting-started/quick-start\">Quick Start</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","frontmatter":{"title":"Introduction","order":"0"},"isInternal":false,"tokens":1178,"sizeBytes":4714},{"name":"introduction.zh.md","path":"packages/site/docs/manual/introduction.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/introduction.zh.md","title":"Manual Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 简介\norder: 0\nsidebar: false\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 是一个图可视化引擎。它提供了图的绘制、布局、分析、交互、动画等图可视化能力。旨在为开发者提供一套简单易用、专业可靠、可高度定制的图可视化开发工具</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">丰富元素</h4>\n\n<p style=\"text-align: center;\">内置 10+ 元素，满足常规场景需求</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">灵活交互</h4>\n\n<p style=\"text-align: center;\">内置 10+ 交互，并可根据不同场景自由组合</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高性能布局算法</h4>\n\n<p style=\"text-align: center;\">高性能布局，内置 10+ 常用的图布局，支持 WebGPU、 WASM 计算加速</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">多色主题，适用多种场景</h4>\n\n<p style=\"text-align: center;\"><image height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D 场景</h4>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">支持 3D 元素、布局，打造沉浸式的图可视化场景</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高可定制性</h4>\n\n<p style=\"text-align: center;\">元素、布局、交互、插件统统可定制，实现你的每一个创意</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">仅需 3 分钟，开启 G6 之旅</h4>\n\n<p style=\"text-align: center;\">点击进入👉 <a href=\"/manual/getting-started/quick-start\">快速开始</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n","frontmatter":{"title":"简介","order":"0","sidebar":false},"isInternal":false,"tokens":1005,"sizeBytes":4463},{"name":"AntvDagreLayout.en.md","path":"packages/site/docs/manual/layout/AntvDagreLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/AntvDagreLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: AntvDagre Layout\norder: 2\n---\n\n## Overview\n\nAntvDagre builds upon the original [dagre](https://github.com/dagrejs/dagre/wiki) layout and adds more useful options, such as `nodeOrder`, `edgeLabelSpace`, and more. The `dagre` layout itself is a hierarchical layout suitable for directed acyclic graphs (DAGs), which can automatically handle node direction and spacing, and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## Options\n\n> For more native `dagre` options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout). Here, only some core and new options are listed.\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Diagram\" />\n\n| Property       | Description                                                                                                                                                                                        | Type                                                | Default | Required |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------- | -------- |\n| type           | Layout type                                                                                                                                                                                        | `antv-dagre`                                        | -       | ✓        |\n| rankdir        | Layout direction, options                                                                                                                                                                          | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`    |          |\n| align          | Node alignment, options                                                                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`    |          |\n| nodesep        | Node spacing (px). For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing.                                                                                             | number                                              | 50      |          |\n| nodesepFunc    | Callback for node spacing (px), allows different spacing for different nodes. For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing. Takes precedence over `nodesep`. | (d?: Node) => number                                |         |          |\n| ranksep        | Rank spacing (px). For `TB` or `BT`, it's vertical spacing between adjacent ranks; for `LR` or `RL`, it's horizontal spacing.                                                                      | number                                              | 50      |          |\n| ranksepFunc    | Callback for rank spacing (px), allows different spacing for different ranks. For `TB` or `BT`, it's vertical spacing; for `LR` or `RL`, it's horizontal spacing. Takes precedence over `ranksep`. | (d?: Node) => number                                |         |          |\n| ranker         | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                                                                         | `network-simplex` \\| `tight-tree` \\| `longest-path` | -       |          |\n| nodeSize       | Specify node size for all nodes or each node, used for occupying space and spacing calculation                                                                                                     | Size \\| ((nodeData: Node) => Size)                  | -       |          |\n| controlPoints  | Whether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that consumes `style.controlPoints` as control points                 | boolean                                             | false   |          |\n| begin          | Top-left alignment position of the layout                                                                                                                                                          | [number, number] \\| [number, number, number]        | -       |          |\n| sortByCombo    | Whether to sort nodes in the same rank based on `parentId` in each node's data to avoid Combo overlap                                                                                              | boolean                                             | false   |          |\n| edgeLabelSpace | Whether to reserve space for edge labels                                                                                                                                                           | boolean                                             | true    |          |\n| nodeOrder      | Reference array for node order in the same rank, storing node ids                                                                                                                                  | string[]                                            | -       |          |\n| radial         | Whether to use radial layout based on `dagre`                                                                                                                                                      | boolean                                             | -       |          |\n| focusNode      | Focus node, only effective when `radial` is true                                                                                                                                                   | ID \\| Node \\| null                                  | -       |          |\n| preset         | Reference node positions for layout calculation, usually used to keep transitions smooth when switching data                                                                                       | NodeData[]                                          | -       |          |\n\n> Note: In G6, the control points computed by `antv-dagre` are written into `edge.style.controlPoints`.\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\nNode alignment: U = upper, D = down, L = left, R = right\n\n- `UL`: align to upper left\n- `UR`: align to upper right\n- `DL`: align to lower left\n- `DR`: align to lower right\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\nLayout direction. T = top, B = bottom, L = left, R = right\n\n- `TB`: top to bottom\n- `BT`: bottom to top\n- `LR`: left to right\n- `RL`: right to left\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\nLayout mode\n\n### ranksep\n\n> _number_ **Default:** 50\n\nRank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. `ranksepFunc` has higher priority.\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\nCallback for rank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. Takes precedence over nodesep if set.\n\n### nodesep\n\n> _number_ **Default:** 50\n\nNode spacing (px)\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. `nodesepFunc` has higher priority.\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\nCallback for node spacing (px), allows different spacing for different nodes\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. Takes precedence over nodesep if set.\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\nTop-left alignment position of the layout\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\nWhether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that uses `style.controlPoints` as control points. Adds `style.controlPoints` to edge data.\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\nWhether to reserve space for edge labels\n\nThis affects whether a dummy node is added in the middle of the edge.\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\nFocus node, only effective when `radial` is true\n\n- ID: node id\n- Node: node instance\n- null: cancel focus\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\nReference array for node order in the same rank, stores node ids\n\nIf not specified, dagre's default order is used.\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\nSpecify node size for all or each node.\n\nUsed for collision detection to prevent node overlap\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\nReference node positions for layout calculation\n\nUsually for smooth transitions when switching data. In G6, if updating data, the existing layout result is used as input.\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout based on dagre\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\nWhether to sort nodes in the same rank by their parentId to prevent Combo overlap\n\nRecommended to enable when using Combo\n\n## Suitable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, node direction and spacing are automatically handled\n- **Dependency Graphs**: Display dependencies between packages or modules\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks\n\n## Related Documentation\n\n> The following documents can help you better understand the Dagre layout\n\n- [Graph Layout Algorithms: In-depth Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","frontmatter":{"title":"AntvDagre Layout","order":"2"},"isInternal":false,"tokens":2583,"sizeBytes":10332},{"name":"AntvDagreLayout.zh.md","path":"packages/site/docs/manual/layout/AntvDagreLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/AntvDagreLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: AntV Dagre 布局 AntvDagre\norder: 2\n---\n\n## 概述\n\nAntvDagre 在原先[dagre](https://github.com/dagrejs/dagre/wiki)布局的基础上增加了更多有用的设置项，比如`nodeOrder`、`edgeLabelSpace`等等。 `dagre`布局本身一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## 配置项\n\n> 更多`dagre`原生配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)，这里仅列出部分核心配置和新增的配置\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性           | 描述                                                                                                                                               | 类型                                                | 默认值 | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------ | ---- |\n| type           | 布局类型                                                                                                                                           | `antv-dagre`                                        | -      | ✓    |\n| rankdir        | 布局方向，可选值                                                                                                                                   | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`   |      |\n| align          | 节点对齐方式，可选值                                                                                                                               | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`   |      |\n| nodesep        | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                                 | number                                              | 50     |      |\n| nodesepFunc    | 节点间距（px）的回调函数，优先级高于 `nodesep`                                                                                                     | (d?: Node) => number                                | -      |      |\n| ranksep        | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                               | number                                              | 50     |      |\n| ranksepFunc    | 层间距（px）的回调函数，优先级高于 `ranksep`                                                                                                       | (d?: Node) => number                                | -      |      |\n| ranker         | 为每个节点分配等级的算法，共支持三种算法：`longest-path`、`tight-tree`、`network-simplex`                                                          | `network-simplex` \\| `tight-tree` \\| `longest-path` | -      |      |\n| nodeSize       | 统一指定或为每个节点指定节点大小，用于占位与间距计算                                                                                               | Size \\| ((nodeData: Node) => Size)                  | -      |      |\n| controlPoints  | 是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'）时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效 | boolean                                             | false  |      |\n| begin          | 布局的左上角对齐位置                                                                                                                               | [number, number] \\| [number, number, number]        | -      |      |\n| sortByCombo    | 同一层节点是否根据每个节点数据中的 `parentId` 进行排序，以防止 Combo 重叠                                                                          | boolean                                             | false  |      |\n| edgeLabelSpace | 是否为边的 label 预留位置                                                                                                                          | boolean                                             | true   |      |\n| nodeOrder      | 同层节点顺序的参考数组，存放节点 id 值                                                                                                             | string[]                                            | -      |      |\n| radial         | 是否基于 `dagre` 进行辐射布局                                                                                                                      | boolean                                             | -      |      |\n| focusNode      | 关注的节点，仅在 `radial` 为 true 时生效                                                                                                           | ID \\| Node \\| null                                  | -      |      |\n| preset         | 布局计算时参考的节点位置，一般用于切换数据时保证重新布局的连续性                                                                                   | NodeData[]                                          | -      |      |\n\n> 补充：在 G6 中，`antv-dagre` 计算得到的控制点会被写入边的 `style.controlPoints`。\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\n节点对齐方式 U：upper（上）；D：down（下）；L：left（左）；R：right（右）\n\n- `UL`:对齐到左上角\n- `UR`:对齐到右上角\n- `DL`:对齐到左下角\n- `DR`:对齐到右下角\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\n布局的方向。T：top（上）；B：bottom（下）；L：left（左）；R：right（右）\n\n- `TB`:从上至下布局\n- `BT`:从下至上布局\n- `LR`:从左至右布局\n- `RL`:从右至左布局\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\n布局的模式\n\n### ranksep\n\n> _number_ **Default:** 50\n\n层间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。ranksepFunc 拥有更高的优先级\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\n层间距（px）的回调函数\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### nodesep\n\n> _number_ **Default:** 50\n\n节点间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。nodesepFunc 拥有更高的优先级\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\n节点间距（px）的回调函数，通过该参数可以对不同节点设置不同的节点间距\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\n布局的左上角对齐位置\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\n是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'） 时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效。本质上就是给边数据增加了 `style.controlPoints`\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\n是否为边的label留位置\n\n这会影响是否在边中间添加dummy node\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\n关注的节点，注意，仅在`radial` 为 true 时生效\n\n- ID: 节点 id\n- Node: 节点实例\n- null: 取消关注\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\n同层节点顺序的参考数组，存放节点 id 值\n\n若未指定，则将按照 dagre 本身机制排列同层节点顺序\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\n统一指定或为每个节点指定节点大小。\n\n用于防止节点重叠时的碰撞检测\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\n布局计算时参考的节点位置\n\n一般用于切换数据时保证重新布局的连续性。在 G6 中，若是更新数据，则将自动使用已存在的布局结果数据作为输入\n\n### radial\n\n> _boolean_\n\n是否基于 dagre 进行辐射布局\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\n同一层节点是否根据每个节点数据中的 parentId 进行排序，以防止 Combo 重叠\n\n建议在有 Combo 的情况下配置\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解 Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","frontmatter":{"title":"AntV Dagre 布局 AntvDagre","order":"2"},"isInternal":false,"tokens":1872,"sizeBytes":10021},{"name":"BaseLayout.en.md","path":"packages/site/docs/manual/layout/BaseLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/BaseLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Common Layout Configuration Options\norder: 1\n---\n\nThis article introduces the common attribute configurations for built-in layouts.\n\n## General Configuration\n\n| Property               | Description                                                                             | Type                                                  | Default    | Required |\n| ---------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------- | -------- |\n| type                   | Layout type, name of built-in or custom layout                                          | [Type](#Type)                                         | -          | ✓        |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in the layout (takes effect when preLayout is true) | boolean                                               | false      |          |\n| nodeFilter             | Nodes participating in the layout                                                       | (node: NodeData) => boolean                           | () => true |          |\n| comboFilter            | Combos participating in the layout                                                      | (combo: ComboData) => boolean                         | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements                           | boolean                                               | false      |          |\n| enableWorker           | Whether to run the layout in a WebWorker                                                | boolean                                               | -          |          |\n| iterations             | Number of iterations for iterative layout                                               | number                                                | -          |          |\n| animation              | Whether to enable layout animation                                                      | boolean                                               | false      |          |\n| width                  | Width of the layout area, defaults to the current container width                       | number                                                | -          |          |\n| height                 | Height of the layout area, defaults to the current container height                     | number                                                | -          |          |\n| center                 | Layout center point                                                                     | [number, number] \\| [number, number, number]          | -          |          |\n| node                   | Node field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |          |\n| edge                   | Edge field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, source?, target? })                | -          |          |\n\nAdditional notes:\n\n- `width` / `height` / `center` are common layout fields uniformly supported by `@antvis/layout`.\n- `node` / `edge` are used to adapt non-standard business fields such as custom `id` / `source` / `target`.\n- `iterations` is the step count used by the G6 runtime to drive iterative layouts, and is not the same as some layouts' internal algorithm parameters.\n\n### Type\n\nSpecifies the layout type, either the name of a built-in layout type or a custom layout.\n\n```js {4}\nconst graph = new Graph({\n  // Other configurations...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\nOptional values include:\n\n- `antv-dagre`: [Custom layout based on dagre](/en/manual/layout/antv-dagre-layout)\n- `circular`: [Circular layout](/en/manual/layout/circular-layout)\n- `combo-combined`: [Layout suitable for combinations](/en/manual/layout/combo-combined-layout)\n- `concentric`: [Concentric layout](/en/manual/layout/concentric-layout)\n- `d3-force`: [Force-directed layout based on D3](/en/manual/layout/d3-force-layout)\n- `d3-force-3d`: [3D Force-directed layout](/en/manual/layout/d3-force3-d-layout)\n- `dagre`: [Dagre layout](/en/manual/layout/dagre-layout)\n- `fishbone`: [Fishbone layout](/en/manual/layout/fishbone)\n- `force`: [Force-directed layout](/en/manual/layout/force-layout)\n- `force-atlas2`: [ForceAtlas2 layout](/en/manual/layout/force-atlas2-layout)\n- `fruchterman`: [Fruchterman layout](/en/manual/layout/fruchterman-layout)\n- `grid`: [Grid layout](/en/manual/layout/grid-layout)\n- `mds`: [MDS layout for high-dimensional data](/en/manual/layout/mds-layout)\n- `radial`: [Radial layout](/en/manual/layout/radial-layout)\n- `random`: [Random layout](/en/manual/layout/random-layout)\n- `snake`: [Snake layout](/en/manual/layout/snake)\n- `compact-box`: [Compact box tree layout](/en/manual/layout/compact-box-layout)\n- `dendrogram`: [Dendrogram layout](/en/manual/layout/dendrogram-layout)\n- `mindmap`: [Mindmap layout](/en/manual/layout/mindmap-layout)\n- `indented`: [Indented tree layout](/en/manual/layout/indented-layout)\n","frontmatter":{"title":"Common Layout Configuration Options","order":"1"},"isInternal":false,"tokens":1292,"sizeBytes":5169},{"name":"BaseLayout.zh.md","path":"packages/site/docs/manual/layout/BaseLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/BaseLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 布局通用配置项\norder: 1\n---\n\n本文介绍内置布局通用属性配置。\n\n## 通用配置\n\n| 属性                   | 描述                                                  | 类型                                                  | 默认值     | 必选 |\n| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ---------- | ---- |\n| type                   | 布局类型，内置布局或自定义布局的名称                  | [Type](#Type)                                         | -          | ✓    |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（当 preLayout 为 true 时生效） | boolean                                               | false      |      |\n| nodeFilter             | 参与该布局的节点                                      | (node: NodeData) => boolean                           | () => true |      |\n| comboFilter            | 参与该布局的combo元素                                 | (combo: ComboData) => boolean                         | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                    | boolean                                               | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                           | boolean                                               | -          |      |\n| iterations             | 迭代布局的迭代次数                                    | number                                                | -          |      |\n| animation              | 是否启用布局动画                                      | boolean                                               | false      |      |\n| width                  | 布局区域宽度，默认使用当前容器宽度                    | number                                                | -          |      |\n| height                 | 布局区域高度，默认使用当前容器高度                    | number                                                | -          |      |\n| center                 | 布局中心点                                            | [number, number] \\| [number, number, number]          | -          |      |\n| node                   | 节点字段映射，用于把业务字段映射为布局字段            | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |      |\n| edge                   | 边字段映射，用于把业务字段映射为布局字段              | (datum) => ({ id?, source?, target? })                | -          |      |\n\n补充说明：\n\n- `width` / `height` / `center` 是 `@antvis/layout` 统一支持的通用布局字段。\n- `node` / `edge` 用于适配非标准 `id/source/target` 业务数据。\n- `iterations` 是 G6 运行时用于驱动迭代布局的步数，不等同于某些布局内部自己的算法参数。\n\n### Type\n\n指定布局类型，内置布局类型名称或自定义布局的名称。\n\n```js {4}\nconst graph = new Graph({\n  // 其他配置...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\n可选值有：\n\n- `antv-dagre`：[基于 dagre 定制的布局](/manual/layout/antv-dagre-layout)\n- `circular`：[环形布局](/manual/layout/circular-layout)\n- `combo-combined`：[适用于存在组合的布局](/manual/layout/combo-combined-layout)\n- `concentric`：[同心圆布局](/manual/layout/concentric-layout)\n- `d3-force`[基于 D3 的力导向布局](/manual/layout/d3-force-layout)\n- `d3-force-3d`：[3D力导向布局](/manual/layout/d3-force3-d-layout)\n- `dagre`：[dagre 布局](/manual/layout/dagre-layout)\n- `fishbone`：[鱼骨布局](/manual/layout/fishbone)\n- `force`：[力导向布局](/manual/layout/force-layout)\n- `force-atlas2`：[ForceAtlas2 布局](/manual/layout/force-atlas2-layout)\n- `fruchterman`：[Fruchterman 布局](/manual/layout/fruchterman-layout)\n- `grid`：[网格布局](/manual/layout/grid-layout)\n- `mds`：[高维数据降维算法布局](/manual/layout/mds-layout)\n- `radial`：[径向布局](/manual/layout/radial-layout)\n- `random`：[随机布局](/manual/layout/random-layout)\n- `snake`：[蛇形布局](/manual/layout/snake)\n- `compact-box`：[紧凑树布局](/manual/layout/compact-box-layout)\n- `dendrogram`：[树状布局](/manual/layout/dendrogram-layout)\n- `mindmap`：[思维导图布局](/manual/layout/mindmap-layout)\n- `indented`：[缩进树布局](/manual/layout/indented-layout)\n","frontmatter":{"title":"布局通用配置项","order":"1"},"isInternal":false,"tokens":918,"sizeBytes":4530},{"name":"CircularLayout.en.md","path":"packages/site/docs/manual/layout/CircularLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/CircularLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Circular Layout\norder: 3\n---\n\n## Overview\n\nCircular layout arranges nodes evenly or at intervals on a circle, and also supports spiral layouts by configuring different startRadius and endRadius. See more circular layout [examples](en/examples#layout-circular) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n**Circular layout**:\n\n- Suitable for networks with equal relationships and no hierarchical structure\n\n**Spiral layout**:\n\n- Suitable for implicit hierarchies or time series graphs (such as organizational charts, propagation networks)\n\n## Basic Usage\n\nOther settings use the default configuration (layout width and height default to the entire canvas container)\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## Options\n\n| Property    | Description                                                                                                       | Type                                          | Default                                   | Required |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------- | -------- |\n| type        | Layout type                                                                                                       | circular                                      | -                                         | ✓        |\n| angleRatio  | How many 2\\*PI between the first and last node                                                                    | number                                        | 1                                         |          |\n| center      | Center of the layout                                                                                              | [number, number]\\|[number, number, number]    | [`layout width` / 2, `layout height` / 2] |          |\n| clockwise   | Whether to arrange clockwise                                                                                      | boolean                                       | true                                      |          |\n| divisions   | Number of segments on the ring (segments will be evenly distributed, effective when endRadius - startRadius != 0) | number                                        | 1                                         |          |\n| nodeSize    | Node size (diameter), used for collision detection                                                                | Size \\| ((nodeData: Node) => Size)            | 10                                        |          |\n| nodeSpacing | Minimum spacing between rings, used to adjust radius                                                              | number \\| ((nodeData: Node) => number)        | 10                                        |          |\n| ordering    | Node ordering on the ring, [see details](#ordering)                                                               | `topology` \\| `topology-directed` \\| `degree` | -                                         |          |\n| radius      | Circle radius, if set, spiral layout configs `startRadius` and `endRadius` are ignored, [see details](#radius)    | number                                        | -                                         |          |\n| startAngle  | Start angle of the layout                                                                                         | number                                        | 0                                         |          |\n| endAngle    | End angle of the layout                                                                                           | number                                        | 2 \\* Math.PI                              |          |\n| startRadius | Start radius for spiral layout, [usage](#spiral-layout)                                                           | number                                        | -                                         |          |\n| endRadius   | End radius for spiral layout                                                                                      | number                                        | -                                         |          |\n| width       | Layout width                                                                                                      | number                                        | canvas width                              |          |\n| height      | Layout height                                                                                                     | number                                        | canvas height                             |          |\n\n### ordering\n\nNode ordering on the ring\n\n- `topology`: topological order\n- `topology-directed`: topological order (directed graph)\n- `degree`: order by degree\n\nIf not set (`null`), the order in the array is used directly\n\n### radius\n\nIf radius, startRadius, and endRadius are not set, the default is `Math.min(layout width, layout height) / 2`, i.e., fills the entire layout area\n\n## Code Examples\n\n### Basic Circular Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### Spiral Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"Circular Layout","order":"3"},"isInternal":false,"tokens":1685,"sizeBytes":6740},{"name":"CircularLayout.zh.md","path":"packages/site/docs/manual/layout/CircularLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/CircularLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 环形布局 Circular\norder: 3\n---\n\n## 概述\n\n环形布局是一种把节点均匀或者按间隔放置在圆上的布局，也支持通过配置 startRadius 和 endRadius 为不一样的值实现螺旋状布局。参考更多环形布局[样例](/examples#layout-circular)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n**环形布局**:\n\n- 适用于平等关系网络、无层级结构的图\n\n**螺旋状布局**:\n\n- 适用于隐式层级或时间序列图（如组织架构、传播网络）\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## 配置项\n\n| 属性        | 描述                                                                                | 类型                                          | 默认值                           | 必选 |\n| ----------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | -------------------------------- | ---- |\n| type        | 布局类型                                                                            | circular                                      | -                                | ✓    |\n| angleRatio  | 从第一个节点到最后节点之间相隔多少个 2\\*PI                                          | number                                        | 1                                |      |\n| center      | 布局的中心                                                                          | [number, number]\\|[number, number, number]    | [`布局宽度` / 2, `布局高度` / 2] |      |\n| clockwise   | 是否顺时针排列                                                                      | boolean                                       | true                             |      |\n| divisions   | 节点在环上的分段数（几个段将均匀分布，在 endRadius - startRadius != 0 时生效）      | number                                        | 1                                |      |\n| nodeSize    | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                      | Size \\| ((nodeData: Node) => Size)            | 10                               |      |\n| nodeSpacing | 环与环之间最小间距，用于调整半径                                                    | number \\| ((nodeData: Node) => number)        | 10                               |      |\n| ordering    | 节点在环上排序的依据，[说明](#ordering)                                             | `topology` \\| `topology-directed` \\| `degree` | -                                |      |\n| radius      | 圆的半径，设置了则螺旋状布局的配置`startRadius`、`endRadius`不生效，[说明](#radius) | number                                        | -                                |      |\n| startAngle  | 布局的开始角度                                                                      | number                                        | 0                                |      |\n| endAngle    | 布局的结束角度                                                                      | number                                        | 2 \\* Math.PI                     |      |\n| startRadius | 螺旋状布局的开始半径，[用法](#螺旋状布局)                                           | number                                        | -                                |      |\n| endRadius   | 螺旋状布局的结束半径                                                                | number                                        | -                                |      |\n| width       | 布局的宽度                                                                          | number                                        | 画布宽度                         |      |\n| height      | 布局的高度                                                                          | number                                        | 画布高度                         |      |\n\n### ordering\n\n节点在环上排序的依据\n\n- `topology`: 按照拓扑排序\n- `topology-directed`: 按照拓扑排序（有向图）\n- `degree`: 按照度数大小排序\n\n不配置（`null`）则直接使用数组中的顺序\n\n### radius\n\n如果radius、startRadius、endRadius都没配置，则默认为最终计算出来的`Math.min(布局宽度, 布局高度) / 2`，即布满整个布局区域\n\n## 代码示例\n\n### 基础环形布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### 螺旋状布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"环形布局 Circular","order":"3"},"isInternal":false,"tokens":1291,"sizeBytes":6131},{"name":"ComboCombinedLayout.en.md","path":"packages/site/docs/manual/layout/ComboCombinedLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ComboCombinedLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ComboCombined Layout\norder: 4\n---\n\n## Overview\n\nComboCombined composite layout is suitable for graph data with composite group structures. It supports flexible configuration of the layout for elements inside combos as well as the layout between the outermost combos and nodes. By default, the internal elements use the Concentric layout, and the outer layout uses the gForce force-directed layout, balancing layout effect and overall stability. See more ComboCombined layout [examples](/en/examples#layout-combo-layout) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts).\n\n## Usage Scenarios\n\n- User profile analysis: Analyze user behavior and product relationships, use user interest circles as combos, display specific products and behavior tags as internal nodes, and help operators identify user consumption paths.\n- Supply chain management graph: Divide suppliers, manufacturers, warehouses, and distributors into combos by role or region, display resources, personnel, or equipment as internal nodes, and clearly show the internal structure of each link in the supply chain.\n\n## Options\n\n| Property     | Description                                                                                                                                        | Type                                                                                       | Default      | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------ | -------- |\n| type         | Layout type                                                                                                                                        | `combo-combined`                                                                           | -            | ✓        |\n| center       | Layout center                                                                                                                                      | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | Graph center |          |\n| layout       | Layout configuration. Can be fixed, or returned dynamically based on `comboId`                                                                     | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -            |          |\n| nodeSize     | Node size (diameter), used for collision detection                                                                                                 | `number` \\| `number[]` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number     | -            |          |\n| nodeSpacing  | Spacing between nodes                                                                                                                              | `number` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number                   | -            |          |\n| comboSpacing | Spacing between combos                                                                                                                             | `number` \\| (d?: unknown) => number                                                        | -            |          |\n| comboPadding | Padding value inside the combo, used only for force calculation, not for rendering. It is recommended to set the same value as the visual padding. | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -            |          |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\nIn `5.1`, it is recommended to use a single `layout` field to choose layouts for different levels, instead of configuring `innerLayout` and `outerLayout` separately.\n\n**Example**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"ComboCombined Layout","order":"4"},"isInternal":false,"tokens":1247,"sizeBytes":5004},{"name":"ComboCombinedLayout.zh.md","path":"packages/site/docs/manual/layout/ComboCombinedLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ComboCombinedLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 复合布局 ComboCombined\norder: 4\n---\n\n## 概述\n\nComboCombined 复合布局适用于复合分组结构的图数据展示场景，支持灵活配置 Combo 内部元素的布局以及最外层 Combo 和节点之间的布局。 默认情况内部元素采用 Concentric 同心圆布局，外部布局采用 gForce 力导向布局，兼顾布局效果与整体稳定性。参考更多 ComboCombined 复合布局[样例](/examples#layout-combo-layout)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts)\n\n## 使用场景\n\n- 用户画像分析: 分析用户行为与商品关系，将用户兴趣圈层作为 Combo，内部节点展示具体商品和行为标签，帮助运营人员识别用户消费路径。\n- 供应链管理图：供应商、制造商、仓储、分销商按角色或区域划分 Combo，内部节点展示资源、人员或设备，清晰展示供应链各环节内部结构。\n\n## 配置项\n\n| 属性         | 描述                                                                                                | 类型                                                                                       | 默认值 | 必选 |\n| ------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---- |\n| type         | 布局类型                                                                                            | `combo-combined`                                                                           | -      | ✓    |\n| center       | 布局中心                                                                                            | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | 图中心 |      |\n| layout       | 布局配置。可固定指定，也可根据 `comboId` 动态返回                                                   | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -      |      |\n| nodeSize     | 节点大小（直径）。用于碰撞检测                                                                      | `number` \\| `number[]` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number        | -      |      |\n| nodeSpacing  | 节点间距                                                                                            | `number` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number                      | -      |      |\n| comboSpacing | Combo 之间的间距                                                                                    | `number` \\| (d?: unknown) => number                                                        | -      |      |\n| comboPadding | Combo 内部的 padding 值，不用于渲染，仅用于计算力。推荐设置为与视图上 Combo 内部 padding 值相同的值 | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -      |      |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\n5.1 中推荐使用单个 `layout` 字段为不同层级选择布局，而不是分别配置 `innerLayout` 和 `outerLayout`。\n\n**示例**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## 示例代码\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"复合布局 ComboCombined","order":"4"},"isInternal":false,"tokens":902,"sizeBytes":4361},{"name":"CompactBoxLayout.en.md","path":"packages/site/docs/manual/layout/CompactBoxLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/CompactBoxLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: CompactBox Layout\norder: 5\n---\n\n## Overview\n\nThe CompactBox layout is suitable for visualizing structured tree data. It is evolved from the classic [Reingold–Tilford tidy layout algorithm](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf), and considers the bounding box of each tree node during layout, effectively maintaining the compactness and hierarchical clarity of the tree structure. See more CompactBox layout [examples](/en/examples#layout-compact-box) and [source code](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox Tidy Tree Layout Example'/>\n\n## Usage Scenarios\n\n- Decision trees: The compact tree layout can visually and intuitively display each decision path.\n- Knowledge graphs: Show hierarchical relationships and connections between concepts. The compact layout can present complex knowledge networks in limited space.\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## Options\n\n| Property  | Description                                                                                                   | Type                                                         | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------- | -------- |\n| type      | Layout type                                                                                                   | `compact-box`                                                | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                       | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                   | `LR`    |          |\n| getSide   | Set whether the node is on the left or right of the root. Only works for `H` direction. [See below](#getside) | (d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string |         |          |\n| getId     | Callback for node id                                                                                          | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => string |         |          |\n| getWidth  | Callback for node width                                                                                       | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHeight | Callback for node height                                                                                      | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHGap   | Callback for horizontal gap                                                                                   | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getVGap   | Callback for vertical gap                                                                                     | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| radial    | Whether to enable radial layout, [see below](#radial)                                                         | boolean                                                      | false   |          |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\nTree layout direction\n\n- `TB`: Root at the top, layout downwards\n- `BT`: Root at the bottom, layout upwards\n- `LR`: Root at the left, layout to the right\n- `RL`: Root at the right, layout to the left\n- `H`: Root in the middle, horizontal symmetric layout. You can use `getSide` to specify the left/right logic for each node\n- `V`: Root in the middle, vertical symmetric layout\n\n### getSide\n\n> _(d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string_\n\nSet whether the node is on the left or right of the root. Only works for `H` direction. If not set, the algorithm will automatically assign left/right. See [getSide auto logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n({ data }) => {\n  // data is a node\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => string_\n\nCallback for node id\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node width\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node height\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for horizontal gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for vertical gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout. If `radial` is `true`, it is recommended to set `direction` to `'LR'` or `'RL'`.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"CompactBox Layout","order":"5"},"isInternal":false,"tokens":1809,"sizeBytes":7334},{"name":"CompactBoxLayout.zh.md","path":"packages/site/docs/manual/layout/CompactBoxLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/CompactBoxLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 紧凑树布局 CompactBox\norder: 5\n---\n\n## 概述\n\n紧凑树布局适用于结构化树形数据的展示，基于经典的 [Reingold–Tilford tidy 布局算法](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf) 演进而来，通过布局时综合考虑每个树节点的包围盒，有效保持树结构的紧凑性与层次清晰。参考更多 CompactBox 布局[样例](/examples#layout-compact-box)和[源码](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js)\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox 紧凑树布局示例'/>\n\n## 使用场景\n\n- 决策树: 通过紧凑树布局可简单直观的图形化展示每个决策路径\n- 知识图谱: 展示概念之间的层级关系和连接，紧凑布局可以在有限空间内呈现复杂的知识网络\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                                                                                    | 类型                                                      | 默认值 | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                                | `compact-box`                                             | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                          | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                | `LR`   |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在 `H` 布局方向上生效 | (d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string |        |      |\n| getId     | 节点 id 的回调函数                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => string |        |      |\n| getWidth  | 计算每个节点的宽度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHeight | 计算每个节点的高度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHGap   | 计算每个节点的水平间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getVGap   | 计算每个节点的垂直间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)                                                                     | boolean                                                   | false  |      |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\n树布局方向\n\n- `TB`：根节点在上，往下布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*KrAqTrFbNjMAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `BT`：根节点在下，往上布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vNmOTJ4q0uwAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `LR`：根节点在左，往右布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ffD6S74MXw4AAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `RL`：根节点在右，往左布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vTg2SJbtj_sAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `H`：根节点在中间，水平对称布局。可传入 `getSide` 方法指定每个节点的左右分布逻辑\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0GsIQISvieYAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n### getSide\n\n> _(d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在 `direction` 为 `H` 时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考 [getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n({ data }) => {\n  // data 是一个节点\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => string_\n\n节点 id 的回调函数\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\n是否按照辐射状布局。若 `radial` 为 `true`，建议 `direction` 设置为 `'LR'` 或 `'RL'`\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"紧凑树布局 CompactBox","order":"5"},"isInternal":false,"tokens":1680,"sizeBytes":8023},{"name":"ConcentricLayout.en.md","path":"packages/site/docs/manual/layout/ConcentricLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ConcentricLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Concentric Layout\norder: 6\n---\n\n## Overview\n\nThe concentric layout arranges nodes in layers according to a certain sorting rule, with each layer of nodes placed around a common center. See more concentric layout [examples](/en/examples#layout-concentric) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n- Layered data visualization, such as permission structures, organizational charts, etc., with the center as the top-level role and outer rings as lower-level nodes.\n- Visualization of ranking analysis results, with high-importance nodes in the center and low-importance nodes on the periphery, quickly expressing the relative influence of nodes in the graph.\n\n## Options\n\n| Property       | Description                                                                                                                                                                 | Type                                               | Default                                                   | Required |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- | -------- | --------- | --- |\n| type           | Layout type                                                                                                                                                                 | `concentric`                                       | -                                                         | ✓        |\n| center         | Center position of the circular layout, defaults to the center of the container                                                                                             | [number, number] \\| [number, number, number]       | -                                                         |          |\n| clockwise      | Whether to arrange nodes clockwise                                                                                                                                          | boolean                                            | false                                                     |          |\n| equidistant    | Whether the distance between rings is equal                                                                                                                                 | boolean                                            | false                                                     |          |\n| width          | Layout width, defaults to container width                                                                                                                                   | number                                             | -                                                         |          |\n| height         | Layout height, defaults to container height                                                                                                                                 | number                                             | -                                                         |          |\n| sortBy         | The property to sort by (node attribute name). The higher the value, the closer to the center. If set to 'degree', nodes with higher degree are placed closer to the center | string                                             | `degree`                                                  |          |\n| maxLevelDiff   | Maximum attribute difference in the same layer. If undefined, set to maxValue / 4, where maxValue is the maximum value of the sorting property                              | number                                             | undefined                                                 |          |\n| nodeSize       | Node size (diameter), used for collision detection                                                                                                                          | number \\| number[] \\| ((nodeData: Node) => number) | 30                                                        |          |\n| nodeSpacing    | Minimum spacing between rings, used to adjust the radius                                                                                                                    | number \\| number[] \\| ((node?: Node) => number)    | 10                                                        |          |\n| preventOverlap | Whether to prevent overlap. Must be used with nodeSize or data.size. Only works if node size is set in data or in this layout config.                                       | boolean                                            | false                                                     |          |\n| startAngle     | The angle (in radians) to start laying out nodes                                                                                                                            | number                                             | 3 / 2 \\* Math.PI                                          |          |\n| sweep          | The angle difference between the first and last node in the same layer. If undefined, it is set to `2 _ Math.PI _ (1 - 1 /                                                  | level.nodes                                        | )`, where `level.nodes` is the set of nodes in that layer | number   | undefined |     |\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: 'Center', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Concentric Layout","order":"6"},"isInternal":false,"tokens":2131,"sizeBytes":8523},{"name":"ConcentricLayout.zh.md","path":"packages/site/docs/manual/layout/ConcentricLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ConcentricLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 同心圆布局 Concentric\norder: 6\n---\n\n## 概述\n\n同心圆布局是一种将节点根据某种排序规则分层，并以圆心为中心、沿圆周排列每层节点的布局方式。参考更多同心圆布局[样例](/examples#layout-concentric)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n- 分层数据可视化，如权限控制结构、组织架构图等，中心是顶级角色，外圈为下级节点。\n- 排序分析结果可视化，高重要度放中心，低重要度放外围，快速表达图中节点的相对影响力。\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                        | 类型                                               | 默认值           | 必选 |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------- | ---- |\n| type           | 布局类型                                                                                                                                                                                                    | `concentric`                                       | -                | ✓    |\n| center         | 圆形布局的中心位置，默认为当前容器的中心位置                                                                                                                                                                | [number, number] \\| [number, number, number]       | -                |      |\n| clockwise      | 是否按照顺时针排列                                                                                                                                                                                          | boolean                                            | false            |\n| equidistant    | 环与环之间的距离是否相等                                                                                                                                                                                    | boolean                                            | false            |      |\n| width          | 布局的宽度，默认使用容器宽度                                                                                                                                                                                | number                                             | -                |      |\n| height         | 布局的高度，默认使用容器高度                                                                                                                                                                                | number                                             | -                |      |\n| sortBy         | 指定排序的依据（节点属性名）<br>数值越高则该节点被放置得越中心。若为 degree，则会计算节点的度数，度数越高，节点将被放置得越中心                                                                             | string                                             | `degree`         |      |\n| maxLevelDiff   | 同一层节点的最大属性差值<br>若为 undefined，则将会被设置为 maxValue / 4 ，其中 maxValue 为最大的排序依据的属性值。例如，若 sortBy 为 'degree'，则 maxValue 为所有节点中度数最大的节点的度数                 | number                                             | undefined        |      |\n| nodeSize       | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                                                                                                                                              | number \\| number[] \\| ((nodeData: Node) => number) | 30               |      |\n| nodeSpacing    | 环与环之间最小间距，用于调整半径                                                                                                                                                                            | number \\| number[] \\| ((node?: Node) => number)    | 10               |      |\n| preventOverlap | 是否防止重叠<br>必须配合 nodeSize 属性或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测                        | boolean                                            | false            |      |\n| startAngle     | 开始布局节点的弧度                                                                                                                                                                                          | number                                             | 3 / 2 \\* Math.PI |      |\n| sweep          | 同一层中第一个节点与最后一个节点之间的弧度差<br>若为 undefined ，则将会被设置为 2 \\* Math.PI \\* (1 - 1 / \\|level.nodes\\|) ，其中 level.nodes 为该算法计算出的每一层的节点，\\|level.nodes\\| 代表该层节点数量 | number                                             | undefined        |      |\n\n## 代码示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n</details>\n","frontmatter":{"title":"同心圆布局 Concentric","order":"6"},"isInternal":false,"tokens":2611,"sizeBytes":11540},{"name":"custom-layout.en.md","path":"packages/site/docs/manual/layout/custom-layout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/custom-layout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Layout\norder: 22\n---\n\n## Overview\n\nIn G6, layouts are divided into two types: 'iterative layout' and 'non-iterative layout'. An iterative layout refers to a layout algorithm that iterates multiple times until convergence, while a non-iterative layout refers to a layout algorithm that executes only once.\n\n## Implement Layout\n\n### Non-Iterative Layout\n\nImplementing a non-iterative layout is relatively straightforward; you only need to implement the `execute` method in `BaseLayout`. Below is a simple implementation of a custom layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\nIn the code above, we implemented a simple layout algorithm that arranges nodes along a diagonal line starting from the top-left corner.\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=info}\n\nThe `execute` method returns a GraphData object, which only needs to contain the basic information of the elements (such as id, source, target) and the properties added by the layout (such as x, y, control points of edges, etc.), and does not need to contain other unnecessary information.\nIf you only need to layout the nodes, you can return only the node information and do not need to return the edge information.\n:::\n\n### Iterative Layout\n\nThe implementation of an iterative layout also requires inheriting from `BaseLayout`, but in addition to `execute`, you also need to implement the `tick` and `stop` methods. The `tick` method is used to iterate the layout to a specified number of rounds, and the `stop` method is used to stop the layout iteration.\n\nIn addition, in iterative layouts, you need to call `options.onTick` each time the layout iterates to trigger the graph update.\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\nBelow is a simple implementation of an iterative layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\nIn this example, we have implemented a simple iterative layout algorithm that toggles the x-coordinate of the nodes between 50 and 150 every 200 milliseconds and arranges them in order along the y-axis according to the sequence of the nodes.\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## Register Layout\n\nYou can register through the `register` method provided by G6. For more details, please refer to [Register Layout](/en/manual/core-concept/layout#register-layout)\n\n## Configure Layout\n\nThe type and parameters of the layout can be configured in `options.layout`. For more details, please refer to [Configure Layout](/en/manual/core-concept/layout#configure-layout)\n","frontmatter":{"title":"Custom Layout","order":"22"},"isInternal":false,"tokens":1073,"sizeBytes":4289},{"name":"custom-layout.zh.md","path":"packages/site/docs/manual/layout/custom-layout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/custom-layout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义布局\norder: 22\n---\n\n## 概述\n\nG6 中布局分为`迭代布局`和`非迭代布局`两种，迭代布局是指布局算法会迭代多次直到收敛，非迭代布局是指布局算法只执行一次。\n\n## 实现布局\n\n### 非迭代布局\n\n实现一个非迭代布局相对简单，只需要实现 `BaseLayout` 中的 `execute` 方法即可，下面是一个简单的自定义布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\n在上面的代码中，我们实现了一个简单的布局算法，将节点从左上角沿对角线排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=提示}\n`execute` 方法返回的是一个 GraphData 对象，里面仅需要包含元素的基本信息（如 id、source、target）以及布局新增的属性（如 x、y、边的控制点等），不需要包含其他无用的信息。\n如果仅需要对节点进行布局，可以只返回节点信息，不需要返回边的信息。\n:::\n\n### 迭代布局\n\n迭代布局的实现同样需要继承 `BaseLayout`，但是除 `execute` 外还需要实现 `tick` 和 `stop` 方法，`tick` 方法用于将布局迭代到指定轮次，`stop` 方法用于停止布局迭代。\n\n此外，迭代布局中需要在每次迭代调用 `options.onTick` 以触发图的更新。\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\n下面是一个简单的迭代布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\n在这个例子中，我们实现了一个简单的迭代布局算法，每 200ms 将节点的 x 坐标在 50 和 150 之间切换，并按照节点顺序在 y 方向上排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## 注册布局\n\n通过 G6 提供的 register 方法注册即可，详见[注册布局](/manual/layout/overview#注册布局)\n\n## 配置布局\n\n可在 `options.layout` 中配置布局的类型和参数，详见[配置布局](/manual/layout/overview#配置布局)\n","frontmatter":{"title":"自定义布局","order":"22"},"isInternal":false,"tokens":701,"sizeBytes":3707},{"name":"D3Force3DLayout.en.md","path":"packages/site/docs/manual/layout/D3Force3DLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/D3Force3DLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 3D Force-Directed Layout\norder: 7\n---\n\n## Overview\n\nThe D3Force3D layout is a 3D extension based on [d3-force](https://d3js.org/d3-force), which simulates physical forces in three-dimensional space to achieve automatic layout. Compared to 2D layouts, it adds force effects in the Z-axis direction, allowing richer data relationships to be displayed in 3D space.\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D Force-Directed Layout Illustration\" />\n\n## Core Concepts\n\n### Force System\n\nD3Force3D extends the traditional 2D force-directed layout with the following forces:\n\n- **3D Centering Force**: Pulls nodes toward the center point in 3D space\n- **3D Collision Force**: Prevents node overlap in 3D space\n- **3D Radial Force**: Attracts nodes to a sphere in 3D space\n- **3D Axis Forces**: Applies forces along the X, Y, and Z axes\n\n### Iteration System\n\nThe layout is computed through iterations, mainly involving the following parameters:\n\n- **alpha**: The current energy value of the iteration, controlling node movement speed\n- **alphaDecay**: The decay rate of the energy value\n- **alphaMin**: The minimum energy value; iteration stops below this value\n- **velocityDecay**: The velocity decay factor\n\n## Options\n\n| Property        | Description                                                      | Type                                                                       | Default       | Required |\n| --------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------- | -------- |\n| type            | Layout type                                                      | string                                                                     | `d3-force-3d` | ✓        |\n| nodeSize        | Node size (diameter), used for collision detection               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -             |          |\n| iterations      | Number of force iterations; higher means more precise but slower | number                                                                     | -             |          |\n| numDimensions   | Number of dimensions (2 or 3)                                    | number                                                                     | 3             |          |\n| forceSimulation | Custom force simulation method                                   | Simulation<NodeDatum, EdgeDatum>                                           | -             |          |\n| onTick          | Callback for each iteration                                      | (data: LayoutMapping) => void                                              | -             |          |\n| randomSource    | Random number generator                                          | () => number                                                               | -             |          |\n\n### Iteration Control\n\n| Property      | Description                   | Type   | Default | Required |\n| ------------- | ----------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold | number | 1       |          |\n| alphaDecay    | Convergence decay rate (0-1)  | number | 0.028   |          |\n| alphaMin      | Stop iteration threshold      | number | 0.001   |          |\n| alphaTarget   | Target convergence threshold  | number | 0       |          |\n| velocityDecay | Velocity decay factor         | number | 0.4     |          |\n\n### Force Model Options\n\n#### Centering Force (center)\n\n| Property        | Description         | Type   | Default | Required |\n| --------------- | ------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate | number | 0       |          |\n| center.y        | Center y coordinate | number | 0       |          |\n| center.z        | Center z coordinate | number | 0       |          |\n| center.strength | Force strength      | number | 1       |          |\n\n#### Collision Force (collide)\n\n| Property           | Description          | Type                                                                       | Default | Required |\n| ------------------ | -------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| collide.radius     | Collision radius     | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10      |          |\n| collide.strength   | Force strength       | number                                                                     | 1       |          |\n| collide.iterations | Collision iterations | number                                                                     | 1       |          |\n\n#### Link Force (link)\n\n| Property        | Description           | Type                                                                       | Default | Required |\n| --------------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| link.id         | Edge id generator     | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |          |\n| link.distance   | Ideal edge length     | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |          |\n| link.strength   | Force strength        | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |          |\n| link.iterations | Link force iterations | number                                                                     | 1       |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                  | Type                                                                       | Default  | Required |\n| -------------------- | ---------------------------- | -------------------------------------------------------------------------- | -------- | -------- |\n| manyBody.strength    | Force strength               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy          | number                                                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum interaction distance | number                                                                     | 1        |          |\n| manyBody.distanceMax | Maximum interaction distance | number                                                                     | Infinity |          |\n\n#### Radial Force (radial)\n\n| Property        | Description     | Type                                                                       | Default | Required |\n| --------------- | --------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| radial.strength | Force strength  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1     |          |\n| radial.radius   | Target radius   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100     |          |\n| radial.x        | Sphere center x | number                                                                     | 0       |          |\n| radial.y        | Sphere center y | number                                                                     | 0       |          |\n| radial.z        | Sphere center z | number                                                                     | 0       |          |\n\n#### Axis Forces (x, y, z)\n\nEach axis can be configured separately:\n\n| Property   | Description           | Type                                                                       | Default | Required |\n| ---------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| x.strength | X-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| x.x        | Target x coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.strength | Y-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.y        | Target y coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.strength | Z-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.z        | Target z coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n","frontmatter":{"title":"3D Force-Directed Layout","order":"7"},"isInternal":false,"tokens":2211,"sizeBytes":8844},{"name":"D3Force3DLayout.zh.md","path":"packages/site/docs/manual/layout/D3Force3DLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/D3Force3DLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 3D D3力导向布局 D3Force3D\norder: 7\n---\n\n## 概述\n\nD3Force3D 布局是基于 [d3-force](https://d3js.org/d3-force) 的三维扩展版本，通过在三维空间中模拟物理力的作用来实现自动布局。相比二维布局，它增加了 Z 轴方向的力作用，能够在三维空间中展现更丰富的数据关系。\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D 力导向布局示意图\" />\n\n## 核心概念\n\n### 力系统\n\nD3Force3D 在传统二维力导向布局的基础上，扩展了以下力的作用：\n\n- **三维中心力**：将节点拉向三维空间的中心点\n- **三维碰撞力**：在三维空间中防止节点重叠\n- **三维径向力**：将节点吸引到三维空间中的球面上\n- **三维坐标力**：分别在 X、Y、Z 三个方向上施加作用力\n\n### 迭代系统\n\n布局计算通过迭代来实现，主要涉及以下参数：\n\n- **alpha**：当前迭代的活力值，控制节点移动速度\n- **alphaDecay**：活力值的衰减率\n- **alphaMin**：最小活力值，低于此值停止迭代\n- **velocityDecay**：速度衰减因子\n\n## 配置项\n\n| 属性            | 描述                                         | 类型                                                                       | 默认值        | 必选 |\n| --------------- | -------------------------------------------- | -------------------------------------------------------------------------- | ------------- | ---- |\n| type            | 布局类型                                     | string                                                                     | `d3-force-3d` | ✓    |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10            |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大 | number                                                                     | -             |      |\n| numDimensions   | 维度数量，固定为 3                           | number                                                                     | 3             |      |\n| forceSimulation | 自定义力模拟方法                             | Simulation<NodeDatum, EdgeDatum>                                           | -             |      |\n| onTick          | 每次迭代的回调函数                           | (data: LayoutMapping) => void                                              | -             |      |\n| randomSource    | 随机数生成函数                               | () => number                                                               | -             |      |\n\n### 迭代控制\n\n| 属性          | 描述                  | 类型   | 默认值 | 必选 |\n| ------------- | --------------------- | ------ | ------ | ---- |\n| alpha         | 当前迭代收敛阈值      | number | 1      |      |\n| alphaDecay    | 收敛阈值衰减率（0-1） | number | 0.028  |      |\n| alphaMin      | 停止迭代的阈值        | number | 0.001  |      |\n| alphaTarget   | 目标收敛阈值          | number | 0      |      |\n| velocityDecay | 速度衰减因子          | number | 0.4    |      |\n\n### 力模型配置\n\n#### 中心力（center）\n\n| 属性            | 描述          | 类型   | 默认值 | 必选 |\n| --------------- | ------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标 | number | 0      |      |\n| center.y        | 中心点 y 坐标 | number | 0      |      |\n| center.z        | 中心点 z 坐标 | number | 0      |      |\n| center.strength | 力的强度      | number | 1      |      |\n\n#### 碰撞力（collide）\n\n| 属性               | 描述               | 类型                                                                       | 默认值 | 必选 |\n| ------------------ | ------------------ | -------------------------------------------------------------------------- | ------ | ---- |\n| collide.radius     | 碰撞半径           | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10     |      |\n| collide.strength   | 力的强度           | number                                                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数 | number                                                                     | 1      |      |\n\n#### 链接力（link）\n\n| 属性            | 描述             | 类型                                                                       | 默认值  | 必选 |\n| --------------- | ---------------- | -------------------------------------------------------------------------- | ------- | ---- |\n| link.id         | 边的 id 生成函数 | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |      |\n| link.distance   | 理想边长         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |      |\n| link.strength   | 力的强度         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |      |\n| link.iterations | 链接力的迭代次数 | number                                                                     | 1       |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                      | 类型                                                                       | 默认值   | 必选 |\n| -------------------- | ------------------------- | -------------------------------------------------------------------------- | -------- | ---- |\n| manyBody.strength    | 力的强度                  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数 | number                                                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离              | number                                                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离              | number                                                                     | Infinity |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述        | 类型                                                                       | 默认值 | 必选 |\n| --------------- | ----------- | -------------------------------------------------------------------------- | ------ | ---- |\n| radial.strength | 力的强度    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1    |      |\n| radial.radius   | 目标半径    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100    |      |\n| radial.x        | 球心 x 坐标 | number                                                                     | 0      |      |\n| radial.y        | 球心 y 坐标 | number                                                                     | 0      |      |\n| radial.z        | 球心 z 坐标 | number                                                                     | 0      |      |\n\n#### 坐标力（x、y、z）\n\n每个方向的力可以单独配置：\n\n| 属性       | 描述             | 类型                                                                       | 默认值 | 必选 |\n| ---------- | ---------------- | -------------------------------------------------------------------------- | ------ | ---- |\n| x.strength | X 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| x.x        | 目标 x 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.strength | Y 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.y        | 目标 y 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.strength | Z 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.z        | 目标 z 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n","frontmatter":{"title":"3D D3力导向布局 D3Force3D","order":"7"},"isInternal":false,"tokens":1768,"sizeBytes":8410},{"name":"D3ForceLayout.en.md","path":"packages/site/docs/manual/layout/D3ForceLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/D3ForceLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: D3 Force-Directed Layout\norder: 8\n---\n\n## Overview\n\nThe D3Force layout is a force-directed layout based on [d3-force](https://d3js.org/d3-force). It simulates physical forces (such as attraction, repulsion, collision, etc.) to make the graph reach a stable state with minimal energy.\n\nThe main features of this layout are:\n\n1. **Automatic arrangement**: No need to manually set node positions, the system will automatically find suitable positions\n2. **Real-time adjustment**: When you drag a node, other nodes will adjust their positions in real time\n3. **Flexible configuration**:\n   - You can adjust the attraction and repulsion between nodes\n   - You can set the ideal length of edges\n   - You can fix the positions of important nodes\n4. **Animation effect**: Nodes move with smooth animation, making changes more natural\n\n<img alt=\"D3Force layout diagram\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Core Concepts\n\n### Force System\n\nThe D3Force layout simulates five different forces to achieve automatic layout. Imagine a physical world where these forces act simultaneously and eventually reach equilibrium:\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> Note: The arrows of different colors in the diagram represent different types of forces. In the actual layout, these forces are invisible and also affected by other forces.\n\n- **Link Force**: Imagine nodes connected by rubber bands, which pull connected nodes to a suitable distance. The tightness of the rubber band is the force strength, and the ideal length is the distance we set.\n- **Many-Body Force**: Similar to magnets, it allows all nodes to attract or repel each other. When the force strength is negative, nodes repel each other (like like poles of magnets); when positive, they attract (like opposite poles). This force determines the density of the graph.\n- **Center Force**: Like all nodes are tied to the center of the canvas by an invisible string. This force prevents nodes from drifting too far and keeps the graph centered.\n- **Collision Force**: Treats nodes as solid balls. When nodes get too close, they automatically bounce apart. This force mainly prevents node overlap and improves readability.\n- **Radial Force**: Imagine an invisible ring that attracts nodes to the ring. By setting the radius and force strength, nodes can form a beautiful circular layout.\n\n### Iteration System\n\nLayout calculation is an iterative process with two key concepts:\n\n#### Alpha Value (Energy)\n\nLike the \"energy\" of the layout, it determines how vigorously nodes move:\n\n- **Initial state**: Alpha = 1, nodes move vigorously\n- **During calculation**: Alpha gradually decreases, node movement slows\n- **End state**: When Alpha < alphaMin, nodes stop moving\n\n#### Iterations\n\nControls the number of times forces are applied in each calculation:\n\n- **Effect**: The larger the value, the more precise the layout, but the slower the computation\n- **Adjustment**:\n  - Simple graphs: use the default value\n  - Complex graphs: increase the number of iterations as needed\n  - Real-time interaction: use fewer iterations\n\n> Tip: Iterations and alpha value work together. Increasing iterations makes each step more precise, while alpha controls the overall progress.\n\n## Options\n\n| Property        | Description                                        | Type                                       | Default    | Required |\n| --------------- | -------------------------------------------------- | ------------------------------------------ | ---------- | -------- |\n| type            | Layout type                                        | string                                     | 'd3-force' | ✓        |\n| centerX         | Layout center x coordinate                         | number                                     | width / 2  |          |\n| centerY         | Layout center y coordinate                         | number                                     | height / 2 |          |\n| centerStrength  | Center force strength                              | number                                     | -          |          |\n| nodeSize        | Node size (diameter), for collision detection      | number \\| ((node, index, nodes) => number) | 10         |          |\n| nodeSpacing     | Extra spacing between nodes                        | number \\| ((node, index, nodes) => number) | 0          |          |\n| iterations      | Number of force iterations, higher is more precise | number                                     | -          |          |\n| onTick          | Callback for each iteration, for real-time results | (data: LayoutMapping) => void              | -          |          |\n| forceSimulation | Custom force simulation, defaults to d3.js method  | Simulation<NodeDatum, EdgeDatum>           | -          |          |\n| randomSource    | Function to generate random numbers                | () => number                               | -          |          |\n\n### Iteration Control\n\n| Property      | Description                                          | Type   | Default | Required |\n| ------------- | ---------------------------------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold, controls activity     | number | 1       |          |\n| alphaMin      | Minimum threshold to stop, when alpha < this, stop   | number | 0.001   |          |\n| alphaDecay    | Decay rate of alpha, [0, 1], 0.028 ≈ 300 iterations  | number | 0.028   |          |\n| alphaTarget   | Target alpha, system tries to converge to this value | number | 0       |          |\n| velocityDecay | Velocity decay factor, higher means slower movement  | number | 0.4     |          |\n\n### Force Model Options\n\n#### Link Force (link)\n\n| Property        | Description                                  | Type                                       | Default     | Required |\n| --------------- | -------------------------------------------- | ------------------------------------------ | ----------- | -------- |\n| link.id         | Function to generate edge id                 | (edge, index, edges) => string             | (e) => e.id |          |\n| link.distance   | Ideal edge length                            | number \\| ((edge, index, edges) => number) | 30          |          |\n| link.strength   | Force strength, higher means closer to ideal | number \\| ((edge, index, edges) => number) | 1           |          |\n| link.iterations | Number of link force iterations              | number                                     | 1           |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                                                     | Type                                       | Default  | Required |\n| -------------------- | --------------------------------------------------------------- | ------------------------------------------ | -------- | -------- |\n| manyBody.strength    | Force strength, negative for repulsion, positive for attraction | number \\| ((node, index, nodes) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy, smaller is more accurate                   | number                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum distance, prevents excessive force                      | number                                     | 1        |          |\n| manyBody.distanceMax | Maximum distance, beyond which no force is applied              | number                                     | Infinity |          |\n\n#### Center Force (center)\n\n| Property        | Description                                   | Type   | Default | Required |\n| --------------- | --------------------------------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate                           | number | -       |          |\n| center.y        | Center y coordinate                           | number | -       |          |\n| center.strength | Force strength, higher means closer to center | number | -       |          |\n\n> Note: In `5.1`, `centerX` / `centerY` are the recommended shortcut fields. If you configure the `center` force directly, it follows the native `d3-force` style.\n\n#### Collision Force (collide)\n\n| Property           | Description                                     | Type                                       | Default | Required |\n| ------------------ | ----------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| collide.radius     | Collision radius, nodes repel if closer         | number \\| ((node, index, nodes) => number) | 10      |          |\n| collide.strength   | Force strength, higher means stronger repulsion | number                                     | 1       |          |\n| collide.iterations | Number of collision iterations                  | number                                     | 1       |          |\n\n#### Radial Force (radial)\n\n| Property        | Description                                   | Type                                       | Default | Required |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| radial.strength | Force strength, higher means closer to radius | number \\| ((node, index, nodes) => number) | 0.1     |          |\n| radial.radius   | Target radius, nodes are attracted to circle  | number \\| ((node, index, nodes) => number) | 100     |          |\n| radial.x        | Center x coordinate                           | number                                     | 0       |          |\n| radial.y        | Center y coordinate                           | number                                     | 0       |          |\n\n#### X Axis Force (x)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| x.strength | Force strength in x direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| x.x        | Target x coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n#### Y Axis Force (y)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| y.strength | Force strength in y direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| y.y        | Target y coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n## Code Examples\n\n### Prevent Node Overlap\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\nSee [Example - Prevent Node Overlap in Force-Directed Layout](/en/examples/layout/force-directed/#prevent-overlap)\n\n### Team Clustering Layout\n\nThis example shows how to use force-directed layout for team clustering, where nodes of different teams automatically cluster together.\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // Team A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // Team B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // Team C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // Team A internal connections\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // Team B internal connections\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // Team C internal connections\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // Few connections between teams\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// Create mock data with nodes from different teams\nconst data = {\n  nodes: [\n    // Team A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // Team B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // Team C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // Team A internal connections\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // Team B internal connections\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // Team C internal connections\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // Few connections between teams\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\nMain configuration notes:\n\n- `link.distance`: Shorter within teams, longer between teams\n- `link.strength`: Stronger within teams, weaker between teams\n- `manyBody.strength`: Controls repulsion between nodes\n- `collide`: Prevents node overlap\n- `center`: Keeps the layout centered\n\nSee also [Customize parameters for different nodes](/en/examples/layout/force-directed/#functional-params).\n","frontmatter":{"title":"D3 Force-Directed Layout","order":"8"},"isInternal":false,"tokens":4468,"sizeBytes":17876},{"name":"D3ForceLayout.zh.md","path":"packages/site/docs/manual/layout/D3ForceLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/D3ForceLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: D3力导向布局 D3Force\norder: 8\n---\n\n## 概述\n\nD3Force 布局是基于 [d3-force](https://d3js.org/d3-force) 实现的力导向布局。它通过模拟物理力的作用（如引力、斥力、碰撞等），使图布局达到一个能量最小的稳定状态。\n\n这种布局的主要特点是：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的理想长度\n   - 可以固定某些重要节点的位置\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img alt=\"D3Force 布局示意图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 核心概念\n\n### 力系统 Force System\n\nD3Force 布局通过模拟五种不同的力来实现自动布局。想象一个物理世界，这些力同时作用，最终达到平衡：\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> 注：图中不同颜色的箭头代表不同类型的力，实际布局中这些力是无形的，同时也会受其他力影响。\n\n- **链接力**（Link Force）：想象节点之间连着橡皮筋，可以把相连的节点拉到合适的距离。橡皮筋的松紧度就是力的强度（strength），理想长度就是我们设置的距离（distance）。\n- **多体力**（Many-Body Force）：类似磁铁的效果，可以让所有节点互相吸引或排斥。力的强度为负值时节点会互相排斥（像相同磁极），为正值时会互相吸引（像相反磁极）。这个力决定了图的疏密程度。\n- **中心力**（Center Force）：就像所有节点都被一根看不见的绳子拴在画布中心。这个力可以防止节点飘得太远，让整个图保持在画布的中心位置。\n- **碰撞力**（Collision Force）：让节点变成有实体大小的小球，当节点太近时会自动弹开。这个力主要用来防止节点重叠，提高图的可读性。\n- **径向力**（Radial Force）：想象有一个看不见的圆环，这个力会把节点吸引到圆环上。通过设置圆的半径和力的强度，可以让节点形成漂亮的环形布局。\n\n### 迭代系统（Iteration System）\n\n布局计算是一个反复调整的过程，包含两个关键概念：\n\n#### Alpha 值（活力值）\n\n就像布局的\"能量\"，决定节点移动的剧烈程度：\n\n- **初始状态**：Alpha = 1，节点移动剧烈\n- **计算过程**：Alpha 值逐渐降低，节点移动变缓\n- **结束状态**：当 Alpha < alphaMin 时，节点停止移动\n\n#### 迭代次数（Iterations）\n\n控制每次计算时力的作用次数：\n\n- **作用**：值越大，布局越精确，但计算越慢\n- **调节**：\n  - 简单图：使用默认值即可\n  - 复杂图：可以适当增加迭代次数\n  - 实时交互：建议使用较小的迭代次数\n\n> 提示：迭代次数（iterations）和活力值（alpha）是相互配合的。增加迭代次数可以让每一步计算更精确，而活力值则控制整体计算的进度。\n\n## 配置项\n\n| 属性            | 描述                                          | 类型                                       | 默认值     | 必选 |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ---------- | ---- |\n| type            | 布局类型                                      | string                                     | 'd3-force' | ✓    |\n| centerX         | 布局中心点 x 坐标                             | number                                     | width / 2  |      |\n| centerY         | 布局中心点 y 坐标                             | number                                     | height / 2 |      |\n| centerStrength  | 中心力强度                                    | number                                     | -          |      |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠    | number \\| ((node, index, nodes) => number) | 10         |      |\n| nodeSpacing     | 节点间额外间距                                | number \\| ((node, index, nodes) => number) | 0          |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大  | number                                     | -          |      |\n| onTick          | 每次迭代的回调函数，用于实时获取布局结果      | (data: LayoutMapping) => void              | -          |      |\n| forceSimulation | 自定义力模拟方法，若不指定则使用 d3.js 的方法 | Simulation<NodeDatum, EdgeDatum>           | -          |      |\n| randomSource    | 用于生成随机数的函数                          | () => number                               | -          |      |\n\n### 迭代控制\n\n| 属性          | 描述                                                   | 类型   | 默认值 | 必选 |\n| ------------- | ------------------------------------------------------ | ------ | ------ | ---- |\n| alpha         | 当前迭代的收敛阈值，控制布局的活跃程度                 | number | 1      |      |\n| alphaMin      | 停止迭代的最小阈值，当 alpha 小于该值时停止迭代        | number | 0.001  |      |\n| alphaDecay    | 收敛阈值的衰减率，范围 [0, 1]，0.028 对应约 300 次迭代 | number | 0.028  |      |\n| alphaTarget   | 目标收敛阈值，系统会尝试将 alpha 收敛到该值            | number | 0      |      |\n| velocityDecay | 速度衰减因子，值越大节点运动越缓慢                     | number | 0.4    |      |\n\n### 力模型配置\n\n#### 链接力（link）\n\n| 属性            | 描述                               | 类型                                       | 默认值      | 必选 |\n| --------------- | ---------------------------------- | ------------------------------------------ | ----------- | ---- |\n| link.id         | 边的 id 生成函数                   | (edge, index, edges) => string             | (e) => e.id |      |\n| link.distance   | 理想边长，边会趋向于该长度         | number \\| ((edge, index, edges) => number) | 30          |      |\n| link.strength   | 力的强度，值越大边长越接近理想边长 | number \\| ((edge, index, edges) => number) | 1           |      |\n| link.iterations | 链接力的迭代次数                   | number                                     | 1           |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                                                  | 类型                                       | 默认值   | 必选 |\n| -------------------- | ----------------------------------------------------- | ------------------------------------------ | -------- | ---- |\n| manyBody.strength    | 力的强度，负值为斥力，正值为引力                      | number \\| ((node, index, nodes) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数，值越小越精确但性能消耗越大 | number                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离，防止力过大                              | number                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离，超过该距离的节点不产生力                | number                                     | Infinity |      |\n\n#### 中心力（center）\n\n| 属性            | 描述                               | 类型   | 默认值 | 必选 |\n| --------------- | ---------------------------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标                      | number | -      |      |\n| center.y        | 中心点 y 坐标                      | number | -      |      |\n| center.strength | 力的强度，值越大节点越趋向于中心点 | number | -      |      |\n\n> 补充：5.1 中推荐优先使用 `centerX` / `centerY` 作为快捷配置；如果直接配置 `center` force，则按 d3-force 原生写法生效。\n\n#### 碰撞力（collide）\n\n| 属性               | 描述                                   | 类型                                       | 默认值 | 必选 |\n| ------------------ | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| collide.radius     | 碰撞半径，小于该距离的节点会产生排斥力 | number \\| ((node, index, nodes) => number) | 10     |      |\n| collide.strength   | 力的强度，值越大排斥效果越明显         | number                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数                     | number                                     | 1      |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述                                   | 类型                                       | 默认值 | 必选 |\n| --------------- | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| radial.strength | 力的强度，值越大节点越趋向于目标半径   | number \\| ((node, index, nodes) => number) | 0.1    |      |\n| radial.radius   | 目标半径，节点会被吸引到该半径的圆周上 | number \\| ((node, index, nodes) => number) | 100    |      |\n| radial.x        | 圆心 x 坐标                            | number                                     | 0      |      |\n| radial.y        | 圆心 y 坐标                            | number                                     | 0      |      |\n\n#### X 轴力（x）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| x.strength | X 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| x.x        | 目标 x 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n#### Y 轴力（y）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| y.strength | Y 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| y.y        | 目标 y 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n## 代码示例\n\n### 防止节点重叠\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\n效果见 [示例 - 力导向布局防止节点重叠](/examples/layout/force-directed/#prevent-overlap)\n\n### 团队聚类布局\n\n该示例展示了如何使用力导向布局实现团队聚类效果，不同团队的节点会自动聚集在一起。\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // 团队 A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // 团队 B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // 团队 C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // 团队 A 内部连接\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // 团队 B 内部连接\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // 团队 C 内部连接\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // 团队间的少量连接\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 创建模拟数据，包含不同团队的节点\nconst data = {\n  nodes: [\n    // 团队 A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // 团队 B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // 团队 C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // 团队 A 内部连接\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // 团队 B 内部连接\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // 团队 C 内部连接\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // 团队间的少量连接\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\n主要配置说明：\n\n- `link.distance`：团队内部距离短，团队间距离长\n- `link.strength`：团队内部连接强度大，团队间连接强度小\n- `manyBody.strength`：控制节点间排斥力\n- `collide`：防止节点重叠\n- `center`：保持整体布局在画布中心\n\n还可以参考 [定制不同节点的参数](/examples/layout/force-directed/#functional-params) 示例。\n","frontmatter":{"title":"D3力导向布局 D3Force","order":"8"},"isInternal":false,"tokens":3385,"sizeBytes":17577},{"name":"DagreLayout.en.md","path":"packages/site/docs/manual/layout/DagreLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/DagreLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Dagre Layout\norder: 9\n---\n\n# Dagre Layout\n\n## Overview\n\nDagre is a hierarchical layout suitable for directed acyclic graphs (DAGs). It can automatically handle the direction and spacing between nodes and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## Options\n\n> For more options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Illustration\" />\n\n| Property        | Description                                                                                                                                | Type                                                | Default           | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- | ----------------- | -------- |\n| type            | Layout type                                                                                                                                | `dagre`                                             | -                 | ✓        |\n| rankdir         | Layout direction, options                                                                                                                  | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |          |\n| align           | Node alignment, options                                                                                                                    | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |          |\n| nodesep         | Node spacing (px). For `TB` or `BT`, it is the horizontal spacing; for `LR` or `RL`, it is the vertical spacing                            | number                                              | 50                |          |\n| ranksep         | Rank spacing (px). For `TB` or `BT`, it is the vertical spacing between adjacent ranks; for `LR` or `RL`, it is the horizontal spacing     | number                                              | 100               |          |\n| ranker          | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                 | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |          |\n| directed        | Whether to treat the graph as directed                                                                                                     | boolean                                             | true              |          |\n| compound        | Whether to support nested structures                                                                                                       | boolean                                             | true              |          |\n| multigraph      | Whether to allow multi-edges                                                                                                               | boolean                                             | true              |          |\n| nodeSize        | G6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |          |\n| edgeMinLen      | Minimum number of ranks crossed by an edge                                                                                                 | number \\| (edge) => number                          | 1                 |          |\n| edgeWeight      | Edge weight, used to affect optimization priority                                                                                          | number \\| (edge) => number                          |                   |          |\n| edgeLabelSize   | Edge label size, used to reserve layout space                                                                                              | number[] \\| (edge) => number[]                      |                   |          |\n| edgeLabelPos    | Edge label position                                                                                                                        | string \\| (edge) => string                          |                   |          |\n| edgeLabelOffset | Offset between the label and the edge                                                                                                      | number \\| (edge) => number                          |                   |          |\n\n> Note: `dagre` does not require configuring `controlPoints` separately. G6 automatically converts the polyline points returned by the layout into `style.controlPoints` on the edge.\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`, **Default**: `TB`\n\nLayout direction\n\n- `TB`: Top to Bottom;\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='Top to Bottom Layout'/>\n\n- `BT`: Bottom to Top;\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='Bottom to Top Layout'/>\n\n- `LR`: Left to Right;\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='Left to Right Layout'/>\n\n- `RL`: Right to Left.\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='Right to Left Layout'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`, **Default**: `UL`\n\nNode alignment\n\n- `UL`: Upper Left\n- `UR`: Upper Right\n- `DL`: Down Left\n- `DR`: Down Right\n\n### nodesep\n\n> number, **Default**: 50\n\nNode spacing (px). For `TB` or `BT`, it's the horizontal spacing; for `LR` or `RL`, it's the vertical spacing\n\n### ranksep\n\n> number, **Default**: 50\n\nRank spacing (px). For `TB` or `BT`, it's the vertical spacing between ranks; for `LR` or `RL`, it's the horizontal spacing between ranks\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`, **Default**: `network-simplex`\n\nAlgorithm for assigning ranks to nodes, supports three algorithms:\n\n- `longest-path`: Uses DFS to recursively find the longest path for each node. Simple and fast, but may result in many long edges.\n- `tight-tree`: An optimization algorithm to reduce the number of long edges. It first uses `longest-path` to compute initial ranks, then adjusts slack edges to build a feasible tree.\n- `network-simplex`: Based on [A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf), iteratively modifies node ranks to minimize slack edges.\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]`\n\n```js\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n## Applicable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, automatically handling direction and spacing between nodes.\n- **Dependency Graphs**: Display dependencies between packages or modules.\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks.\n\n## Related Documentation\n\n> The following documents can help you better understand Dagre layout\n\n- [Graph Layout Algorithms｜Detailed Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Interpretation of Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","frontmatter":{"title":"Dagre Layout","order":"9"},"isInternal":false,"tokens":2055,"sizeBytes":8221},{"name":"DagreLayout.zh.md","path":"packages/site/docs/manual/layout/DagreLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/DagreLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Dagre 布局\norder: 9\n---\n\n## 概述\n\nDagre 是一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## 配置项\n\n> 更多配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性            | 描述                                                                                                                                            | 类型                                                | 默认值            | 必选 |\n| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ----------------- | ---- |\n| type            | 布局类型                                                                                                                                        | `dagre`                                             | -                 | ✓    |\n| rankdir         | 布局方向，可选值                                                                                                                                | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |      |\n| align           | 节点对齐方式，可选值                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |      |\n| nodesep         | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                              | number                                              | 50                |      |\n| ranksep         | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                            | number                                              | 100               |      |\n| ranker          | 为每个节点分配等级的算法，共支持三种算法，分别是：`longest-path`、`tight-tree`、`network-simplex`                                               | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |      |\n| directed        | 是否按有向图处理                                                                                                                                | boolean                                             | true              |      |\n| compound        | 是否支持嵌套结构                                                                                                                                | boolean                                             | true              |      |\n| multigraph      | 是否允许多重边                                                                                                                                  | boolean                                             | true              |      |\n| nodeSize        | G6 自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个 number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |      |\n| edgeMinLen      | 边跨越的最小层数                                                                                                                                | number \\| (edge) => number                          | 1                 |      |\n| edgeWeight      | 边权重，用于影响优化优先级                                                                                                                      | number \\| (edge) => number                          |                   |      |\n| edgeLabelSize   | 边标签尺寸，用于预留空间                                                                                                                        | number[] \\| (edge) => number[]                      |                   |      |\n| edgeLabelPos    | 边标签位置                                                                                                                                      | string \\| (edge) => string                          |                   |      |\n| edgeLabelOffset | 标签与边的偏移                                                                                                                                  | number \\| (edge) => number                          |                   |      |\n\n> 补充：`dagre` 不需要单独配置 `controlPoints`，G6 会把布局输出的折线点自动转换为边的 `style.controlPoints`。\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`， **Default**: `TB`\n\n布局方向\n\n- `TB`：从上到下；\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='：从上到下布局'/>\n\n- `BT`：从下到上；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='从下到上布局'/>\n\n- `LR`：从左到右；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='从左到右布局'/>\n\n- `RL`：从右到左。\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='水平布局'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`， **Default**: `UL`\n\n节点对齐方式\n\n- `UL`：左上对齐\n- `UR`：右上对齐\n- `DL`：左下对齐\n- `DR`：右下对齐\n\n### nodesep\n\n> number， **Default**: 50\n\n节点间距（px）。在rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距\n\n### ranksep\n\n> number， **Default**: 50\n\n层间距（px）。在rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`， **Default**: `network-simplex`\n\n为每个节点分配层级的算法，共支持三种算法，分别是：\n\n- `longest-path`： 最长路径算法，使用DFS深度优先搜索，递归查找每个节点的最长路径。优点是计算简单速度快，但会导致长边过多；\n- `tight-tree`： 紧凑树算法，一种优化算法，目的是减少长边的数量。先用最长路径算法`longest-path`计算出初始层级，然后调整松弛边的长度，从而构建可行树。\n- `network-simplex`： 网络单形法，参考算法[A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf)，核心思想是迭代修改节点的层级，缩小松弛边。\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]`\n\n```js\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n### controlPoints\n\n> boolean， **Default**: false\n\n是否保留边的控制点。\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n","frontmatter":{"title":"Dagre 布局","order":"9"},"isInternal":false,"tokens":1702,"sizeBytes":8611},{"name":"DendrogramLayout.en.md","path":"packages/site/docs/manual/layout/DendrogramLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/DendrogramLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Dendrogram Layout\norder: 10\n---\n\n## Overview\n\nThe dendrogram layout is suitable for visualizing hierarchical clustering data. Its feature is that all child nodes are laid out on the same level, node size is not considered, and each node is treated as 1px.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='Dendrogram Layout Example'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"Dendrogram Layout Options Illustration\" />\n\n| Property  | Description                                            | Type                                       | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------------------------------ | ------- | -------- |\n| type      | Layout type                                            | `dendrogram`                               | -       | ✓        |\n| direction | Layout direction, [options](#direction)                | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`    |          |\n| nodeSep   | Node spacing, distance between nodes on the same level | number                                     | 20      |          |\n| rankSep   | Rank spacing, distance between different levels        | number                                     | 200     |          |\n| radial    | Whether to enable radial layout, [see below](#radial)  | boolean                                    | false   |          |\n\n### direction\n\nTree layout direction options:\n\n- `TB`: Root at the top, layout downward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB direction'/>\n\n- `BT`: Root at the bottom, layout upward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT direction'/>\n\n- `LR`: Root at the left, layout to the right\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR direction'/>\n\n- `RL`: Root at the right, layout to the left\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL direction'/>\n\n- `H`: Root in the middle, horizontal symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H direction'/>\n\n- `V`: Root in the middle, vertical symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V direction'/>\n\n### radial\n\nWhether to enable radial layout mode. When enabled, nodes are distributed radially around the root node.\n\nIf `radial` is set to `true`, it is recommended to set `direction` to `'LR'` or `'RL'` for best results.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='Radial Layout'/>\n","frontmatter":{"title":"Dendrogram Layout","order":"10"},"isInternal":false,"tokens":796,"sizeBytes":3184},{"name":"DendrogramLayout.zh.md","path":"packages/site/docs/manual/layout/DendrogramLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/DendrogramLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 生态树 Dendrogram\norder: 10\n---\n\n## 概述\n\n生态树布局适用于层次聚类数据的可视化，其特点是所有子节点布局在同一层级，不考虑节点大小，每个节点被当成 1px 处理。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='生态树布局示例'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"生态树配置项图解\" />\n\n| 属性      | 描述                                           | 类型                                       | 默认值 | 必选 |\n| --------- | ---------------------------------------------- | ------------------------------------------ | ------ | ---- |\n| type      | 布局类型                                       | `dendrogram`                               | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                 | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`   |      |\n| nodeSep   | 节点间距，即同一层级节点之间的距离，单位为像素 | number                                     | 20     |      |\n| rankSep   | 层级间距，即不同层级之间的距离，单位为像素     | number                                     | 200    |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)            | boolean                                    | false  |      |\n\n### direction\n\n树布局的方向，有以下选项：\n\n- `TB`：根节点在上，往下布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB方向'/>\n\n- `BT`：根节点在下，往上布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT方向'/>\n\n- `LR`：根节点在左，往右布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR方向'/>\n\n- `RL`：根节点在右，往左布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL方向'/>\n\n- `H`：根节点在中间，水平对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H方向'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V方向'/>\n\n### radial\n\n是否启用辐射状布局模式。启用后，节点将以根节点为中心呈辐射状分布。\n\n若 `radial` 设置为 `true`，建议将 `direction` 设置为 `'LR'` 或 `'RL'` 以获得最佳效果。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='辐射状布局'/>\n","frontmatter":{"title":"生态树 Dendrogram","order":"10"},"isInternal":false,"tokens":610,"sizeBytes":3071},{"name":"Fishbone.en.md","path":"packages/site/docs/manual/layout/Fishbone.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/Fishbone.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Fishbone Layout\norder: 11\n---\n\n## Overview\n\nFishbone layout is a graphical layout specifically designed for representing hierarchical data. By simulating the shape of a fishbone, it arranges data nodes according to their hierarchy, making the hierarchical relationships of the data clearer and more intuitive. Fishbone layout is especially suitable for datasets that need to show causality, hierarchy, or classification information.\n\n## Use Cases\n\n- Displaying hierarchical data, such as organizational structures or classification systems\n- Showing problem analysis processes, such as fault analysis or quality analysis\n- Displaying decision processes, such as decision trees or factor analysis\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## Options\n\n| Property               | Description                                                                                      | Type                                                                                                                                   | Default  | Required |\n| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- |\n| type                   | Layout type                                                                                      | `fishbone`                                                                                                                             | -        | ✓        |\n| direction              | Layout direction, `RL` (right to left, head on right), `LR` (left to right, head on left)        | `RL` \\| `LR`                                                                                                                           | `RL`     |          |\n| hGap                   | Horizontal gap                                                                                   | number                                                                                                                                 | -        |          |\n| vGap                   | Vertical gap                                                                                     | number                                                                                                                                 | -        |          |\n| getRibSep              | Function to get rib gap                                                                          | (node: NodeData) => number                                                                                                             | () => 60 |          |\n| width                  | Layout width                                                                                     | number                                                                                                                                 | -        |          |\n| height                 | Layout height                                                                                    | number                                                                                                                                 | -        |          |\n| nodeSize               | Node size                                                                                        | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (effective when preLayout is true)                 | boolean                                                                                                                                | -        |          |\n| nodeFilter             | Nodes to participate in this layout                                                              | (node: NodeData) => boolean                                                                                                            | -        |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements (not suitable for pipeline layout) | boolean                                                                                                                                | -        |          |\n\n## Code Example\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Real Case\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone Layout](/en/examples/layout/fishbone/#basic)\n","frontmatter":{"title":"Fishbone Layout","order":"11"},"isInternal":false,"tokens":3340,"sizeBytes":13359},{"name":"Fishbone.zh.md","path":"packages/site/docs/manual/layout/Fishbone.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/Fishbone.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 鱼骨布局 Fishbone\norder: 11\n---\n\n## 概述\n\n鱼骨布局是一种专门用于表示层次结构数据的图形布局方式。它通过模拟鱼骨的形状，将数据节点按照层次结构排列，使得数据的层次关系更加清晰直观。鱼骨布局特别适用于需要展示因果关系、层次结构或分类信息的数据集。\n\n## 使用场景\n\n- 需要展示层次结构数据，如组织结构、分类体系\n- 需要展示问题分析过程，如故障分析、质量分析\n- 需要展示决策过程，如决策树、影响因素分析\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## 配置项\n\n| 属性                   | 描述                                                       | 类型                                                                                                                                   | 默认值   | 必选 |\n| ---------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type                   | 布局类型                                                   | `fishbone`                                                                                                                             | -        | ✓    |\n| direction              | 排布方向，`RL` 从右到左，鱼头在右；`LR` 从左到右，鱼头在左 | `RL` \\| `LR`                                                                                                                           | `RL`     |      |\n| hGap                   | 水平间距                                                   | number                                                                                                                                 | -        |      |\n| vGap                   | 垂直间距                                                   | number                                                                                                                                 | -        |      |\n| getRibSep              | 获取鱼骨间距                                               | (node: NodeData) => number                                                                                                             | () => 60 |      |\n| width                  | 布局宽度                                                   | number                                                                                                                                 | -        |      |\n| height                 | 布局高度                                                   | number                                                                                                                                 | -        |      |\n| nodeSize               | 节点大小                                                   | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局，当 preLayout 为 true 时生效        | boolean                                                                                                                                | -        |      |\n| nodeFilter             | 参与该布局的节点                                           | (node: NodeData) => boolean                                                                                                            | -        |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局，不适用于流水线布局     | boolean                                                                                                                                | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone布局](/examples/layout/fishbone/#basic)\n","frontmatter":{"title":"鱼骨布局 Fishbone","order":"11"},"isInternal":false,"tokens":3038,"sizeBytes":12808},{"name":"ForceAtlas2Layout.en.md","path":"packages/site/docs/manual/layout/ForceAtlas2Layout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ForceAtlas2Layout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ForceAtlas2 Force-directed Layout\norder: 12\n---\n\n## Overview\n\nForceAtlas2 is a force-directed layout algorithm that optimizes node positions by simulating forces in a physical system. This layout is especially suitable for visualizing large-scale network data, effectively revealing relationships and cluster structures among nodes.\n\n## Use Cases\n\n- Social network analysis: Display user relationship networks, with node degree reflecting user influence\n- Knowledge graphs: Show associations between concepts, discover knowledge domains through clustering\n- System architecture diagrams: Show dependencies between system components, highlight core components via hub mode\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## Options\n\n| Property       | Description                                                                                                                                                                   | Type                                | Default  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | -------- |\n| type           | Layout type, must be `force-atlas2`                                                                                                                                           | `force-atlas2`                      | -        | ✓        |\n| maxIteration   | Maximum number of iterations                                                                                                                                                  | number                              | 500      |          |\n| minMovement    | Convergence threshold                                                                                                                                                         | number                              | 0.4      |          |\n| barnesHut      | Whether to enable quadtree acceleration. When enabled, improves performance for large graphs but may affect layout quality. By default, enabled if node count > 250.          | boolean                             | -        |          |\n| dissuadeHubs   | Whether to enable hub mode. If true, nodes with higher in-degree are more likely to be placed at the center than those with high out-degree                                   | boolean                             | false    |          |\n| height         | Layout height. Defaults to container height                                                                                                                                   | number                              | -        |          |\n| kg             | Gravity coefficient. The larger the value, the more concentrated the layout is at the center                                                                                  | number                              | 1        |          |\n| kr             | Repulsion coefficient. Adjusts the compactness of the layout. The larger the value, the looser the layout                                                                     | number                              | 5        |          |\n| ks             | Controls the speed of node movement during iteration                                                                                                                          | number                              | 0.1      |          |\n| ksmax          | Maximum node movement speed during iteration                                                                                                                                  | number                              | 10       |          |\n| mode           | Clustering mode. In `linlog` mode, clusters are more compact                                                                                                                  | `normal` \\| `linlog`                | `normal` |          |\n| nodeSize       | Node size (diameter). Used for repulsion calculation when `preventOverlap` is enabled. If not set, uses `data.size` in node data                                              | Size \\| ((node?: Node) => Size)     | -        |          |\n| nodeSpacing    | Spacing between nodes                                                                                                                                                         | number \\| ((node?: Node) => number) | -        |          |\n| onTick         | Callback for each iteration                                                                                                                                                   | (data: LayoutMapping) => void       | -        |          |\n| preventOverlap | Whether to prevent node overlap. When enabled, layout considers node size to avoid overlap. Node size is specified by `nodeSize` or `data.size` in node data                  | boolean                             | false    |          |\n| prune          | Whether to enable auto-pruning. By default, enabled if node count > 100. Pruning speeds up convergence but may reduce layout quality. Set to false to disable auto-activation | boolean                             | -        |          |\n| tao            | Tolerance for stopping oscillation when layout is near convergence                                                                                                            | number                              | 0.1      |          |\n| width          | Layout width. Defaults to container width                                                                                                                                     | number                              | -        |          |\n| center         | Layout center, format [x, y]. Each node is attracted to this point, gravity controlled by `kg`. If not set, uses canvas center                                                | [number, number]                    | -        |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## Real Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2 Layout](/en/examples/layout/force-directed/#atlas2)\n","frontmatter":{"title":"ForceAtlas2 Force-directed Layout","order":"12"},"isInternal":false,"tokens":2578,"sizeBytes":10314},{"name":"ForceAtlas2Layout.zh.md","path":"packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ForceAtlas2 力导向布局\norder: 12\n---\n\n## 概述\n\nForceAtlas2 是一种基于力导向的布局算法，它通过模拟物理系统中的力来优化节点位置。该布局特别适用于大规模网络数据的可视化，能够有效地展示节点之间的关系和聚类结构。\n\n## 使用场景\n\n- 社交网络分析：展示用户之间的关系网络，通过节点度数反映用户影响力\n- 知识图谱：展示概念之间的关联关系，通过聚类效果发现知识领域\n- 系统架构图：展示系统组件之间的依赖关系，通过 hub 模式突出核心组件\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                 | 类型                                | 默认值   | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | ---- |\n| type           | 布局类型，必须为 `force-atlas2`                                                                                                                                      | `force-atlas2`                      | -        | ✓    |\n| maxIteration   | 最大迭代次数                                                                                                                                                         | number                              | 500      |      |\n| minMovement    | 收敛阈值                                                                                                                                                             | number                              | 0.4      |      |\n| barnesHut      | 是否开启四叉树加速，开启后可以提升大规模图的布局性能，但可能会影响布局质量。默认情况下为 undefined，当节点数量大于 250 时它将会被激活。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| dissuadeHubs   | 是否开启 hub 模式。若为 true，相比与出度大的节点，入度大的节点将会有更高的优先级被放置在中心位置                                                                     | boolean                             | false    |      |\n| height         | 布局高度，默认使用容器高度                                                                                                                                           | number                              | -        |      |\n| kg             | 重力系数，`kg` 越大，布局越聚集在中心                                                                                                                                | number                              | 1        |      |\n| kr             | 斥力系数，可用于调整布局的紧凑程度。kr 越大，布局越松散                                                                                                              | number                              | 5        |      |\n| ks             | 控制迭代过程中，节点移动的速度                                                                                                                                       | number                              | 0.1      |      |\n| ksmax          | 迭代过程中，最大的节点移动的速度上限                                                                                                                                 | number                              | 10       |      |\n| mode           | 聚类模式，`linlog` 模式下，聚类将更加紧凑                                                                                                                            | `normal` \\| `linlog`                | `normal` |      |\n| nodeSize       | 节点大小（直径）。当开启 `preventOverlap` 时，用于计算节点之间的斥力。如果不设置，则使用节点数据中的 size 属性                                                       | Size \\| ((node?: Node) => Size)     | -        |      |\n| nodeSpacing    | 节点间距                                                                                                                                                             | number \\| ((node?: Node) => number) | -        |      |\n| onTick         | 每一次迭代的回调函数                                                                                                                                                 | (data: LayoutMapping) => void       | -        |      |\n| preventOverlap | 是否防止节点重叠。开启后，布局会考虑节点大小，避免节点重叠                                                                                                           | boolean                             | false    |      |\n| prune          | 是否开启自动剪枝模式。默认情况下为 undefined，当节点数量大于 100 时它将会被激活。注意，剪枝能够提高收敛速度，但可能会降低图的布局质量。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| tao            | 迭代接近收敛时停止震荡的容忍度                                                                                                                                       | number                              | 0.1      |      |\n| width          | 布局宽度，默认使用容器宽度                                                                                                                                           | number                              | -        |      |\n| center         | 布局中心点，用于指定重力的中心，格式为 [x, y]。每个节点都会受到一个指向该中心点的重力，重力大小由 `kg` 参数控制。如果不设置，则使用画布中心点                        | [number, number]                    | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2布局](/examples/layout/force-directed/#atlas2)\n","frontmatter":{"title":"ForceAtlas2 力导向布局","order":"12"},"isInternal":false,"tokens":2266,"sizeBytes":10468},{"name":"ForceLayout.en.md","path":"packages/site/docs/manual/layout/ForceLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ForceLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Force-directed Layout\norder: 13\n---\n\n## Overview\n\nForce-directed layout is a graph layout algorithm based on physical simulation that determines node positions by simulating attraction and repulsion forces between nodes. This layout is particularly suitable for displaying complex relationship networks, such as social networks and knowledge graphs.\n\nThe force-directed layout automatically calculates and adjusts node positions to maintain appropriate distances between connected nodes while minimizing edge crossings. During the layout process, it simulates a physical system where nodes repel each other like charged particles, and edges connect nodes like springs.\n\nKey features of force-directed layout include:\n\n1. **Automatic Arrangement**: No need to manually set node positions, the system automatically finds suitable positions\n2. **Real-time Adjustment**: When you drag a node, other nodes will adjust their positions in real-time\n3. **Flexible Configuration**:\n   - Can adjust attraction and repulsion forces between nodes\n   - Can set edge lengths\n   - Can prevent node overlap\n4. **Animation Effects**: Smooth animations during node movement make changes more natural\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='Force-directed Layout Example'/>\n\n## Core Concepts\n\n### Basic Principles of Force-directed Layout\n\nForce-directed layout is a graph layout algorithm based on physical simulation that models nodes and edges as a physical system:\n\n- Nodes are treated as physical particles\n- Edges are treated as springs\n- The entire system reaches its lowest energy state through physical simulation\n\n### Detailed Core Forces\n\n#### Node Repulsion\n\n- **Physical Model**: Coulomb's Law\n- **Function**: Prevents node overlap and ensures more uniform node distribution, where `factor` and `coulombDisScale` control the overall strength and range of repulsion.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='Repulsion Force'/>\n\n  - k: Repulsion coefficient (`factor` / `coulombDisScale²`)\n  - q1,q2: Node strength (`nodeStrength`)\n  - r: Distance between nodes\n\n#### Edge Attraction\n\n- **Physical Model**: Hooke's Law\n- **Function**: Simulates edge tension, moving nodes along edge directions, where `edgeStrength` and `linkDistance` control edge \"stiffness\" and length.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='Edge Attraction'/>\n\n  - ka: Edge attraction strength (`edgeStrength`)\n  - L: Edge length (`linkDistance`)\n  - r: Actual edge length\n\n#### Centripetal Force\n\n- **Physical Model**: Newton's Universal Law of Gravitation\n- **Function**: Attracts nodes toward the canvas center or cluster centers, where `gravity` and `center` control gravity strength and center point position\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Centripetal Force'/>\n\n  - G: Gravitational constant (`gravity`)\n  - xc: Center point coordinates (`center`)\n  - mass: Node mass (`nodeSize`)\n\n#### Interaction of Three Forces\n\n- **Physical Model**: Force interactions, generating acceleration\n- **Function**: Repulsion, edge attraction, and centripetal force work together, affecting node movement through acceleration superposition, ultimately reaching the lowest energy state.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Force Interactions'/>\n\n### Physical System\n\n#### Node Velocity Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='Node Velocity Formula'/>\n\n  - v: Velocity\n  - a: Acceleration\n  - dt: Time step (`interval`)\n  - damping: Damping coefficient (`damping`)\n\n- **Function**:\n  1. Controls node movement stability\n  2. Damping coefficient prevents system oscillation\n  3. Time step affects displacement per iteration\n\n#### Node Position Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='Node Position Formula'/>\n\n  - x: Node position\n  - v: Node velocity\n  - dt: Time step (`interval`)\n\n- **Function**:\n  1. Updates node position based on velocity\n  2. Ensures motion continuity\n  3. Prevents node overlap through `preventOverlap`\n\n#### Cluster Center Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='Cluster Center Calculation'/>\n\n  - n: Number of nodes in cluster\n  - (xi​,yi​): Position of each node\n\n- **Function**:\n  1. Calculates cluster center\n  2. Centripetal force pulls nodes toward their cluster center\n  3. Cluster center can change dynamically\n\n#### Cluster Strength Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='Cluster Strength Calculation'/>\n\n  - s: Cluster strength (`clusterNodeStrength`)\n  - xc​: Cluster center\n\n- **Function**:\n  1. Controls cluster compactness\n  2. Higher cluster strength means tighter clusters\n  3. Can be dynamically adjusted based on node properties\n\n#### Mass Effect on Forces\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='Mass Effect on Forces'/>\n\n  - a: Acceleration\n  - F: Force (repulsion, edge attraction, centripetal force)\n  - mass: Node mass\n\n- **Function**:\n  1. Nodes with larger mass move less\n  2. Nodes with smaller mass move more\n  3. Mass calculation can be customized through `getMass`\n\n#### Energy Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='Energy Calculation'/>\n\n  - m: Node mass\n  - v: Node velocity\n\n- **Function**:\n  1. Monitors layout convergence\n  2. System stabilizes when energy approaches zero\n\n#### System Convergence Condition\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='System Convergence Condition'/>\n\n- **Function**:\n  1. Controls iteration count\n  2. Stops when movement is below threshold\n  3. Can choose between mean, maximum, or minimum through `distanceThresholdMode`\n\n### Force Interaction Diagram\n\n```mermaid\ngraph TD\n    A[Input] --> B[Initialize Parameters];\n    B --> C[Build Layout Calculation];\n    C --> D[Iterative Calculation];\n    D --> E{Converged?};\n    E -->|Yes| F[Output Layout];\n    E -->|No| G[Calculate Repulsion];\n    G --> H[Calculate Edge Attraction];\n    H --> I[Calculate Centripetal Force];\n    I --> J[Update Velocity];\n    J --> K[Update Position];\n    K --> D;\n```\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/BOu7Rbuz4MoAAAAAQjAAAAgADpdRAQFr/original' alt='Force Simulation Diagram'/>\n\n## Configuration Options\n\nBased on the physical characteristics of force-directed layout, the following configuration options are available:\n\n### Basic Configuration\n\n| Property              | Description                                                                                                                                                                                                                                        | Default Value | Required |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type                  | Layout type                                                                                                                                                                                                                                        | `force`       | ✓        |\n| dimensions            | Layout dimensions, 2 for 2D layout, 3 for 3D layout                                                                                                                                                                                                | 2             |          |\n| width                 | Layout width                                                                                                                                                                                                                                       | Canvas width  |          |\n| height                | Layout height                                                                                                                                                                                                                                      | Canvas height |          |\n| center                | Layout center point                                                                                                                                                                                                                                | Graph center  |          |\n| maxIteration          | Maximum iteration count, if 0 will auto-adjust                                                                                                                                                                                                     | 0             |          |\n| minMovement           | Stop iteration when average movement distance is less than 0.4                                                                                                                                                                                     | 0.4           |          |\n| distanceThresholdMode | Movement distance calculation mode: mean: stop when average movement distance is less than `minMovement`; max: stop when maximum movement distance is less than `minMovement`; min: stop when minimum movement distance is less than `minMovement` | `mean`        |          |\n| maxDistance           | Maximum distance                                                                                                                                                                                                                                   |               |          |\n\n### Force-related Configuration\n\n#### Repulsion Configuration\n\n| Property        | Description                                                                                         | Default Value | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| nodeStrength    | Node force, positive values represent attraction between nodes, negative values represent repulsion | 1000          |          |\n| factor          | Repulsion coefficient, larger values mean stronger repulsion                                        | 1             |          |\n| coulombDisScale | Coulomb coefficient, a factor for repulsion, larger values mean stronger repulsion between nodes    | 0.005         |          |\n\n#### Edge Attraction Configuration\n\n| Property     | Description                                                                                                    | Default Value | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| edgeStrength | Edge force (attraction) strength, fixed force or callback function to dynamically return different edge forces | 500           |          |\n| linkDistance | Edge length, fixed length or callback function to dynamically return different edge lengths                    | 200           |          |\n\n#### Centripetal Force Configuration\n\n| Property           | Description                                                                                                                                                                                                                                                          | Default Value | Required |\n| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| gravity            | Center force strength, the force attracting all nodes to the center. Larger values mean more compact layout                                                                                                                                                          | 10            |          |\n| centripetalOptions | Centripetal force configuration, including center and strength for leaf nodes, isolated nodes, and other nodes. leaf: leaf node centripetal force; single: single node centripetal force; others: other node centripetal force; center: custom center point function | [0, 0]        |          |\n\n#### Clustering Configuration\n\n| Property            | Description                                                                                                                                                                                                                                                                                                                                                   | Default Value | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| clustering          | Whether to cluster all nodes. If true, will use the field specified by nodeClusterBy in node data for clustering. centripetalOptions.single, centripetalOptions.leaf, and centripetalOptions.others will use the value returned by getClusterNodeStrength; leaf and centripetalOptions.center will use the average center of all nodes in the current cluster | `false`       |          |\n| nodeClusterBy       | Specifies the field name in node data for clustering. Takes effect when clustering is true. Automatically generates centripetalOptions, can be used with clusterNodeStrength                                                                                                                                                                                  |               |          |\n| clusterNodeStrength | Used with clustering and nodeClusterBy to specify the strength of the cluster centripetal force                                                                                                                                                                                                                                                               |               |          |\n| leafCluster         | Whether to cluster leaf nodes. If true, centripetalOptions.single will be 100; centripetalOptions.leaf will use the value returned by getClusterNodeStrength; getClusterNodeStrength.center will return the average center of all leaf nodes                                                                                                                  | false         |          |\n\n#### Performance and Optimization Configuration\n\n| Property        | Description                                                                                                                                                                                                                                                               | Default Value | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| damping         | Damping coefficient, range [0, 1]. Larger values mean slower speed decrease                                                                                                                                                                                               | 0.9           |          |\n| maxSpeed        | Maximum movement length per iteration                                                                                                                                                                                                                                     | 200           |          |\n| interval        | Controls the movement speed of each node per iteration                                                                                                                                                                                                                    | 0.02          |          |\n| preventOverlap  | Whether to prevent overlap. Must be used with nodeSize or data.size in node data. Only when data.size is set in the data or nodeSize is configured in the layout with the same value as the node size in the graph, collision detection for node overlap can be performed | true          |          |\n| nodeSize        | Node size (diameter). Used for collision detection to prevent node overlap. Fixed size or callback function to dynamically return node size                                                                                                                               |               |          |\n| nodeSpacing     | Takes effect when preventOverlap is true. Minimum spacing between node edges to prevent overlap. Can be a callback to set different spacing for different nodes                                                                                                           |               |          |\n| collideStrength | Strength of anti-overlap force, range [0, 1]                                                                                                                                                                                                                              | 1             |          |\n\n#### Other Configuration\n\n| Property  | Description                                                                                                                                                                              | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| getMass   | Callback for the mass of each node. The parameter is the node's internal data, and the return value is the mass                                                                          |               |          |\n| getCenter | Callback for the x, y, and strength of the centripetal force for each node. If not specified, no extra centripetal force is applied                                                      |               |          |\n| onTick    | Callback for each iteration                                                                                                                                                              |               |          |\n| monitor   | Callback for monitoring each iteration. energy indicates the convergence energy of the layout. May incur extra computation if configured; if not configured, no computation is performed |               |          |\n\n## Code Examples\n\n### Basic Usage\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Layout width\n    width: 800,\n    // Layout height\n    height: 600,\n  },\n});\n```\n\n### Preventing Node Overlap\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n  },\n});\n```\n\n### Force-directed Layout\n\nThis example demonstrates how to create a basic force-directed graph using force-directed layout.\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Centripetal force\n    gravity: 0.9,\n    // Iteration count\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\nKey configuration explanations:\n\n- `preventOverlap`: Enable node overlap detection\n- `nodeSize`: Set node size\n- `gravity`: Set node centripetal force\n- `iterations`: Set layout calculation precision\n\nYou can also refer to [View Examples](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) for more usage examples.\n","frontmatter":{"title":"Force-directed Layout","order":"13"},"isInternal":false,"tokens":5594,"sizeBytes":22385},{"name":"ForceLayout.zh.md","path":"packages/site/docs/manual/layout/ForceLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/ForceLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Force 力导向布局\norder: 13\n---\n\n## 概述\n\n力导向布局是一种基于物理模拟的图布局算法，它通过模拟节点间的引力和斥力来确定节点的位置。这种布局方式特别适合展示复杂的关系网络，如社交网络、知识图谱等。\n\n力导向布局会自动计算并调整节点位置，使得相连的节点保持适当的距离，同时尽量减少边的交叉。布局过程中会模拟物理系统，节点会像带电粒子一样相互排斥，边则像弹簧一样连接节点。\n\n力导向布局的主要特点包括：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的长度\n   - 可以防止节点重叠\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='力导向布局示例'/>\n\n## 核心概念\n\n### Force 力导向布局基本原理\n\n力导向布局是一种基于物理模拟的图布局算法，它将图中的节点和边模拟为物理系统：\n\n- 节点被视为物理粒子\n- 边被视为弹簧\n- 整个系统通过物理模拟达到能量最低状态\n\n### 核心力详解\n\n#### 斥力（Node Repulsion）\n\n- **物理模型**：库伦定律（Coulomb's Law）\n- **作用**：防止节点重叠，让节点分布更均匀，其中 `factor` 和 `coulombDisScale` 控制斥力的总体强度和范围。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='斥力'/>\n\n  - k: 斥力系数（`factor` / `coulombDisScale²`）\n  - q1,q2: 节点强度(`nodeStrength`)\n  - r: 节点间距离\n\n#### 边拉力（Edge Attraction）\n\n- **物理模型**：胡克定律（Hooke's Law）\n- **作用**：模拟边的拉力，使节点沿着边的方向移动，其中 `edgeStrength` 和 `linkDistance` 控制边的“硬度”和长度。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='边拉力'/>\n\n  - ka: 边拉力强度（`edgeStrength`）\n  - L: 边的长度（`linkDistance`）\n  - r: 实际边长度\n\n#### 向心力（Gravity）\n\n- **物理模型**：牛顿万有引力定律（Newton's Universal Law of Gravitational）\n- **作用**：使节点向画布中心或者聚类中心聚集，其中 `gravity` 和 `center` 控制重力强度和中心点位置\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='向心力'/>\n\n  - G: 万有引力常数（`gravity`）\n  - xc: 中心点坐标（`center`）\n  - mass: 节点质量（`nodeSize`）\n\n#### 三种力的相互作用\n\n- **物理模型**：力的相互作用，产生加速度\n- **作用**：斥力、边拉力、向心力共同作用，通过加速度叠加影响节点运动，最终达到能量最低状态。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='力的相互作用'/>\n\n### 物理系统\n\n#### 节点运动速度公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='节点运动速度公式'/>\n\n  - v: 速度\n  - a: 加速度\n  - dt: 时间步长（`interval`）\n  - damping: 阻尼系数（`damping`）\n\n- **作用**：\n  1. 控制节点移动的稳定性\n  2. 阻尼系数防止系统震荡\n  3. 时间步长影响每次迭代的位移\n\n#### 节点位置公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='节点位置公式'/>\n\n  - x: 节点位置\n  - v: 节点速度\n  - dt: 时间步长（`interval`）\n\n- **作用**：\n  1. 根据速度更新节点位置\n  2. 确保运动连续性\n  3. 通过 `preventOverlap` 防止节点重叠\n\n#### 聚类中心计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='聚类中心计算'/>\n\n  - n: 聚类内节点数量\n  - (xi​,yi​): 每个节点的位置\n\n- **作用**：\n  1. 计算聚类中心\n  2. 向心力将节点拉向所属聚类中心\n  3. 聚类中心可动态变化\n\n#### 聚类强度计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='聚类强度计算'/>\n\n  - s: 聚类强度（`clusterNodeStrength`）\n  - xc​: 聚类中心\n\n- **作用**：\n  1. 控制聚类的紧密程度\n  2. 聚类强度越大，聚类越紧凑\n  3. 可根据节点属性动态调整\n\n#### 质量对力的影响\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='质量对力的影响'/>\n\n  - a: 加速度\n  - F: 力（斥力、边拉力、向心力）\n  - mass: 节点质量\n\n- **作用**：\n  1. 质量大的节点移动较小\n  2. 质量小的节点移动较大\n  3. 通过 `getMass` 可自定义质量计算\n\n#### 能量计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='能量计算'/>\n\n  - m: 节点质量\n  - v: 节点速度\n\n- **作用**：\n  1. 监控布局收敛情况\n  2. 能量趋近于零时系统趋于稳定\n\n#### 系统收敛条件\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='系统收敛条件'/>\n\n- **作用**：\n  1. 控制迭代次数\n  2. 移动量小于阈值时停止\n  3. 通过 `distanceThresholdMode` 可选择平均值、最大值或最小值\n\n### 力相互作用图\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2lI1RruANXoAAAAAAAAAAAAADpdRAQFr/original' alt='力作用模拟图'/>\n\n## 配置项\n\n根据上述力导向布局的物理特性，有以下配置项：\n\n### 基础配置\n\n| 属性                  | 描述                                                                                                                                                         | 默认值   | 必选 |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ---- |\n| type                  | 布局类型                                                                                                                                                     | `force`  | ✓    |\n| dimensions            | 布局维度，2表示2D布局，3表示3D布局                                                                                                                           | 2        |      |\n| width                 | 布局宽度                                                                                                                                                     | 画布宽度 |      |\n| height                | 布局高度                                                                                                                                                     | 画布高度 |      |\n| center                | 布局的中心点                                                                                                                                                 | 图中心   |      |\n| maxIteration          | 最大迭代次数，若为 0 则将自动调整                                                                                                                            | 0        |      |\n| minMovement           | 当平均移动距离小于0.4时停止迭代                                                                                                                              | 0.4      |      |\n| distanceThresholdMode | 移动距离的计算模式：mean: 平均移动距离小于 `minMovement` 时停止迭代；max: 最大移动距离小于时 `minMovement` 时停止迭代；min: 最小移动距离小于时 `minMovement` | `mean`   |      |\n| maxDistance           | 最大距离                                                                                                                                                     |          |      |\n\n### 力相关配置\n\n#### 斥力配置\n\n| 属性            | 描述                                                               | 默认值 | 必选 |\n| --------------- | ------------------------------------------------------------------ | ------ | ---- |\n| nodeStrength    | 节点作用力，正数代表节点之间的引力作用，负数代表节点之间的斥力作用 | 1000   |      |\n| factor          | 斥力系数，数值越大，斥力越大                                       | 1      |      |\n| coulombDisScale | 库伦系数，斥力的一个系数，数字越大，节点之间的斥力越大             | 0.005  |      |\n\n#### 边拉力配置\n\n| 属性         | 描述                                                               | 默认值 | 必选 |\n| ------------ | ------------------------------------------------------------------ | ------ | ---- |\n| edgeStrength | 边的作用力（引力）大小，固定作用力或回调函数动态返回不同边的作用力 | 500    |      |\n| linkDistance | 边的长度，固定长度或回调函数动态返回不同边的长度                   | 200    |      |\n\n#### 向心力配置\n\n| 属性               | 描述                                                                                                                                                         | 默认值 | 必选 |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ---- |\n| gravity            | 向中心力大小，指所有节点被吸引到 center 的力。数字越大，布局越紧凑                                                                                           | 10     |      |\n| centripetalOptions | 向心力配置，包括叶子节点、离散点、其他节点的向心中心及向心力大小。leaf: 叶子节点向心力；single: 单点向心力；others: 其他节点向心力；center: 自定义中心点函数 | [0, 0] |      |\n\n#### 聚类配置\n\n| 属性                | 描述                                                                                                                                                                                                                                                                                                      | 默认值  | 必选 |\n| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---- |\n| clustering          | 是否需要全部节点聚类，若为 `true`，将使用 `nodeClusterBy` 配置的节点数据中的字段作为聚类依据。 `centripetalOptions.single`、`centripetalOptions.leaf`、`centripetalOptions.others` 将使用 `getClusterNodeStrength` 返回值；`leaf`、`centripetalOptions.center` 将使用当前节点所属聚类中所有节点的平均中心 | `false` |      |\n| nodeClusterBy       | 指定节点数据中的字段名称作为节点聚类的依据，`clustering` 为 true 时生效，自动生成 `centripetalOptions`，可配合 `clusterNodeStrength` 使用                                                                                                                                                                 |         |      |\n| clusterNodeStrength | 配合 `clustering` 和 `nodeClusterBy` 使用，指定聚类向心力的大小                                                                                                                                                                                                                                           |         |      |\n| leafCluster         | 是否需要叶子节点聚类，若为 `true`，则 `centripetalOptions.single` 将为 100；`centripetalOptions.leaf` 将使用 `getClusterNodeStrength` 返回值；`getClusterNodeStrength.center` 将为叶子节点返回当前所有叶子节点的平均中心                                                                                  | false   |      |\n\n#### 性能与优化配置\n\n| 属性            | 描述                                                                                                                                                                                           | 默认值 | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| damping         | 阻尼系数，取值范围 [0, 1]。数字越大，速度降低得越慢                                                                                                                                            | 0.9    |      |\n| maxSpeed        | 一次迭代的最大移动长度                                                                                                                                                                         | 200    |      |\n| interval        | 控制每个迭代节点的移动速度                                                                                                                                                                     | 0.02   |      |\n| preventOverlap  | 是否防止重叠，必须配合下面属性 `nodeSize` 或节点数据中的 `data.size` 属性，只有在数据中设置了 `data.size` 或在该布局中配置了与当前图节点大小相同的 `nodeSize` 值，才能够进行节点重叠的碰撞检测 | true   |      |\n| nodeSize        | 节点大小（直径）。用于防止节点重叠时的碰撞检测，固定大小或者回调函数动态返回节点大小                                                                                                           |        |      |\n| nodeSpacing     | `preventOverlap` 为 `true` 时生效, 防止重叠时节点边缘间距的最小值。可以是回调函数, 为不同节点设置不同的最小间距                                                                                |        |      |\n| collideStrength | 防止重叠的力强度，范围 [0, 1]                                                                                                                                                                  | 1      |      |\n\n#### 其他配置\n\n| 属性      | 描述                                                                                                                                                                                                | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| getMass   | 获取节点质量的回调函数，入参为节点内部流转数据，用于计算节点质量大小                                                                                                                                |        |      |\n| getCenter | 每个节点中心力的 x、y、强度的回调函数，若不指定，则没有额外中心力                                                                                                                                   |        |      |\n| onTick    | 每一次迭代的回调函数                                                                                                                                                                                |        |      |\n| monitor   | 每个迭代的监控信息回调，energy 表示布局的收敛能量。若配置可能带来额外的计算能量性能消耗，不配置则不计算。入参为迭代监控信息 `{ energy: number; nodes: Node[]; edges: Edge[]; iterations: number; }` |        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 布局宽度\n    width: 800,\n    // 布局高度\n    height: 600,\n  },\n});\n```\n\n### 防止节点重叠\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n  },\n});\n```\n\n### 力导向布局\n\n该示例展示了如何使用力导向布局创建一个基础的力导向图。\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 向心力\n    gravity: 0.9,\n    // 迭代次数\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\n主要配置说明：\n\n- `preventOverlap`: 开启节点重叠检测\n- `nodeSize`: 设置节点大小\n- `gravity`: 设置节点向心力\n- `iterations`: 设置布局计算的精确程度\n\n还可以参考 [查看示例](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) 获取更多用法。\n","frontmatter":{"title":"Force 力导向布局","order":"13"},"isInternal":false,"tokens":3622,"sizeBytes":19007},{"name":"FruchtermanLayout.en.md","path":"packages/site/docs/manual/layout/FruchtermanLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/FruchtermanLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Fruchterman Force-directed Layout\norder: 14\n---\n\n## Overview\n\nThe Fruchterman layout is a force-directed layout based on the algorithm from [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf). By flexibly configuring parameters to simulate physical forces, the layout automatically reaches a stable equilibrium state with minimal energy. It supports both basic uniform distribution and cluster layouts. See more Fruchterman force-directed layout [examples](/en/examples#layout-fruchterman) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts).\n\n## Use Cases\n\n- Basic uniform distribution: Suitable for displaying network graphs with evenly distributed nodes and clear overall structure, such as network topology and knowledge graphs.\n- Cluster layout: Suitable for visualizing data with internal aggregation or grouping, such as community structure display and association group analysis.\n\n## Options\n\n| Property     | Description                                                                                                                                                                                        | Type                                                                                                       | Default          | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------- | -------- |\n| type         | Layout type                                                                                                                                                                                        | `'fruchterman'`                                                                                            | -                | ✓        |\n| height       | Layout height                                                                                                                                                                                      | `number`                                                                                                   | container height |          |\n| width        | Layout width                                                                                                                                                                                       | `number`                                                                                                   | container width  |          |\n| maxIteration | Maximum number of iterations                                                                                                                                                                       | `number`                                                                                                   | 500              |          |\n| minMovement  | Convergence threshold                                                                                                                                                                              | `number`                                                                                                   | 0.4              |          |\n| gravity      | Central force, i.e., the force attracting all nodes to the [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915). The larger the value, the more compact the layout | `number`                                                                                                   | 10               |          |\n| speed        | Node movement speed per iteration. Too high a speed may cause strong oscillation                                                                                                                   | `number`                                                                                                   | 5                |          |\n| onTick       | Callback for each iteration                                                                                                                                                                        | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -                |          |\n\n### Cluster Layout\n\n| Property       | Description                                                                               | Type      | Default     | Required |\n| -------------- | ----------------------------------------------------------------------------------------- | --------- | ----------- | -------- |\n| clustering     | Whether to use cluster layout                                                             | `boolean` | `false`     |          |\n| nodeClusterBy  | Field name in node data for clustering, effective when `clustering` is true               | `string`  | `'cluster'` |          |\n| clusterGravity | Gravity within clusters, affects cluster compactness, effective when `clustering` is true | `number`  | 10          |          |\n\n## Example Code\n\n### Basic Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### Cluster Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","frontmatter":{"title":"Fruchterman Force-directed Layout","order":"14"},"isInternal":false,"tokens":2727,"sizeBytes":10908},{"name":"FruchtermanLayout.zh.md","path":"packages/site/docs/manual/layout/FruchtermanLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/FruchtermanLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Fruchterman 力导向布局\norder: 14\n---\n\n## 概述\n\nFruchterman 布局是基于 [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf) 算法实现的一种力导向布局，通过灵活的参数配置模拟物理作用，使整个布局自动达到能量最小的稳定平衡状态，支持基础均匀分布和聚类布局。参考更多 Fruchterman 力导向布局[样例](/examples#layout-fruchterman)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts)\n\n## 使用场景\n\n- 基础均匀分布: 适用于展示节点均匀分布，整体结构清晰的网络关系图, 比如网络拓扑、知识图谱。\n- 聚类布局: 适用于具有内部聚合特性或分组的数据可视化展示, 比如社区结构展示、关联组分析。\n\n## 配置项\n\n| 属性         | 描述                                                                                                                                           | 类型                                                                                                       | 默认值   | 必选 |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type         | 布局类型                                                                                                                                       | `'fruchterman'`                                                                                            | -        | ✓    |\n| height       | 布局的高度                                                                                                                                     | `number`                                                                                                   | 容器高度 |      |\n| width        | 布局的宽度                                                                                                                                     | `number`                                                                                                   | 容器宽度 |      |\n| maxIteration | 最大迭代次数                                                                                                                                   | `number`                                                                                                   | 500      |      |\n| minMovement  | 收敛阈值                                                                                                                                       | `number`                                                                                                   | 0.4      |      |\n| gravity      | 中心力大小，指所有节点被吸引到 [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915) 的力。数字越大，布局越紧凑 | `number`                                                                                                   | 10       |      |\n| speed        | 每次迭代节点移动的速度。速度太快可能会导致强烈震荡                                                                                             | `number`                                                                                                   | 5        |      |\n| onTick       | 每一次迭代的回调函数                                                                                                                           | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -        |      |\n\n### 聚类布局\n\n| 属性           | 描述                                                                       | 类型      | 默认值      | 必选 |\n| -------------- | -------------------------------------------------------------------------- | --------- | ----------- | ---- |\n| clustering     | 是否按照聚类布局                                                           | `boolean` | `false`     |      |\n| nodeClusterBy  | 聚类布局依据的节点数据 `data` 中的字段名，在 `clustering` 为 `true` 时生效 | `string`  | `'cluster'` |      |\n| clusterGravity | 聚类内部的重力大小，影响聚类的紧凑程度，在 `clustering` 为 `true` 时生效   | `number`  | 10          |      |\n\n## 示例代码\n\n### 基本布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### 聚类布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n","frontmatter":{"title":"Fruchterman 力导向布局","order":"14"},"isInternal":false,"tokens":2350,"sizeBytes":10192},{"name":"GridLayout.en.md","path":"packages/site/docs/manual/layout/GridLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/GridLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Grid Layout\norder: 15\n---\n\n## Overview\n\nThe grid layout arranges nodes in a grid pattern, suitable for scenarios where nodes need to be arranged neatly. This layout supports automatic calculation of the number of rows and columns, or you can specify them manually. It also supports preventing node overlap.\n\n## Use Cases\n\n- Visualizing data in a matrix or table format\n\n## Online Demo\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## Options\n\n| Property              | Description                                                                                                                     | Type                                             | Default   | Required |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | -------- |\n| type                  | Layout type                                                                                                                     | `grid`                                           | -         | ✓        |\n| begin                 | Grid start position (top-left corner), default is `[0, 0]`                                                                      | [number, number]                                 | [0, 0]    |          |\n| cols                  | Number of columns. If undefined, the algorithm calculates it automatically based on node count, layout space, and rows (if set) | number                                           | undefined |          |\n| rows                  | Number of rows. If undefined, the algorithm calculates it automatically based on node count, layout space, and cols (if set)    | number                                           | 10        |          |\n| width                 | Layout area width. In G6, the container width is used as the default value                                                      | number                                           | 300       |          |\n| height                | Layout area height. In G6, the container height is used as the default value                                                    | number                                           | 300       |          |\n| condense              | If false, uses all available canvas space; if true, uses the minimum canvas space                                               | boolean                                          | false     |          |\n| nodeSize              | Node size (diameter), used for collision detection when preventing overlap                                                      | Size \\| ((nodeData: Node) => Size)               | -         |          |\n| nodeSpacing           | Node spacing, used to adjust the gap between nodes                                                                              | ((node?: Node) => number) \\| number              | -         |          |\n| position              | Specify the row and column for each node                                                                                        | (node?: Node) => { row?: number; col?: number; } | undefined |          |\n| preventOverlap        | Whether to prevent node overlap. Requires nodeSize or size property in node data                                                | boolean                                          | false     |          |\n| preventOverlapPadding | Padding when preventing overlap. Effective when preventOverlap is true                                                          | number                                           | 10        |          |\n| sortBy                | Sort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting              | string                                           | undefined |          |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\nWhether to prevent overlap\n\nMust be used with nodeSize or the size property in node data. Only when data has data.size or nodeSize is set in the layout, collision detection for node overlap can be performed.\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\nPadding when preventing overlap. Effective when preventOverlap is true.\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\nSort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting. In G6, the container width is used as the default value for grid layout width. When used alone, the default is 300.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Custom Configuration\n\nYou can customize the grid layout in various ways:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // Start layout from [50, 50]\n    cols: 4, // 4 columns\n    rows: 6, // 6 rows\n    width: 400, // Layout area width\n    height: 600, // Layout area height\n    preventOverlap: true, // Prevent node overlap\n    nodeSize: 30, // Node size\n    condense: true, // Use minimum space\n    sortBy: 'value', // Sort by value property\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // Property for sorting\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Specify Node Position\n\nYou can specify the position for specific nodes using the `position` property:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // Specify position for specific nodes\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // Top-left\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // Top-right\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // Bottom-left\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // Bottom-right\n      return undefined; // Other nodes are auto-arranged\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Real Cases\n\n- [Grid Layout](/en/examples/layout/grid/#basic)\n","frontmatter":{"title":"Grid Layout","order":"15"},"isInternal":false,"tokens":3006,"sizeBytes":12024},{"name":"GridLayout.zh.md","path":"packages/site/docs/manual/layout/GridLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/GridLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 网格布局 Grid\norder: 15\n---\n\n## 概述\n\n网格布局将节点按照网格形式排列，适用于需要整齐排列节点的场景。该布局支持自动计算行列数，也可以手动指定行列数，并支持防止节点重叠。\n\n## 使用场景\n\n- 在数据可视化中需要展示矩阵或表格形式的数据关系\n\n## 在线体验\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## 配置项\n\n| 属性                  | 描述                                                                                                                             | 类型                                             | 默认值    | 必选 |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | ---- |\n| type                  | 布局类型                                                                                                                         | `grid`                                           | -         | ✓    |\n| begin                 | 网格开始位置（左上角），默认为 `[0, 0]`                                                                                          | [number, number]                                 | [0, 0]    |      |\n| cols                  | 网格的列数，为 undefined 时算法根据节点数量、布局空间、rows（若指定）自动计算                                                    | number                                           | undefined |      |\n| rows                  | 网格的行数，为 undefined 时算法根据节点数量、布局空间、cols（若指定）自动计算                                                    | number                                           | 10        |      |\n| width                 | 布局区域宽度，在 G6 中使用当前容器的宽度作为默认值                                                                               | number                                           | 300       |      |\n| height                | 布局区域高度，在 G6 中使用当前容器的高度作为默认值                                                                               | number                                           | 300       |      |\n| condense              | 为 false 时表示利用所有可用画布空间，为 true 时表示利用最小的画布空间                                                            | boolean                                          | false     |      |\n| nodeSize              | 节点大小（直径），用于防止节点重叠时的碰撞检测                                                                                   | Size \\| ((nodeData: Node) => Size)               | -         |      |\n| nodeSpacing           | 节点间距，用于调整节点之间的间隔                                                                                                 | ((node?: Node) => number) \\| number              | -         |      |\n| position              | 指定每个节点所在的行和列                                                                                                         | (node?: Node) => { row?: number; col?: number; } | undefined |      |\n| preventOverlap        | 是否防止节点重叠，需要配合 nodeSize 或节点数据中的 size 属性使用                                                                 | boolean                                          | false     |      |\n| preventOverlapPadding | 避免重叠时节点的间距 padding，preventOverlap 为 true 时生效                                                                      | number                                           | 10        |      |\n| sortBy                | 指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心 | string                                           | undefined |      |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\n是否防止重叠\n\n必须配合下面属性 nodeSize 或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\n避免重叠时节点的间距 padding，preventOverlap 为 true 时生效\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\n指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心\n\n在 G6 中使用当前容器的宽度作为 grid 布局 width 的默认值。单独使用此布局时默认值为 300\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 自定义配置\n\n可以通过多种方式自定义网格布局：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // 从坐标 [50, 50] 开始布局\n    cols: 4, // 指定 4 列\n    rows: 6, // 指定 6 行\n    width: 400, // 布局区域宽度\n    height: 600, // 布局区域高度\n    preventOverlap: true, // 防止节点重叠\n    nodeSize: 30, // 节点大小\n    condense: true, // 使用最小空间\n    sortBy: 'value', // 按 value 属性排序\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // 用于排序的属性\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 指定节点位置\n\n可以通过 `position` 属性为特定节点指定位置：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // 为特定节点指定位置\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // 左上角\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // 右上角\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // 左下角\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // 右下角\n      return undefined; // 其他节点自动布局\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [Grid布局](/examples/layout/grid/#basic)\n","frontmatter":{"title":"网格布局 Grid","order":"15"},"isInternal":false,"tokens":2712,"sizeBytes":12374},{"name":"IndentedLayout.en.md","path":"packages/site/docs/manual/layout/IndentedLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/IndentedLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Indented Tree\norder: 16\n---\n\n# Indented Tree Layout\n\n## Overview\n\nIndented tree layout represents the hierarchy of tree nodes through indentation in the horizontal direction. Each element occupies a row or column, commonly used in file directory structures, organizational charts, and other scenarios. This layout provides a clear structure for displaying hierarchical relationships.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented Tree Layout'/>\n\n## Use Cases\n\n- File directory structure visualization\n- Organizational charts\n- Classification system display\n- Tree-like data where hierarchical relationships need to be emphasized\n\n## Configuration Items\n\n> IndentedLayout supports common layout configuration items and specific configuration items, as shown below.\n\n| Property               | Description                                                         | Type                            | Default    | Required |\n| ---------------------- | ------------------------------------------------------------------- | ------------------------------- | ---------- | -------- |\n| type                   | Layout type, must be 'indented'                                     | 'indented'                      | -          | ✓        |\n| direction              | Layout direction, see details below                                 | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |          |\n| indent                 | Column spacing, fixed value or function                             | number \\| (d?: Node) => number  | 20         |          |\n| getWidth               | Get each node's width, effective when direction='H'                 | (d?: Node) => number            | -          |          |\n| getHeight              | Get each node's height                                              | (d?: Node) => number            | -          |          |\n| getSide                | Node placement on left/right side of root, overrides direction='H'  | (d?: Node) => 'left' \\| 'right' | -          |          |\n| dropCap                | Whether the first child of each node starts on the next line        | boolean                         | true       |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (when preLayout=true) | boolean                         | false      |          |\n| nodeFilter             | Nodes participating in this layout                                  | (node: NodeData) => boolean     | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements       | boolean                         | false      |          |\n| enableWorker           | Whether to run layout in WebWorker                                  | boolean                         | -          |          |\n| iterations             | Number of iterations for iterative layout                           | number                          | -          |          |\n\n### Complex Type Explanations\n\n- **direction**\n\n  - `'LR'`: Root node on the left, layout to the right\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`: Root node on the right, layout to the left\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`: Root node in the middle, horizontal symmetric layout\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - Fixed value: Consistent indentation for all levels\n  - Function: (d?: Node) => number, customize indentation based on node\n  - Example:\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - Used to customize each node's width/height, often for content adaptation\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - Specifies which side of the root node a node should be placed, only effective when direction='H'\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## Example Code\n\n> For more examples, see [Online Demo](https://g6.antv.antgroup.com/en/examples/layout/indented)\n\n### Automatic Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### Right Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'LR'\n```\n\n### Left Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'RL'\n```\n\n### Custom Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### No Line Break for First Child Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","frontmatter":{"title":"Indented Tree","order":"16"},"isInternal":false,"tokens":1543,"sizeBytes":6171},{"name":"IndentedLayout.zh.md","path":"packages/site/docs/manual/layout/IndentedLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/IndentedLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 缩进树 Indented\norder: 16\n---\n\n## 概述\n\nIndented（缩进树）布局是一种通过水平方向的缩进量来表示树节点层级的布局方式。每个元素占据一行或一列，常用于文件目录结构、组织架构等场景。该布局结构清晰，便于展示层级关系。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented 缩进树布局示意图'/>\n\n## 使用场景\n\n- 文件目录结构可视化\n- 组织架构树\n- 分类体系展示\n- 需要突出层级关系的树状数据\n\n## 配置项\n\n> IndentedLayout 支持通用布局配置项和专有配置项，详见下表。\n\n| 属性                   | 描述                                                 | 类型                            | 默认值     | 必选 |\n| ---------------------- | ---------------------------------------------------- | ------------------------------- | ---------- | ---- |\n| type                   | 布局类型，需为 'indented'                            | 'indented'                      | -          | ✓    |\n| direction              | 布局方向，根节点在左/右/中间，详见下方说明           | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |      |\n| indent                 | 列间间距，支持固定值或函数                           | number \\| (d?: Node) => number  | 20         |      |\n| getWidth               | 获取每个节点宽度，仅 direction='H' 时生效            | (d?: Node) => number            | -          |      |\n| getHeight              | 获取每个节点高度                                     | (d?: Node) => number            | -          |      |\n| getSide                | 节点排布在根节点的左/右侧，设置后 direction='H' 失效 | (d?: Node) => 'left' \\| 'right' | -          |      |\n| dropCap                | 每个节点的第一个子节点是否换行                       | boolean                         | true       |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（preLayout=true 时生效）      | boolean                         | false      |      |\n| nodeFilter             | 参与该布局的节点                                     | (node: NodeData) => boolean     | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                   | boolean                         | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                          | boolean                         | -          |      |\n| iterations             | 迭代布局的迭代次数                                   | number                          | -          |      |\n\n### 复杂类型说明\n\n- **direction**\n\n  - `'LR'`：根节点在左，向右布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`：根节点在右，向左布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`：根节点在中间，水平对称布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - 固定数值：所有层级缩进一致\n  - 函数：(d?: Node) => number，可根据节点自定义缩进\n  - 示例：\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - 用于自定义每个节点的宽度/高度，常用于自适应内容\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - 指定节点在根节点的哪一侧，仅 direction='H' 时生效\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## 示例代码\n\n> 更多示例可参考 [在线 Demo](https://g6.antv.antgroup.com/examples/layout/indented)\n\n### 子节点自动分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### 子节点右侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'LR'\n```\n\n### 子节点左侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'RL'\n```\n\n### 自定义子节点分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### 首子节点不换行\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n","frontmatter":{"title":"缩进树 Indented","order":"16"},"isInternal":false,"tokens":1191,"sizeBytes":5754},{"name":"MdsLayout.en.md","path":"packages/site/docs/manual/layout/MdsLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/MdsLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: MDS High-dimensional Data Dimensionality Reduction Layout\norder: 17\n---\n\n# MDS High-dimensional Data Dimensionality Reduction Layout\n\n## Overview\n\nMDS (Multidimensional Scaling) is a classic dimensionality reduction algorithm. In G6, the MDS layout constructs a distance matrix between nodes and restores their relative distances in high-dimensional space as much as possible in 2D space. It is suitable for graph visualization scenarios that show similarity, distance, or structural relationships between nodes.\n\n## Use Cases\n\n- Data dimensionality reduction visualization\n- Displaying distance relationships between nodes\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## Options\n\n| Option           | Description                           | Type              | Default       | Required |\n| :--------------- | :------------------------------------ | :---------------- | :------------ | :------- |\n| **type**         | Layout type                           | `mds`             | -             | Yes      |\n| **center**       | Center position of the layout         | `[number,number]` | canvas center | No       |\n| **linkDistance** | Ideal length of edges (spring length) | `number`          | 200           | No       |\n\n**center**\n\nThe center coordinates of the layout. All nodes will be symmetrically distributed around this point.\n\n**linkDistance**\n\n> number Default: 50\n\nThe ideal distance between nodes. The larger the value, the more dispersed the nodes.\n\n## Code Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"MDS High-dimensional Data Dimensionality Reduction Layout","order":"17"},"isInternal":false,"tokens":580,"sizeBytes":2318},{"name":"MdsLayout.zh.md","path":"packages/site/docs/manual/layout/MdsLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/MdsLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 高维数据降维布局 MDS\norder: 17\n---\n\n## 概述\n\nMDS（多维尺度分析，Multidimensional Scaling）是一种经典的降维算法。在 G6 中，MDS 布局通过构造节点间的距离矩阵，在二维空间中尽可能还原它们在高维空间中的相对距离。适用于展示节点之间相似度、距离或结构关系的图可视化场景。\n\n## 使用场景\n\n- 数据降维可视化\n- 展示节点之间的距离关系\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## 配置项\n\n| 配置项           | 描述                               | 类型              | 默认值   | 必选 |\n| :--------------- | :--------------------------------- | :---------------- | :------- | :--- |\n| **type**         | 布局类型                           | `mds`             | -        | 是   |\n| **center**       | 布局的中心位置                     | `[number,number]` | 画布中心 | 否   |\n| **linkDistance** | 边的理想长度（弹簧未受力时的长度） | `number`          | 200      | 否   |\n\n**center**\n\n布局的中心点坐标，所有节点会围绕该点对称分布。\n\n**linkDistance**\n\n> number Default: 50\n\n节点之间的理想距离，越大则节点间距离越分散。\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"高维数据降维布局 MDS","order":"17"},"isInternal":false,"tokens":406,"sizeBytes":2074},{"name":"MindmapLayout.en.md","path":"packages/site/docs/manual/layout/MindmapLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/MindmapLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Mindmap Tree\norder: 18\n---\n\n## Overview\n\nThe mindmap tree layout is suitable for hierarchical layouts of tree structures, supporting expansion on both left and right sides. Nodes at the same depth will be placed on the same layer. Note: the layout **does** take node size into account. See more mindmap layout [examples](/en/examples#layout-mindmap) or [source code](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"Mindmap tree options diagram\" />\n\n| Property  | Description                                                                                             | Type                                | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------- | -------- |\n| type      | Layout type                                                                                             | `mindmap`                           | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                 | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`    |          |\n| getHeight | Function to calculate the height of each node                                                           | (d?: Node) => number                |         | ✓        |\n| getWidth  | Function to calculate the width of each node                                                            | (d?: Node) => number                |         | ✓        |\n| getVGap   | Vertical gap for each node. Note: the actual vertical gap between two nodes is twice the vgap           | (d?: Node) => number                |         |          |\n| getHGap   | Horizontal gap for each node. Note: the actual horizontal gap between two nodes is twice the hgap       | (d?: Node) => number                |         |          |\n| getSide   | Set whether the node is placed on the left or right of the root. Only effective when `direction` is `H` | (d?: Node) => string                |         |          |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\nTree layout direction\n\n- `'H'`: horizontal — The children of the root node are divided into two parts and placed on the left and right sides of the root node. You can pass the `getSide` method to specify the left/right distribution logic for each node. If not provided, the first half will be placed on the right, and the second half on the left by default.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='Horizontal layout'/>\n\n- `'LR' | 'TB'`: Children are placed on the right side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `'RL'`: Children are placed on the left side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `BT`: Children are placed on the right side of the root node, then the entire graph is rotated 180° along the X axis.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='Vertical layout'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\nWidth of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\nHeight of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\nHorizontal gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\nVertical gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\nSet whether the node is placed on the left or right of the root. Note: only effective when `direction` is `H`. If not set, the first half of the children will be placed on the right, and the second half on the left by default. See [getSide auto calculation logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### Suitable Scenarios\n\n- Data lineage graph: `direction='H'` is suitable for rendering upstream and downstream lineage of a specified node, with upstream on the left and downstream on the right of the central node.\n- Mind map: Build custom mind map components.\n","frontmatter":{"title":"Mindmap Tree","order":"18"},"isInternal":false,"tokens":1331,"sizeBytes":5333},{"name":"MindmapLayout.zh.md","path":"packages/site/docs/manual/layout/MindmapLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/MindmapLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 脑图树 Mindmap\norder: 18\n---\n\n## 概述\n\n脑图树布局适用于树状结构的层次化布局，支持左右两侧展开，深度相同的节点将会被放置在同一层。需要注意：布局**会**考虑节点的大小。参考更多脑图布局[样例](/examples#layout-mindmap)或[源码](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"脑图树配置项图解\" />\n\n| 属性      | 描述                                                                                                  | 类型                                | 默认值 | 必选 |\n| --------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                              | `mindmap`                           | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                        | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`   |      |\n| getHeight | 计算每个节点的高度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getWidth  | 计算每个节点的宽度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getVGap   | 每个节点的垂直间隙，注意实际两个节点间的垂直间隙是2倍的vgap                                           | (d?: Node) => number                |        |      |\n| getHGap   | 每个节点的水平间隙，注意实际两个节点间的水平间隙是2倍的hgap                                           | (d?: Node) => number                |        |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在`H`布局方向上生效 | (d?: Node) => string                |        |      |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\n树布局的方向\n\n- `'H'`：horizontal（水平）—— 根节点的子节点分成两部分横向放置在根节点左右两侧。可传入`getSide`方法指定每个节点的左右分布逻辑，不传则默认将前半部分放置在右侧，后半部分放置在左侧。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='水平布局'/>\n\n- `'LR' | 'TB'`：将子节点排布在根节点的右侧；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='竖直布局'/>\n\n- `'RL'`：将子节点排布在根节点的左侧；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='竖直布局'/>\n\n- `BT`：将子节点排布在根节点右侧，然后将整个图沿X轴旋转180°；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='竖直布局'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在`direction`为`H`时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考[getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### 布局适用场景\n\n- 数据血缘图：`direction='H'`很适合渲染血缘图中查看指定节点的上下游血缘的场景，上游分布在中心节点的左侧，下游分布在右侧；\n- 思维导图：构建自定义的思维导图组件。\n","frontmatter":{"title":"脑图树 Mindmap","order":"18"},"isInternal":false,"tokens":993,"sizeBytes":5198},{"name":"overview.en.md","path":"packages/site/docs/manual/layout/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/overview.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Layout Overview\norder: 0\n---\n\n## Overview\n\nGraph layout refers to the process of arranging elements in a graph according to certain rules, such as force-directed layout based on charge elasticity models, grid layout with sequential arrangement, and tree layout based on hierarchical structures.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Layout Types\n\nG6 provides a variety of layout algorithms, allowing users to choose the appropriate one based on their needs:\n\n- [AntVDagreLayout](/en/manual/layout/antv-dagre-layout): Custom layout based on dagre\n- [CircularLayout](/en/manual/layout/circular-layout): Circular layout\n- [ComboCombinedLayout](/en/manual/layout/combo-combined-layout): Layout suitable for combinations\n- [ConcentricLayout](/en/manual/layout/concentric-layout): Concentric layout\n- [D3Force3DLayout](/en/manual/layout/d3-force3-d-layout): [3D Force-directed](https://github.com/vasturiano/d3-force-3d) layout\n- [D3ForceLayout](/en/manual/layout/d3-force-layout): Force-directed layout based on [D3](https://d3js.org/d3-force)\n- [DagreLayout](/en/manual/layout/dagre-layout): [dagre](https://github.com/dagrejs/dagre) layout\n- [FishboneLayout](/en/manual/layout/fishbone): Fishbone layout\n- [ForceAtlas2Layout](/en/manual/layout/force-atlas2-layout): [ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) layout\n- [ForceLayout](/en/manual/layout/force-layout): Force-directed layout\n- [FruchtermanLayout](/en/manual/layout/fruchterman-layout): [Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) layout\n- [GridLayout](/en/manual/layout/grid-layout): Grid layout\n- [MDSLayout](/en/manual/layout/mds-layout): High-dimensional data dimensionality reduction layout\n- [RadialLayout](/en/manual/layout/radial-layout): Radial layout\n- [RandomLayout](/en/manual/layout/random-layout): Random layout\n- [SnakeLayout](/en/manual/layout/snake): Snake layout\n- [CompactBoxLayout](/en/manual/layout/compact-box-layout): Compact tree layout\n- [DendrogramLayout](/en/manual/layout/dendrogram-layout): Dendrogram layout\n- [MindmapLayout](/en/manual/layout/mindmap-layout): Mindmap layout\n- [IndentedLayout](/en/manual/layout/indented-layout): Indented tree layout\n\nAmong them, `CompactBox Layout`, `Dendrogram Layout`, `Mindmap Layout`, and `Indented Layout` are types of tree layouts suitable for tree-structured graphs.\n\n## Register Layout\n\nYou can directly use built-in layouts, but if you want to use other layouts, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## Configure Layout\n\nThe `layout` configuration item can specify the graph's layout algorithm, for example:\n\n```typescript\n{\n  layout: {\n    // Specify the layout algorithm to use\n    type: 'force',\n    // Configuration items for the layout algorithm\n    gravity: 10\n    // ...\n  }\n}\n```\n\nYou can also use `graph.setLayout` to update the layout configuration after the graph is instantiated.\n\nStarting from `5.1`, layout docs align their shared fields with `@antv/layout`. Besides each layout's own algorithm parameters, you should also pay attention to common options such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`.\n\n## Layout Acceleration\n\nG6 provides accelerated versions for some layout algorithms, including executing layout algorithms in Web Workers, providing [WASM](https://webassembly.org/) versions of layout algorithms, and GPU-accelerated layout algorithms. They can be used as follows:\n\n### Execute Layout Algorithms in Web Workers\n\nExcept for tree layouts, all built-in layout algorithms in G6 support execution in Web Workers. Simply set `enableWorker` to `true`:\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### Use WASM Version Layout Algorithms\n\nCurrently supported WASM version layout algorithms include: `Fruchterman Layout`, `ForceAtlas Layout`, `Force Layout`, `Dagre Layout`.\n\nFirst, install `@antv/layout-wasm`:\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\nInitialize threads:\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... other configurations\n  },\n});\n```\n\n### Use GPU-Accelerated Layout\n\nCurrently supported GPU-accelerated layout algorithms include: `Fruchterman Layout`, `GForce Layout`.\n\nFirst, install `@antv/layout-gpu`:\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... other configurations\n  },\n});\n```\n\n## Execute Layout\n\nUsually, after calling `graph.render()`, G6 will automatically execute the layout algorithm.\n\nIf you need to manually execute the layout algorithm, G6 provides the following APIs:\n\n- [layout](/api/layout#graphlayoutlayoutoptions): Execute layout algorithm\n- [setLayout](/api/layout#graphsetlayoutlayout): Set layout algorithm\n- [stopLayout](/api/layout#graphstoplayout): Stop layout algorithm\n\n## Custom Layout\n\nIf the built-in layout algorithms cannot meet your needs, you can customize layout algorithms. For details, please refer to [Custom Layout](/manual/layout/custom-layout).\n\nIf you are migrating layout configuration from G6 `5.0` to `5.1`, see [Upgrade from 5.0 to 5.1 (Layout)](/en/manual/whats-new/upgrade-to-5-1).\n","frontmatter":{"title":"Layout Overview","order":"0"},"isInternal":false,"tokens":1595,"sizeBytes":6380},{"name":"overview.zh.md","path":"packages/site/docs/manual/layout/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/overview.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 布局总览\norder: 0\n---\n\n## 概述\n\n图布局是指将图中的元素按照一定的规则进行排列的过程，例如基于电荷弹性模型的力导向布局、逐次排布的网格布局、基于层次结构的树布局等。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 布局类型\n\nG6 提供了多种布局算法，用户可以根据自己的需求选择合适的布局算法：\n\n- [AntVDagreLayout](/manual/layout/antv-dagre-layout)：基于 dagre 定制的布局\n- [CircularLayout](/manual/layout/circular-layout)：环形布局\n- [ComboCombinedLayout](/manual/layout/combo-combined-layout)：适用于存在组合的布局\n- [ConcentricLayout](/manual/layout/concentric-layout)：同心圆布局\n- [D3Force3DLayout](/manual/layout/d3-force3-d-layout)：[3D 力导向](https://github.com/vasturiano/d3-force-3d)布局\n- [D3ForceLayout](/manual/layout/d3-force-layout)：基于 [D3](https://d3js.org/d3-force) 的力导向布局\n- [DagreLayout](/manual/layout/dagre-layout)：[dagre](https://github.com/dagrejs/dagre) 布局\n- [FishboneLayout](/manual/layout/fishbone)：鱼骨布局\n- [ForceAtlas2Layout](/manual/layout/force-atlas2-layout)：[ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) 布局\n- [ForceLayout](/manual/layout/force-layout)：力导向布局\n- [FruchtermanLayout](/manual/layout/fruchterman-layout)：[Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) 布局\n- [GridLayout](/manual/layout/grid-layout)：网格布局\n- [MDSLayout](/manual/layout/mds-layout)：高维数据降维算法布局\n- [RadialLayout](/manual/layout/radial-layout)：径向布局\n- [RandomLayout](/manual/layout/random-layout)：随机布局\n- [SnakeLayout](/manual/layout/snake)：蛇形布局\n- [CompactBoxLayout](/manual/layout/compact-box-layout): 紧凑树布局\n- [DendrogramLayout](/manual/layout/dendrogram-layout): 树状布局\n- [MindmapLayout](/manual/layout/mindmap-layout): 思维导图布局\n- [IndentedLayout](/manual/layout/indented-layout): 缩进树布局\n\n其中 `CompactBox Layout`、`Dendrogram Layout`、`Mindmap Layout`、`Indented Layout` 是树布局的一种，适用于树状结构的图。\n\n## 注册布局\n\n你可以直接使用内置布局，如果想要使用其他布局，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## 配置布局\n\n通过 `layout` 配置项可以指定图的布局算法，例如：\n\n```typescript\n{\n  layout: {\n    // 指定要使用的布局算法\n    type: 'force',\n    // 布局算法的配置项\n    gravity: 10\n    // ...\n  }\n}\n```\n\n也可在图实例化之后使用 `graph.setLayout` 来更新布局配置。\n\n5.1 开始，布局文档中的通用字段已与 `@antvis/layout` 对齐。除了各布局自己的算法参数外，也建议同时关注 `width`、`height`、`center`、`enableWorker`、`node`、`edge` 等公共配置。\n\n## 布局加速\n\nG6 对一些布局算法提供了加速版本，包括：在 Web Worker 中执行布局算法、提供 [WASM](https://webassembly.org/) 版本的布局算法、GPU 加速的布局算法等。可按照下列方式使用：\n\n### 在 Web Worker 中执行布局算法\n\n除树布局外，G6 的所有内置布局算法都支持在 Web Worker 中执行。只需将 `enableWorker` 设置为 `true` 即可：\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### 使用 WASM 版本布局算法\n\n目前支持 WASM 版本的布局算法有：`Fruchterman Layout` `ForceAtlas Layout` `Force Layout` `Dagre Layout`。\n\n首先安装 `@antv/layout-wasm`：\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\n初始化线程：\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... 其他配置\n  },\n});\n```\n\n### 使用 GPU 加速布局\n\n目前支持 GPU 加速的布局算法有：`Fruchterman Layout` `GForce Layout`。\n\n首先安装 `@antv/layout-gpu`：\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他配置\n  },\n});\n```\n\n## 执行布局\n\n通常，在调用 `graph.render()` 后，G6 会自动执行布局算法。\n\n如果需要手动执行布局算法，G6 提供了以下 API：\n\n- [layout](/api/layout#graphlayoutlayoutoptions)：执行布局算法\n- [setLayout](/api/layout#graphsetlayoutlayout)：设置布局算法\n- [stopLayout](/api/layout#graphstoplayout)：停止布局算法\n\n## 自定义布局\n\n如果内置布局算法无法满足需求，可以自定义布局算法，具体请参考[自定义布局](/manual/layout/custom-layout)。\n\n如果你正在从 G6 `5.0` 的布局配置迁移到 `5.1`，可继续阅读 [从 5.0 升级到 5.1（布局）](/manual/whats-new/upgrade-to-5-1)。\n","frontmatter":{"title":"布局总览","order":"0"},"isInternal":false,"tokens":1084,"sizeBytes":5816},{"name":"RadialLayout.en.md","path":"packages/site/docs/manual/layout/RadialLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/RadialLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Radial Layout\norder: 19\n---\n\n## Overview\n\nRadial layout is a graph layout algorithm that arranges nodes in concentric circles by layers. It is commonly used to display hierarchical relationships, community structures, and more. This layout supports advanced features such as node overlap prevention and group sorting, making it suitable for visualizing various network structures.\n\n## Use Cases\n\n- Displaying hierarchical structures (e.g., organizational charts, family trees)\n- Community structure analysis\n- Scenarios that need to highlight the central node and its radiating relationships\n- Complex networks requiring node grouping and sorting\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // other configurations...\n});\n```\n\n## Options\n\n| Property                   | Description                                                     | Type                                             | Default  | Required |\n| -------------------------- | --------------------------------------------------------------- | ------------------------------------------------ | -------- | -------- |\n| type                       | Layout type                                                     | string                                           | `radial` | ✓        |\n| center                     | Center coordinates                                              | [number, number]                                 | -        |          |\n| focusNode                  | Radiating center node                                           | string \\| Node \\| null                           | null     |          |\n| height                     | Canvas height                                                   | number                                           | -        |          |\n| width                      | Canvas width                                                    | number                                           | -        |          |\n| nodeSize                   | Node size (diameter)                                            | number \\| number[] \\| ((nodeData: Node) => Size) | -        |          |\n| nodeSpacing                | Minimum node spacing (effective when preventing overlap)        | number \\| (nodeData: Node) => number             | 10       |          |\n| linkDistance               | Edge length                                                     | number                                           | 50       |          |\n| unitRadius                 | Radius per circle; when null, automatically computed from space | number \\| null                                   | 100      |          |\n| maxIteration               | Maximum number of iterations                                    | number                                           | 1000     |          |\n| maxPreventOverlapIteration | Max iterations for overlap prevention                           | number                                           | 200      |          |\n| preventOverlap             | Whether to prevent node overlap                                 | boolean                                          | false    |          |\n| sortBy                     | Field or sorting function for nodes in the same layer           | string \\| ((nodeData: Node) => number \\| string) | -        |          |\n| sortStrength               | Sorting strength for nodes in the same layer                    | number                                           | 10       |          |\n| strictRadial               | Strictly place nodes in the same layer on the same ring         | boolean                                          | true     |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\nResult:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"Basic Radial Layout\" style=\"max-width: 600px;\" />\n\n## Real Cases\n\n- [Basic Radial Layout](/en/examples/layout/radial/#basic)\n- [Strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#strict-prevent-overlap)\n- [Non-strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#non-strict-prevent-overlap)\n- [Cluster Sorting](/en/examples/layout/radial/#cluster-sort)\n","frontmatter":{"title":"Radial Layout","order":"19"},"isInternal":false,"tokens":1242,"sizeBytes":4968},{"name":"RadialLayout.zh.md","path":"packages/site/docs/manual/layout/RadialLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/RadialLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 径向布局 Radial\norder: 19\n---\n\n## 概述\n\n径向（Radial）布局是一种将节点以同心圆方式分层排列的图布局算法，常用于展示层级关系、社群结构等。该布局支持节点防重叠、分组排序等高级特性，适用于多种网络结构的可视化。\n\n## 使用场景\n\n- 展示层级结构（如组织架构、家谱等）\n- 社群结构分析\n- 需要突出中心节点及其辐射关系的场景\n- 需要节点分组、排序的复杂网络\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // 其他配置...\n});\n```\n\n## 配置项\n\n| 属性                       | 描述                                         | 类型                                             | 默认值   | 必选 |\n| -------------------------- | -------------------------------------------- | ------------------------------------------------ | -------- | ---- |\n| type                       | 布局类型                                     | string                                           | `radial` | ✓    |\n| center                     | 圆心坐标                                     | [number, number]                                 | -        |      |\n| focusNode                  | 辐射中心节点                                 | string \\| Node \\| null                           | null     |      |\n| height                     | 画布高度                                     | number                                           | -        |      |\n| width                      | 画布宽度                                     | number                                           | -        |      |\n| nodeSize                   | 节点大小（直径）                             | number \\| number[] \\| ((nodeData: Node) => Size) | -        |      |\n| nodeSpacing                | 节点最小间距（防重叠时生效）                 | number \\| (nodeData: Node) => number             | 10       |      |\n| linkDistance               | 边长度                                       | number                                           | 50       |      |\n| unitRadius                 | 每圈半径；为 null 时按布局空间自动计算       | number \\| null                                   | 100      |      |\n| maxIteration               | 最大迭代次数                                 | number                                           | 1000     |      |\n| maxPreventOverlapIteration | 防重叠最大迭代次数                           | number                                           | 200      |      |\n| preventOverlap             | 是否防止节点重叠                             | boolean                                          | false    |      |\n| sortBy                     | 同层节点排序字段或排序函数                   | string \\| ((nodeData: Node) => number \\| string) | -        |      |\n| sortStrength               | 同层节点排序强度                             | number                                           | 10       |      |\n| strictRadial               | 是否严格每层节点在同一圆环上（防重叠时生效） | boolean                                          | true     |      |\n\n## 代码示例\n\n### 基本用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\n效果如下：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"基本 Radial 辐射布局\" style=\"max-width: 600px;\" />\n\n## 实际案例\n\n- [基本 Radial 辐射布局](/examples/layout/radial/#basic)\n- [防止节点重叠的严格辐射布局](/examples/layout/radial/#strict-prevent-overlap)\n- [防止节点重叠的非严格辐射布局](/examples/layout/radial/#non-strict-prevent-overlap)\n- [排序聚类](/examples/layout/radial/#cluster-sort)\n","frontmatter":{"title":"径向布局 Radial","order":"19"},"isInternal":false,"tokens":960,"sizeBytes":4558},{"name":"RandomLayout.en.md","path":"packages/site/docs/manual/layout/RandomLayout.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/RandomLayout.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Random Layout\norder: 20\n---\n\n## Overview\n\n**Random Layout** is a layout method based on simple rules. Its core logic is to generate random coordinates for each node within a specified layout area (defined by the layout center, width, and height). The coordinates are completely random, and there is no node collision prevention.\n\n## Use Cases\n\nThe use cases for random layout are very limited. It is only recommended for the following scenarios:\n\n- **Initial Data Display**:\n\n  During early development, when debugging data loading logic or quickly verifying data structure, random layout can be used for preliminary validation.\n\nFor final business delivery, it is recommended to use layouts that better reflect business value, such as [AntVDagreLayout](/en/manual/layout/antv-dagre-layout), [ForceLayout](/en/manual/layout/force-layout), or [custom layouts](/en/manual/layout/custom-layout).\n\n## Basic Usage\n\nAll other configurations use defaults (the layout width and height default to the entire canvas container).\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## Options\n\n| Property | Description   | Type                                         | Default                                   | Required |\n| -------- | ------------- | -------------------------------------------- | ----------------------------------------- | -------- |\n| type     | Layout type   | random                                       | -                                         | ✓        |\n| center   | Layout center | [number, number] \\| [number, number, number] | [`layout width` / 2, `layout height` / 2] |          |\n| height   | Layout height | number                                       | canvas height                             |          |\n| width    | Layout width  | number                                       | canvas width                              |          |\n\n## Example\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Random Layout","order":"20"},"isInternal":false,"tokens":598,"sizeBytes":2391},{"name":"RandomLayout.zh.md","path":"packages/site/docs/manual/layout/RandomLayout.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/RandomLayout.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 随机布局 Random\norder: 20\n---\n\n## 概述\n\n**随机布局（Random Layout）** 是一种基于简单规则的布局方式，其核心逻辑是为每个节点在指定布局区域（由布局中心点、宽度和高度定义）内生成随机坐标（完全随机，无节点防碰撞）。\n\n## 使用场景\n\n随机布局的使用场景非常局限，只推荐以下场景使用：\n\n- **数据初步展示**:\n\n  在开发初期调试数据加载逻辑或需要快速验证数据结构的情况下，可使用随机布局先行验证\n\n业务最终交付推荐使用更能体现业务价值的布局方式，比如 [AntVDagreLayout](/manual/layout/antv-dagre-layout) 、[ForceLayout](/manual/layout/force-layout) 或者[自定义布局](/manual/layout/custom-layout)等。\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## 配置项\n\n| 属性   | 描述       | 类型                                         | 默认值                           | 必选 |\n| ------ | ---------- | -------------------------------------------- | -------------------------------- | ---- |\n| type   | 布局类型   | random                                       | -                                | ✓    |\n| center | 布局的中心 | [number, number] \\| [number, number, number] | [`布局宽度` / 2, `布局高度` / 2] |      |\n| height | 布局的高度 | number                                       | 画布高度                         |      |\n| width  | 布局的宽度 | number                                       | 画布宽度                         |      |\n\n## 示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"随机布局 Random","order":"20"},"isInternal":false,"tokens":404,"sizeBytes":2168},{"name":"Snake.en.md","path":"packages/site/docs/manual/layout/Snake.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/Snake.en.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Snake Layout\norder: 21\n---\n\n## Overview\n\nSnake Layout is a special type of graph layout that can more efficiently display long chain structures in a limited space. Note that the graph data must ensure that nodes are linearly arranged from the source node to the sink node, forming a clear path.\n\nNodes are arranged in an S-shape: the first node is at the start of the first row, subsequent nodes are arranged to the right in the first row until the end. At the end of the row, the next row's nodes are arranged from right to left. This process repeats until all nodes are placed.\n\n## Use Cases\n\nSuitable for scenarios that require compact presentation of linear relationships:\n\n- **Long process visualization**\n\n  Perfect for scenarios with many process steps, such as approval flows, production line procedures, logistics routes, etc.\n\n- **Hierarchical structures in limited space**\n\n  When the hierarchy is too long but the canvas is limited, rows can be folded to save space. For example, API call dependencies (client → gateway → serviceA → serviceB → database, snake layout compresses 5 layers into 2 rows), or file directory trees (deeply nested folder structures, e.g., src/components/utils/helpers/..., using snake layout to fold subdirectories horizontally).\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## Options\n\n> If the layout has specific properties, they are listed below. For common layout options, see [Base Layout Options](/en/manual/layout/base-layout)\n\n| Property                | Description                                                 | Type                                               | Default                                                    | Required |\n| ----------------------- | ----------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- | -------- |\n| type                    | Layout type                                                 | snake                                              | -                                                          | ✓        |\n| [clockwise](#clockwise) | Whether nodes are arranged clockwise                        | boolean                                            | true                                                       |          |\n| colGap                  | Gap size between columns                                    | number                                             | Automatically calculated by canvas width and total columns |          |\n| cols                    | Number of columns                                           | number                                             | 5                                                          |          |\n| nodeSize                | Node size                                                   | Size \\| ((node: NodeData) => Size)                 | -                                                          |          |\n| padding                 | Padding, i.e., distance from layout area to canvas boundary | number \\| number[]                                 | 0                                                          |          |\n| rowGap                  | Gap size between rows                                       | number                                             | Automatically calculated by canvas height and total rows   |          |\n| sortBy                  | Node sorting method                                         | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | Default is the path order in the graph                     |          |\n\n### clockwise\n\n- When arranged clockwise, nodes start from the top left, the first row is arranged left to right, the second row right to left, and so on, forming an S-shaped path.\n- When arranged counterclockwise, nodes start from the top right, the first row is arranged right to left, the second row left to right, and so on, forming a reversed S-shaped path.\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Snake Layout","order":"21"},"isInternal":false,"tokens":1145,"sizeBytes":4590},{"name":"Snake.zh.md","path":"packages/site/docs/manual/layout/Snake.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/layout/Snake.zh.md","title":"Layout Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 蛇形布局 Snake\norder: 21\n---\n\n## 概览\n\n蛇形布局（Snake Layout）是一种特殊的图形布局方式，能够在较小的空间内更有效地展示长链结构。需要注意的是，其图数据需要确保节点按照从源节点到汇节点的顺序进行线性排列，形成一条明确的路径。\n\n节点按 S 字型排列，第一个节点位于第一行的起始位置，接下来的节点在第一行向右排列，直到行末尾。到达行末尾后，下一行的节点从右向左反向排列。这个过程重复进行，直到所有节点排列完毕。\n\n## 使用场景\n\n适合需要紧凑呈现线性关系的场景：\n\n- **长流程可视化**\n\n  完美适配流程步骤过多的场景，如审批流程、生产线工序、物流运输路径等。\n\n- **有限空间内的层级结构**\n\n  层级结构过长但画布受限，需通过折叠行节省空间，比如 API 调用依赖（客户端 → 网关 → 服务A → 服务B → 数据库，蛇形布局将 5 层压缩为 2 行）、文件目录树（深度嵌套的文件夹结构，如 src/components/utils/helpers/... ，用蛇形布局横向折叠子目录）。\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## 配置项\n\n> 如果布局有其特定的属性，我们将在下面列出。对于所有布局的通用属性，见[布局通用配置项](/manual/layout/base-layout)\n\n| 属性                    | 描述                               | 类型                                               | 默认值                                 | 必选 |\n| ----------------------- | ---------------------------------- | -------------------------------------------------- | -------------------------------------- | ---- |\n| type                    | 布局类型                           | snake                                              | -                                      | ✓    |\n| [clockwise](#clockwise) | 节点排布方向是否顺时针             | boolean                                            | true                                   |      |\n| colGap                  | 节点列之间的间隙大小               | number                                             | 默认将根据画布宽度和节点总列数自动计算 |      |\n| cols                    | 节点列数                           | number                                             | 5                                      |      |\n| nodeSize                | 节点尺寸                           | Size \\| ((node: NodeData) => Size)                 | -                                      |      |\n| padding                 | 内边距，即布局区域与画布边界的距离 | number \\| number[]                                 | 0                                      |      |\n| rowGap                  | 节点行之间的间隙大小               | number                                             | 默认将根据画布高度和节点总行数自动计算 |      |\n| sortBy                  | 节点排序方法                       | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | 默认按照在图中的路径顺序进行展示       |      |\n\n### clockwise\n\n- 在顺时针排布时，节点从左上角开始，第一行从左到右排列，第二行从右到左排列，依次类推，形成 S 型路径。\n\n- 在逆时针排布时，节点从右上角开始，第一行从右到左排列，第二行从左到右排列，依次类推，形成反向 S 型路径。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"蛇形布局 Snake","order":"21"},"isInternal":false,"tokens":709,"sizeBytes":4081},{"name":"Background.en.md","path":"packages/site/docs/manual/plugin/Background.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Background.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Background\norder: 1\n---\n\n## Overview\n\nSupport setting a background image for the canvas to make the canvas more hierarchical and narrative.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Setting a unified brand background color or image for charts\n- Distinguishing different functional areas through the background\n- Enhancing the visual hierarchy and aesthetics of charts\n\n## Basic Usage\n\nBelow is a simple example of initializing the Background plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // Specify an identifier for the plugin for dynamic updates\n      backgroundColor: '#f0f2f5', // Set background color\n      backgroundImage: 'url(https://example.com/bg.png)', // Set background image\n    },\n  ],\n});\n```\n\n## Configuration Options\n\nThe configuration options for the Background plugin inherit all CSS style properties ([CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)), so you can use any valid CSS property to configure the background. Here are some common configurations:\n\n| Property           | Description                   | Type   | Default Value     | Required |\n| ------------------ | ----------------------------- | ------ | ----------------- | -------- |\n| type               | Plugin type                   | string | `background`      | ✓        |\n| key                | Unique identifier for updates | string | -                 |          |\n| width              | Background width              | string | `100%`            |          |\n| height             | Background height             | string | `100%`            |          |\n| backgroundColor    | Background color              | string | -                 |          |\n| backgroundImage    | Background image              | string | -                 |          |\n| backgroundSize     | Background size               | string | `cover`           |          |\n| backgroundPosition | Background position           | string | -                 |          |\n| backgroundRepeat   | Background repeat             | string | -                 |          |\n| opacity            | Background opacity            | string | -                 |          |\n| transition         | Transition animation          | string | `background 0.5s` |          |\n| zIndex             | Stacking order                | string | -1                |          |\n\n> Note: The `zIndex` is set to -1 by default to prevent the background from covering other plugin DOM elements, such as grid lines.\n\n## Code Examples\n\n### Basic Background Color\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Using a Background Image\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Gradient Background\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Updating the Background\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// Subsequent updates\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## FAQs\n\n### 1. Background conflicts with other plugins?\n\nBy default, the `zIndex` of the background plugin is set to `-1` to ensure it is below other elements. If there are still conflicts, you can adjust the `zIndex` value:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // Lower z-index to avoid conflicts\n    },\n  ],\n});\n```\n","frontmatter":{"title":"Background","order":"1"},"isInternal":false,"tokens":1151,"sizeBytes":4603},{"name":"Background.zh.md","path":"packages/site/docs/manual/plugin/Background.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Background.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 背景 Background\norder: 1\n---\n\n## 概述\n\n支持为图画布设置一个背景图片，让画布更有层次感、叙事性。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 为图表设置统一的品牌背景色或图片\n- 通过背景区分不同的功能区域\n- 增强图表的视觉层次感和美观度\n\n## 基本用法\n\n以下是一个简单的 Background 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // 为插件指定标识符，方便动态更新\n      backgroundColor: '#f0f2f5', // 设置背景色\n      backgroundImage: 'url(https://example.com/bg.png)', // 设置背景图\n    },\n  ],\n});\n```\n\n## 配置项\n\nBackground 插件的配置项继承了所有 CSS 样式属性（[CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration)），因此你可以使用任何合法的 CSS 属性来配置背景。以下是一些常用配置：\n\n| 属性               | 描述                         | 类型   | 默认值            | 必选 |\n| ------------------ | ---------------------------- | ------ | ----------------- | ---- |\n| type               | 插件类型                     | string | `background`      | ✓    |\n| key                | 插件唯一标识符，用于后续更新 | string | -                 |      |\n| width              | 背景宽度                     | string | `100%`            |      |\n| height             | 背景高度                     | string | `100%`            |      |\n| backgroundColor    | 背景颜色                     | string | -                 |      |\n| backgroundImage    | 背景图片                     | string | -                 |      |\n| backgroundSize     | 背景尺寸                     | string | `cover`           |      |\n| backgroundPosition | 背景位置                     | string | -                 |      |\n| backgroundRepeat   | 背景重复方式                 | string | -                 |      |\n| opacity            | 背景透明度                   | string | -                 |      |\n| transition         | 过渡动画                     | string | `background 0.5s` |      |\n| zIndex             | 层叠顺序                     | string | -1                |      |\n\n> 注意：`zIndex` 默认为 -1，这是为了避免背景覆盖其他插件的 DOM 元素，如网格线。\n\n## 代码示例\n\n### 基础背景色\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 使用背景图片\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 渐变背景\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新背景\n\n```js\n// 初始化时配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// 后续更新\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## 常见问题\n\n### 1. 背景与其他插件冲突？\n\n默认情况下，背景插件的 `zIndex` 设为 `-1`，以确保它位于其他元素之下。如果仍有冲突，可以调整 `zIndex` 值：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // 降低 z-index 避免冲突\n    },\n  ],\n});\n```\n","frontmatter":{"title":"背景 Background","order":"1"},"isInternal":false,"tokens":901,"sizeBytes":4373},{"name":"BubbleSets.en.md","path":"packages/site/docs/manual/plugin/BubbleSets.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/BubbleSets.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: BubbleSets\norder: 2\n---\n\n## Overview\n\nThe BubbleSets plugin represents sets and their relationships by creating bubble shapes, helping users intuitively understand logical relationships such as intersections and unions between sets. It is a tool to enhance data visualization effects, especially suitable for displaying complex data set relationships.\n\n## Use Cases\n\nThe BubbleSets plugin is mainly suitable for the following scenarios:\n\n- Displaying relationships between sets (e.g., intersections, unions)\n- Enhancing the expressive ability of data visualization\n- Identifying specific sets of nodes or edges in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the BubbleSets plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // List of node IDs to be enclosed\n      label: true, // Whether to display labels\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## Configuration Options\n\n| Property                 | Description                                                                              | Type                                                           | Default Value | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| type                     | Plugin type                                                                              | string                                                         | `bubble-sets` | ✓        |\n| key                      | Unique identifier for the plugin for subsequent updates                                  | string                                                         | -             |          |\n| members                  | Member elements, including nodes and edges, [example](#members)                          | string[]                                                       | -             | ✓        |\n| avoidMembers             | Elements to avoid, not included when drawing contours (currently supports setting nodes) | string[]                                                       | -             |          |\n| label                    | Whether to display labels                                                                | boolean                                                        | true          |          |\n| labelPlacement           | Label position                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |          |\n| labelBackground          | Whether to display background                                                            | boolean                                                        | false         |          |\n| labelPadding             | Label padding                                                                            | number \\| number[]                                             | 0             |          |\n| labelCloseToPath         | Whether the label is close to the contour, [example](#labelclosetopath)                  | boolean                                                        | true          |          |\n| labelAutoRotate          | Whether the label rotates with the contour, [example](#labelautorotate)                  | boolean                                                        | true          |          |\n| labelOffsetX             | Label x-axis offset                                                                      | number                                                         | 0             |          |\n| labelOffsetY             | Label y-axis offset                                                                      | number                                                         | 0             |          |\n| labelMaxWidth            | Maximum width of the text, automatically ellipsized if exceeded                          | number                                                         | -             |          |\n| maxRoutingIterations     | Maximum number of iterations for calculating paths between members                       | number                                                         | 100           |          |\n| maxMarchingIterations    | Maximum number of iterations for calculating contours                                    | number                                                         | 20            |          |\n| pixelGroup               | Number of pixels per potential area group, used to improve speed                         | number                                                         | 4             |          |\n| edgeR0                   | Edge radius parameter R0                                                                 | number                                                         | -             |          |\n| edgeR1                   | Edge radius parameter R1                                                                 | number                                                         | -             |          |\n| nodeR0                   | Node radius parameter R0                                                                 | number                                                         | -             |          |\n| nodeR1                   | Node radius parameter R1                                                                 | number                                                         | -             |          |\n| morphBuffer              | Morph buffer size                                                                        | number                                                         |               |          |\n| threshold                | Threshold                                                                                | number                                                         | -             |          |\n| memberInfluenceFactor    | Member influence factor                                                                  | number                                                         | -             |          |\n| edgeInfluenceFactor      | Edge influence factor                                                                    | number                                                         | -             |          |\n| nonMemberInfluenceFactor | Non-member influence factor                                                              | number                                                         | -             |          |\n| virtualEdges             | Whether to use virtual edges                                                             | boolean                                                        | -             |          |\n\n### members\n\nMember elements, including nodes and edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\nExample: Do not let the label stick to the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\nExample: Do not let the label rotate with the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Usage Examples\n\n### Basic BubbleSets\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom BubbleSets Style\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visualization effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"BubbleSets","order":"2"},"isInternal":false,"tokens":5495,"sizeBytes":21981},{"name":"BubbleSets.zh.md","path":"packages/site/docs/manual/plugin/BubbleSets.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/BubbleSets.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 气泡集 BubbleSets\norder: 2\n---\n\n## 概述\n\nBubbleSets 插件通过创建气泡形状来表示集合及其关系，帮助用户直观地理解集合间的交集、并集等逻辑关系。它是一种增强数据可视化效果的工具，特别适用于展示复杂的数据集合关系。\n\n## 使用场景\n\nBubbleSets 插件主要适用于以下场景：\n\n- 展示集合间的关系（如交集、并集）\n- 增强数据可视化的表达能力\n- 在复杂网络图中标识特定节点或边的集合\n\n## 基本用法\n\n以下是一个简单的 BubbleSets 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // 需要包裹的节点 ID 列表\n      label: true, // 是否显示标签\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## 配置项\n\n| 属性                     | 描述                                                             | 类型                                                           | 默认值        | 必选 |\n| ------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | ---- |\n| type                     | 插件类型                                                         | string                                                         | `bubble-sets` | ✓    |\n| key                      | 插件唯一标识符，用于后续更新                                     | string                                                         | -             |      |\n| members                  | 成员元素，包括节点和边，[示例](#members)                         | string[]                                                       | -             | ✓    |\n| avoidMembers             | 需要避开的元素，在绘制轮廓时不会包含这些元素（目前支持设置节点） | string[]                                                       | -             |      |\n| label                    | 是否显示标签                                                     | boolean                                                        | true          |      |\n| labelPlacement           | 标签位置                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |      |\n| labelBackground          | 是否显示背景                                                     | boolean                                                        | false         |      |\n| labelPadding             | 标签内边距                                                       | number \\| number[]                                             | 0             |      |\n| labelCloseToPath         | 标签是否贴合轮廓，[示例](#labelclosetopath)                      | boolean                                                        | true          |      |\n| labelAutoRotate          | 标签是否跟随轮廓旋转，[示例](#labelautorotate)                   | boolean                                                        | true          |      |\n| labelOffsetX             | 标签 x 轴偏移量                                                  | number                                                         | 0             |      |\n| labelOffsetY             | 标签 y 轴偏移量                                                  | number                                                         | 0             |      |\n| labelMaxWidth            | 文本的最大宽度，超出会自动省略                                   | number                                                         | -             |      |\n| maxRoutingIterations     | 计算成员之间路径的最大迭代次数                                   | number                                                         | 100           |      |\n| maxMarchingIterations    | 计算轮廓的最大迭代次数                                           | number                                                         | 20            |      |\n| pixelGroup               | 每个潜在区域组的像素数，用于提高速度                             | number                                                         | 4             |      |\n| edgeR0                   | 边的半径参数 R0                                                  | number                                                         | -             |      |\n| edgeR1                   | 边的半径参数 R1                                                  | number                                                         | -             |      |\n| nodeR0                   | 节点的半径参数 R0                                                | number                                                         | -             |      |\n| nodeR1                   | 节点的半径参数 R1                                                | number                                                         | -             |      |\n| morphBuffer              | 形态缓冲区大小                                                   | number                                                         |               |      |\n| threshold                | 阈值                                                             | number                                                         | -             |      |\n| memberInfluenceFactor    | 成员影响因子                                                     | number                                                         | -             |      |\n| edgeInfluenceFactor      | 边影响因子                                                       | number                                                         | -             |      |\n| nonMemberInfluenceFactor | 非成员影响因子                                                   | number                                                         | -             |      |\n| virtualEdges             | 是否使用虚拟边                                                   | boolean                                                        | -             |      |\n\n### members\n\n成员元素，包括节点和边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\n示例：不让 label 贴合轮廓\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\n示例：不让label标签跟随轮廓旋转\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 使用示例\n\n### 基础 BubbleSets\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义 BubbleSets 样式\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"气泡集 BubbleSets","order":"2"},"isInternal":false,"tokens":4955,"sizeBytes":21143},{"name":"Contextmenu.en.md","path":"packages/site/docs/manual/plugin/Contextmenu.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Contextmenu.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Contextmenu\norder: 3\n---\n\n## Overview\n\nThe context menu, also known as the right-click menu, is a menu that appears when a user clicks on a specific area. It supports triggering custom events before and after clicking. Through the context menu, specific element operations can be integrated, making it convenient to control a particular item when needed.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Various interactions with elements: viewing nodes, viewing edges, deleting nodes, etc.\n\n## Basic Usage\n\nBelow is a simple example of initializing the Contextmenu plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // Enable right-click menu only on nodes, by default all elements are enabled\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: 'View Details', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('Display node details');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property       | Description                                                                                                               | Type                                                                              | Default Value    | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | -------- |\n| className      | Additional class name for the menu DOM                                                                                    | string                                                                            | `g6-contextmenu` |          |\n| trigger        | How to trigger the right-click menu: `contextmenu` for right-click, `click` for click                                     | `click` \\| `contextmenu`                                                          | `contextmenu`    |          |\n| offset         | Offset of the menu display in X and Y directions                                                                          | [number, number]                                                                  | [4, 4]           |          |\n| onClick        | Callback method triggered after the menu is clicked, [example](#onclick)                                                  | (value: string, target: HTMLElement, current: Element) => void                    | -                |          |\n| getItems       | Returns the list of menu items, supports `Promise` type return value. It is a shortcut configuration for `getContent`     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |          |\n| getContent     | Returns the content of the menu, supports `Promise` type return value, can also use `getItems` for shortcut configuration | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |          |\n| loadingContent | Menu content used when `getContent` returns a `Promise`                                                                   | HTMLElement \\| string                                                             | -                |          |\n| enable         | Whether it is available, determines whether the right-click menu is supported by parameters, by default all are available | boolean \\| (event: IElementEvent) => boolean                                      | true             |          |\n\n### Item\n\nEach menu item (Item) contains the following properties:\n\n| Property | Description                          | Type     | Required |\n| -------- | ------------------------------------ | -------- | -------- |\n| name     | Name displayed for the menu item     | `string` | ✓        |\n| value    | Value corresponding to the menu item | `string` | ✓        |\n\n### onClick\n\nThis function is triggered after clicking a menu item, and the function has three parameters:\n\n- value: Corresponds to the value of the menu item\n- target: The DOM node of the menu item container\n- current: The element that triggered the menu item, for example, if it is a node, you can use `current` to get the node information (id), or to modify the element\n\n## Code Examples\n\n### Basic Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + value + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: 'View Details', value: 'detail' },\n          { name: 'Delete', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### Edge Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: 'Change Start Point', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('Execute change start point operation here');\n      },\n      // Enable right-click menu only on edges\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### Asynchronous Loading of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // Enable right-click menu only on nodes\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Dynamic Control of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: 'Delete Node',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: 'Move Edge',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Contextmenu","order":"3"},"isInternal":false,"tokens":2199,"sizeBytes":8828},{"name":"Contextmenu.zh.md","path":"packages/site/docs/manual/plugin/Contextmenu.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Contextmenu.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 上下文菜单 Contextmenu\norder: 3\n---\n\n## 概述\n\n上下文菜单（Contextmenu），也被称为右键菜单，是当用户在某个特定区域上点击后出现的一个菜单。支持在点击前后，触发自定义事件。通过上下文菜单，可以将一些具体元素的操作集成在其中，方便对某一项来进行需要时的单独控制。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 元素的各种交互：查看节点、查看边、删除节点等等交互操作\n\n## 基本用法\n\n以下是一个简单的 Contextmenu 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // 只在节点上开启右键菜单，默认全部元素都开启\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: '查看详情', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('展示节点详情');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                            | 类型                                                                              | 默认值           | 必选 |\n| -------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | ---- |\n| className      | 给菜单的 DOM 追加的类名                                                         | string                                                                            | `g6-contextmenu` |      |\n| trigger        | 如何触发右键菜单：`contextmenu` 表示右键触发，`click` 表示点击触发              | `click` \\| `contextmenu`                                                          | `contextmenu`    |      |\n| offset         | 菜单显式 X、Y 方向的偏移量                                                      | [number, number]                                                                  | [4, 4]           |      |\n| onClick        | 当菜单被点击后，触发的回调方法，[示例](#onclick)                                | (value: string, target: HTMLElement, current: Element) => void                    | -                |      |\n| getItems       | 返回菜单的项目列表，支持 `Promise` 类型的返回值。是 `getContent` 的快捷配置     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |      |\n| getContent     | 返回菜单的内容，支持 `Promise` 类型的返回值，也可以使用 `getItems` 进行快捷配置 | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |      |\n| loadingContent | 当 `getContent` 返回一个 `Promise` 时，使用的菜单内容                           | HTMLElement \\| string                                                             | -                |      |\n| enable         | 是否可用，通过参数判断是否支持右键菜单，默认是全部可用                          | boolean \\| (event: IElementEvent) => boolean                                      | true             |      |\n\n### Item\n\n每个菜单项目 (Item) 包含以下属性：\n\n| 属性  | 描述             | 类型     | 必选 |\n| ----- | ---------------- | -------- | ---- |\n| name  | 菜单项显示的名字 | `string` | ✓    |\n| value | 菜单项对应的值   | `string` | ✓    |\n\n### onClick\n\n点击菜单项后会触发该函数，函数有三个参数：\n\n- value: 对应菜单项的 value\n- target: 对应菜单项容器的 dom 节点\n- current: 对应触发菜单项的元素，例如是节点则可以通过 `current` 来获取到节点的信息(id)等，或者来对元素进行修改\n\n## 代码示例\n\n### 基础右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '查看详情', value: 'detail' },\n          { name: '删除', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### 边的右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: '变更起点', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('这里执行变更起点操作');\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### 异步加载菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 动态控制菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: '删除节点',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: '移动边',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"上下文菜单 Contextmenu","order":"3"},"isInternal":false,"tokens":1766,"sizeBytes":8258},{"name":"custom-plugin.en.md","path":"packages/site/docs/manual/plugin/custom-plugin.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/custom-plugin.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Plugin\norder: 20\n---\n\n## Overview\n\nCustom plugins can implement additional features, such as adding extra components, rendering logic, etc. Custom plugins can effectively achieve functional decoupling, better manage and orchestrate code, and facilitate subsequent maintenance.\n\n## Use Cases\n\n### Add extra components, rendering logic, etc.\n\n- **Extra components**: Such as built-in plugins like `Tooltip`, `Minimap`, `Snapline`, `Grid`, `Context Menu`, `Watermark`, etc.\n- **Rendering logic**: Such as built-in plugins like `Edge Bundling`, and `Remote Data Loading` ([Example](#remote-data-loading)), etc.\n\n### When built-in plugins cannot meet the requirements\n\nWhen built-in plugins cannot fully meet business needs, users can also make adjustments and modifications through custom plugins (inheriting built-in plugins).\n\n_(If the features supported by built-in plugins are more general, or if there are bugs in built-in plugins, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Custom Plugin Examples\n\nLike interactions, the implementation of plugins is also quite flexible, and you can implement your plugin in your preferred style.\n\nHere are a few simple custom plugin implementations:\n\n### Remote Data Loading\n\nAutomatically load remote data during graph instantiation:\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- In this example, we simulate a data loading plugin. After using this plugin, there is no need to pass data when instantiating the Graph, as the plugin will automatically load remote data.\n\n- `BasePlugin` is the base class for all plugins, and each custom plugin needs to inherit this base class.\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### Automatically Enable or Disable Animation Based on Node Count\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // Disable global animation when the number of nodes reaches this value\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In this example, we listen to the `GraphEvent.BEFORE_RENDER` event and determine whether the current number of nodes exceeds a specified value. If so, global animation is disabled; otherwise, it is enabled.\n- `maxLength` is a defined configuration item that can be passed in when initializing the graph instance. [Plugin Configuration](#configure-plugin)\n\n## Register Plugin\n\nRegister using the method provided by G6\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## Configure Plugin\n\n- You can pass the plugin type name or configuration parameter object in `plugins`, see [Configure Plugin](/manual/plugin/overview#configuration-method)\n\n- For example, the previous [Automatically Enable or Disable Animation Based on Node Count](#automatically-enable-or-disable-animation-based-on-node-count) is configured as follows:\n\n  ```typescript\n  const graph = new Graph({\n    // Other configurations\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","frontmatter":{"title":"Custom Plugin","order":"20"},"isInternal":false,"tokens":1192,"sizeBytes":4767},{"name":"custom-plugin.zh.md","path":"packages/site/docs/manual/plugin/custom-plugin.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/custom-plugin.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义插件\norder: 20\n---\n\n## 概述\n\n自定义插件可以实现一些额外的功能，例如添加额外的组件、渲染逻辑等。通过自定义插件可以很好地实现功能解耦，更好地进行管理、编排代码以及后续维护。\n\n## 使用场景\n\n### 添加额外的组件、渲染逻辑等\n\n- **额外的组件**：如内置插件的`提示框`、`小地图`、`对齐线`、`网格线`、`上下文菜单`、`水印`等\n- **渲染逻辑**：如内置插件的`边绑定`，以及`远程数据加载`（[示例](#远程数据加载)）等\n\n### 内置插件无法满足需求\n\n当内置插件无法完全满足业务需求时，用户也可以通过自定义插件（继承内置插件）进行调整和修改。\n\n_（如果需要内置插件支持的特性是较通用的，或者内置插件存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 自定义插件示例\n\n与交互类似，插件的实现也相当灵活，你可以以你喜欢的风格实现你的插件。\n\n下面列举几个简单的自定义插件实现：\n\n### 远程数据加载\n\n在图实例化过程中自动加载远程数据：\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- 在这个例子中，我们模拟实现了一个数据加载插件，在使用该插件后，实例化 Graph 时不用再传入数据，该插件会自动加载远程数据。\n\n- `BasePlugin` 是所有插件的基类，每个自定义插件都需要继承这个基类实现。\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### 自动判断节点数量开启或关闭动画\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // 节点数量达到这个值后关闭全局动画\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在这个例子中，我们监听 `GraphEvent.BEFORE_RENDER` 事件，在响应中判断当前节点数量是否大于指定值，是的话则关闭全局动画，否则开启\n- `maxLength` 是定义的配置项，可在初始化画布实例时传入具体配置，[插件配置](#配置插件)\n\n## 注册插件\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## 配置插件\n\n- 可在 `plugins` 中传入插件类型名称或配置参数对象，详见[配置插件](/manual/plugin/overview#配置方式)\n\n- 比如前面的[自动判断节点数量开启或关闭动画](#自动判断节点数量开启或关闭动画)，配置如下：\n\n  ```typescript\n  const graph = new Graph({\n    // 其他配置\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n","frontmatter":{"title":"自定义插件","order":"20"},"isInternal":false,"tokens":791,"sizeBytes":4432},{"name":"EdgeBundling.en.md","path":"packages/site/docs/manual/plugin/EdgeBundling.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/EdgeBundling.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: EdgeBundling\norder: 4\n---\n\n## Overview\n\nEdge bundling is a graph visualization technique used to reduce visual clutter in complex network graphs and to reveal high-level patterns and structures in the graph. Its purpose is to bundle adjacent edges together.\n\nThe edge bundling plugin provided in G6 is based on the implementation of the [FEDB (Force-Directed Edge Bundling for Graph Visualization)](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf) paper: modeling edges as flexible springs that can attract each other and bundling them through a self-organizing process.\n\n## Use Cases\n\nThe edge bundling plugin is mainly suitable for the following scenarios:\n\n- Reducing visual clutter in complex network graphs\n- Revealing high-level patterns and structures in the graph\n- Improving the readability and aesthetics of large-scale graph data\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeBundling plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property        | Description                                                                                                                                                                                            | Type   | Default Value   | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | --------------- | -------- |\n| type            | Plugin type, used to identify the plugin as an edge bundling plugin                                                                                                                                    | string | `edge-bundling` | ✓        |\n| key             | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                      | string | -               |          |\n| bundleThreshold | Edge compatibility threshold, determines which edges should be bundled together, the larger the value, the fewer edges are bundled, [example](#bundlethreshold)                                        | number | 0.6             |          |\n| cycles          | Number of simulation cycles, controls the number of execution rounds of the edge bundling simulation                                                                                                   | number | 6               |          |\n| divisions       | Initial number of cut points, in subsequent cycles, the number of cut points will gradually increase according to divRate, affecting the degree of edge subdivision                                    | number | 1               |          |\n| divRate         | Growth rate of cut points, determines the growth rate of cut points in each cycle                                                                                                                      | number | 2               |          |\n| iterations      | Specifies the number of iterations executed in the first cycle, in subsequent cycles, the number of iterations will gradually decrease according to iterRate, affecting the accuracy of the simulation | number | 90              |          |\n| iterRate        | Iteration decrement rate, controls the reduction ratio of iterations in each cycle                                                                                                                     | number | 2/3             |          |\n| K               | Edge strength, affects the attraction and repulsion between edges, [example](#k)                                                                                                                       | number | 0.1             |          |\n| lambda          | Initial step size, in subsequent cycles, the step size will double increment, affecting the magnitude of node movement during edge bundling                                                            | number | 0.1             |          |\n\n### bundleThreshold\n\nEdge compatibility threshold, determines which edges should be bundled together. The larger the value, the fewer edges are bundled, and vice versa.\n\n- A lower bundleThreshold value (e.g., 0.4) will cause more edges to be bundled together, forming a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // Lower edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge compatibility threshold\">\n\n- A higher bundleThreshold value (e.g., 0.8) will cause fewer edges to be bundled together, maintaining more independent edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge compatibility threshold\">\n\n### K\n\nEdge strength, affects the attraction and repulsion between edges. A higher K value will make the attraction between edges stronger, resulting in a tighter bundling effect.\n\n- A lower K value (e.g., 0.05) will make the attraction between edges weaker, resulting in a weaker bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // Lower edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge strength\">\n\n- A higher K value (e.g., 0.2) will make the attraction between edges stronger, resulting in a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // Higher edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge strength\">\n\n## Code Examples\n\n### Basic Edge Bundling\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['edge-bundling'],\n});\n```\n\n### Custom Styles\n\nYou can customize the parameters of edge bundling as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n      cycles: 8, // More simulation cycles\n      K: 0.2, // Stronger edge strength\n    },\n  ],\n});\n```\n\n### Dynamic Update of Edge Bundling\n\nUse the key identifier to dynamically update edge bundling properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// Subsequent dynamic update\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // Update edge compatibility threshold\n  cycles: 10, // Update number of simulation cycles\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"EdgeBundling","order":"4"},"isInternal":false,"tokens":2067,"sizeBytes":8268},{"name":"EdgeBundling.zh.md","path":"packages/site/docs/manual/plugin/EdgeBundling.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/EdgeBundling.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 边绑定 EdgeBundling\norder: 4\n---\n\n## 概述\n\n边绑定（Edge Bundling）是一种图可视化技术，用于减少复杂网络图中的视觉混乱，并展示图中的高级别模式和结构。其目的是将相邻的边捆绑在一起。\n\nG6 中提供的边绑定插件是基于 [FEDB（Force-Directed Edge Bundling for Graph Visualization）](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf)论文的实现：将边建模为可以相互吸引的柔性弹簧，通过自组织的方式进行捆绑。\n\n## 使用场景\n\n边绑定插件主要适用于以下场景：\n\n- 减少复杂网络图中的视觉混乱\n- 揭示图中的高级别模式和结构\n- 提高大规模图数据的可读性和美观性\n\n## 基本用法\n\n以下是一个简单的 EdgeBundling 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性            | 描述                                                                                               | 类型   | 默认值          | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------- | ------ | --------------- | ---- |\n| type            | 插件类型，用于标识该插件为边捆绑插件                                                               | string | `edge-bundling` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                   | string | -               |      |\n| bundleThreshold | 边兼容性阈值，该值决定了哪些边应该被绑定在一起，值越大，绑定的边越少，[示例](#bundlethreshold)     | number | 0.6             |      |\n| cycles          | 模拟周期数，控制边捆绑模拟的执行轮数                                                               | number | 6               |      |\n| divisions       | 初始切割点数，在后续的周期中，切割点数将根据 divRate 逐步递增，影响边的细分程度                    | number | 1               |      |\n| divRate         | 切割点数增长率，决定了每一轮周期中切割点数的增长幅度                                               | number | 2               |      |\n| iterations      | 指定在第一个周期中执行的迭代次数，在后续的周期中，迭代次数将根据 iterRate 逐步递减，影响模拟的精度 | number | 90              |      |\n| iterRate        | 迭代次数递减率，控制每一轮周期中迭代次数的减少比例                                                 | number | 2\\/3            |      |\n| K               | 边的强度，影响边之间的吸引力和排斥力，[示例](#k)                                                   | number | 0.1             |      |\n| lambda          | 初始步长，在后续的周期中，步长将双倍递增，影响边捆绑过程中节点移动的幅度                           | number | 0.1             |      |\n\n### bundleThreshold\n\n边兼容性阈值，该值决定了哪些边应该被绑定在一起。值越大，绑定的边越少，反之则绑定的边越多。\n\n- 较低的 bundleThreshold 值（如 0.4）会使更多的边被绑定在一起，形成更明显的捆绑效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // 较低的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边兼容性阈值\">\n\n- 较高的 bundleThreshold 值（如 0.8）会使较少的边被绑定在一起，保持更多的独立边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 较高的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边兼容性阈值\">\n\n### K\n\n边的强度，影响边之间的吸引力和排斥力。较高的 K 值会使边之间的吸引力更强，从而形成更紧密的捆绑效果。\n\n- 较低的 K 值（如 0.05）会使边之间的吸引力较弱，边的捆绑效果较弱。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // 较低的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边强度\">\n\n- 较高的 K 值（如 0.2）会使边之间的吸引力较强，边的捆绑效果更明显。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // 较高的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边强度\">\n\n## 代码示例\n\n### 基础边绑定\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['edge-bundling'],\n});\n```\n\n### 自定义样式\n\n您可以根据需要自定义边绑定的参数：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 更高的边兼容性阈值\n      cycles: 8, // 更多模拟周期\n      K: 0.2, // 更强的边强度\n    },\n  ],\n});\n```\n\n### 动态更新边绑定\n\n使用 key 标识符可以在运行时动态更新边绑定属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // 更新边兼容性阈值\n  cycles: 10, // 更新模拟周期数\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"边绑定 EdgeBundling","order":"4"},"isInternal":false,"tokens":1248,"sizeBytes":6837},{"name":"EdgeFilterLens.en.md","path":"packages/site/docs/manual/plugin/EdgeFilterLens.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/EdgeFilterLens.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: EdgeFilterLens\norder: 5\n---\n\n## Overview\n\nThe Edge Filter Lens plugin allows you to keep the edges of interest within the lens range, while other edges will not be displayed in that range. This is an important visualization exploration tool that can help users focus on edge relationships in specific areas.\n\n## Use Cases\n\n- Need to focus on viewing edge relationships in local areas\n- Highlight connections between specific nodes in complex networks\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeFilterLens plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // Follow mouse movement\n      r: 60, // Set lens radius\n      nodeType: 'both', // Edge display condition\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                                                                                                                                                                                 | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                  | `edge-filter-lens`                          | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                                                                                                                                                                                           | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the lens:<br/>- `pointermove`: The lens always follows the mouse movement <br/>- `click`: Move the lens to the click position when clicking on the canvas <br/>- `drag`: Move the lens by dragging                                                                                                                                                                           | `pointermove` \\| `click` \\| `drag`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the lens                                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                  | 60                                          |          |\n| maxR           | Maximum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to scale the lens radius: `wheel`: Scale the lens radius by the wheel                                                                                                                                                                                                                                                                                                                | `wheel`                                                                                                                                                                 | -                                           |          |\n| nodeType       | Edge display condition:<br/> - `both`: The edge is displayed only when both the source and target nodes are in the lens <br/> - `source`: The edge is displayed only when the source node is in the lens<br/> - `target`: The edge is displayed only when the target node is in the lens <br/> - `either`: The edge is displayed as long as either the source or target node is in the lens | `both` \\| `source` \\| `target` \\| `either`                                                                                                                              | `both`                                      |          |\n| filter         | Filter out elements that are never displayed in the lens                                                                                                                                                                                                                                                                                                                                    | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                       | () => true                                  |          |\n| style          | Style of the lens, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                          | object                                                                                                                                                                  |                                             |          |\n| nodeStyle      | Style of nodes in the lens                                                                                                                                                                                                                                                                                                                                                                  | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: false }`                          |          |\n| edgeStyle      | Style of edges in the lens                                                                                                                                                                                                                                                                                                                                                                  | [EdgeStyle](/en/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/en/manual/data#边数据edgedata)) => [EdgeStyle](/en/manual/element/edge/base-edge#style))   | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                                                                                                                                                                                           | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nStyle properties of the circular lens.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#fff`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | 1             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.8           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the lens:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Edge Filter Lens](/en/examples/plugin/edge-filter-lens/#basic)\n","frontmatter":{"title":"EdgeFilterLens","order":"5"},"isInternal":false,"tokens":4670,"sizeBytes":18693},{"name":"EdgeFilterLens.zh.md","path":"packages/site/docs/manual/plugin/EdgeFilterLens.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/EdgeFilterLens.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 边过滤镜 EdgeFilterLens\norder: 5\n---\n\n## 概述\n\n边过滤镜插件可以将关注的边保留在过滤镜范围内，其他边将在该范围内不显示。这是一个重要的可视化探索工具，可以帮助用户聚焦于特定区域的边关系。\n\n## 使用场景\n\n- 需要聚焦查看局部区域的边关系\n- 在复杂网络中突出显示特定节点之间的连接\n\n## 基本用法\n\n以下是一个简单的 EdgeFilterLens 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // 跟随鼠标移动\n      r: 60, // 设置透镜半径\n      nodeType: 'both', // 边的显示条件\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                                                                       | 类型                                                                                                                                                           | 默认值               | 必选 |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                                                                                   | string                                                                                                                                                         | `edge-filter-lens`   | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                                                                                           | string                                                                                                                                                         | -                    |      |\n| trigger        | 移动透镜的方式：<br/>- `pointermove`：透镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动透镜到点击位置 <br/>- `drag`：通过拖拽方式移动透镜                                                                                                                | `pointermove` \\| `click` \\| `drag`                                                                                                                             | `pointermove`        |      |\n| r              | 透镜的半径                                                                                                                                                                                                                                                 | number                                                                                                                                                         | 60                   |      |\n| maxR           | 透镜的最大半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 画布宽高最小值的一半 |      |\n| minR           | 透镜的最小半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 0                    |      |\n| scaleRBy       | 缩放透镜半径的方式：`wheel`：通过滚轮缩放透镜的半径                                                                                                                                                                                                        | `wheel`                                                                                                                                                        | -                    |      |\n| nodeType       | 边显示的条件：<br/> - `both`：只有起始节点和目标节点都在透镜中时，边才会显示 <br/> - `source`：只有起始节点在透镜中时，边才会显示<br/> - `target`：只有目标节点在透镜中时，边才会显示 <br/> - `either`：只要起始节点或目标节点有一个在透镜中时，边就会显示 | `both` \\| `source` \\| `target` \\| `either`                                                                                                                     | `both`               |      |\n| filter         | 过滤出始终不在透镜中显示的元素                                                                                                                                                                                                                             | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                              | () => true           |      |\n| style          | 透镜的样式，[配置项](#style)                                                                                                                                                                                                                               | object                                                                                                                                                         |                      |      |\n| nodeStyle      | 在透镜中节点的样式                                                                                                                                                                                                                                         | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: false }`   |      |\n| edgeStyle      | 在透镜中边的样式                                                                                                                                                                                                                                           | [EdgeStyle](/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/manual/data#边数据edgedata)) => [EdgeStyle](/manual/element/edge/base-edge#style))   | `{ label: true }`    |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                                                                                           | boolean                                                                                                                                                        | true                 |      |\n\n### style\n\n圆形透镜的样式属性。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#fff` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | 1      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.8    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义透镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [边过滤镜](/examples/plugin/edge-filter-lens/#basic)\n","frontmatter":{"title":"边过滤镜 EdgeFilterLens","order":"5"},"isInternal":false,"tokens":3620,"sizeBytes":16159},{"name":"Fisheye.en.md","path":"packages/site/docs/manual/plugin/Fisheye.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Fisheye.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Fisheye\norder: 6\n---\n\n## Overview\n\nThe Fisheye plugin is designed for focus+context exploration scenarios. It can magnify the area of interest while ensuring that the context and the relationship between the context and the focus center are not lost. It is an important visualization exploration tool.\n\n## Use Cases\n\n- Highlight certain areas during presentations\n- Magnify details locally without losing the overall view\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fisheye plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // Move fisheye by dragging\n      d: 1.5, // Set distortion factor\n      r: 120, // Set fisheye radius\n      showDPercent: true, // Show distortion degree\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                   | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                   | string                                                                                                                                                                  | `fisheye`                                   | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                             | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the fisheye:<br/>- `pointermove`: The fisheye always follows the mouse movement <br/>- `click`: Move the fisheye to the click position when clicking on the canvas <br/>- `drag`: Move the fisheye by dragging | `pointermove` \\| `drag` \\| `click`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the fisheye                                                                                                                                                                                                         | number                                                                                                                                                                  | 120                                         |          |\n| maxR           | Maximum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | 0                                           |          |\n| d              | Distortion factor                                                                                                                                                                                                             | number                                                                                                                                                                  | 1.5                                         |          |\n| maxD           | Maximum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 5                                           |          |\n| minD           | Minimum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to adjust the fisheye radius:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                                     | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| scaleDBy       | Method to adjust the fisheye distortion factor:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                          | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| showDPercent   | Whether to show the distortion factor value in the fisheye                                                                                                                                                                    | boolean                                                                                                                                                                 | true                                        |          |\n| style          | Style of the fisheye, [configuration options](#style)                                                                                                                                                                         | object                                                                                                                                                                  | -                                           |          |\n| nodeStyle      | Style of nodes in the fisheye                                                                                                                                                                                                 | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                             | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nCircular style properties for configuring the appearance of the fisheye.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#ccc`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | -             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.1           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n### Zoom Control\n\n`scaleRBy` and `scaleDBy` can be used to control the adjustment method of the fisheye's radius and distortion factor respectively:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // Adjust radius by wheel\n      scaleRBy: 'wheel',\n      // Adjust distortion factor by dragging\n      scaleDBy: 'drag',\n      // Set range for radius and distortion factor\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\nNote: When `trigger`, `scaleRBy`, and `scaleDBy` are all set to `'drag'`, the priority order is `trigger` > `scaleRBy` > `scaleDBy`, and only the highest priority configuration item will bind the drag event. Similarly, if `scaleRBy` and `scaleDBy` are both set to `'wheel'`, only `scaleRBy` will bind the wheel event.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the fisheye:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","frontmatter":{"title":"Fisheye","order":"6"},"isInternal":false,"tokens":4337,"sizeBytes":17357},{"name":"Fisheye.zh.md","path":"packages/site/docs/manual/plugin/Fisheye.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Fisheye.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 鱼眼放大镜 Fisheye\norder: 6\n---\n\n## 概述\n\n鱼眼放大镜插件是为 focus+context 的探索场景设计的，它能够在放大关注区域的同时，保证上下文以及上下文与关注中心的关系不丢失，是一个重要的可视化探索工具。\n\n## 使用场景\n\n- 在演示过程中需要突出展示某些区域内容\n- 需要局部放大查看细节时，同时又不想失去整体视图\n\n## 基本用法\n\n以下是一个简单的 Fisheye 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // 通过拖拽移动鱼眼\n      d: 1.5, // 设置畸变因子\n      r: 120, // 设置鱼眼半径\n      showDPercent: true, // 显示畸变程度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                          | 类型                                                                                                                                                           | 默认值                 | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                      | string                                                                                                                                                         | `fisheye`              | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                              | string                                                                                                                                                         | -                      |      |\n| trigger        | 用于控制鱼眼放大镜的移动方式，支持以下三种配置：<br/>- `pointermove`：鱼眼放大镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动鱼眼放大镜到点击位置 <br/>- `drag`：通过拖拽方式移动鱼眼放大镜 | `pointermove` \\| `drag` \\| `click`                                                                                                                             | `pointermove`          |      |\n| r              | 鱼眼放大镜半径                                                                                                                                                                                | number                                                                                                                                                         | 120                    |      |\n| maxR           | 鱼眼放大镜可调整的最大半径                                                                                                                                                                    | number                                                                                                                                                         | 画布宽高的最小值的一半 |      |\n| minR           | 鱼眼放大镜可调整的最小半径                                                                                                                                                                    | number                                                                                                                                                         | 0                      |      |\n| d              | 畸变因子                                                                                                                                                                                      | number                                                                                                                                                         | 1.5                    |      |\n| maxD           | 鱼眼放大镜可调整的最大畸变因子                                                                                                                                                                | number                                                                                                                                                         | 5                      |      |\n| minD           | 鱼眼放大镜可调整的最小畸变因子                                                                                                                                                                | number                                                                                                                                                         | 0                      |      |\n| scaleRBy       | 调整鱼眼放大镜范围半径的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| scaleDBy       | 调整鱼眼放大镜畸变因子的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| showDPercent   | 是否在鱼眼放大镜中显示畸变因子数值                                                                                                                                                            | boolean                                                                                                                                                        | true                   |      |\n| style          | 鱼眼放大镜样式，[配置项](#style)                                                                                                                                                              | object                                                                                                                                                         | -                      |      |\n| nodeStyle      | 在鱼眼放大镜中的节点样式                                                                                                                                                                      | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: true }`      |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                              | boolean                                                                                                                                                        | true                   |      |\n\n### style\n\n圆形样式属性，用于配置鱼眼放大镜的外观。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#ccc` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | -      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.1    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n### 缩放控制\n\n通过 `scaleRBy` 和 `scaleDBy` 可以分别控制鱼眼放大镜的半径和畸变因子的调整方式：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // 通过滚轮调整半径\n      scaleRBy: 'wheel',\n      // 通过拖拽调整畸变因子\n      scaleDBy: 'drag',\n      // 设置半径和畸变因子的范围\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\n注意：当 `trigger`、`scaleRBy` 和 `scaleDBy` 同时设置为 `'drag'` 时，优先级顺序为 `trigger` > `scaleRBy` > `scaleDBy`，只会为优先级最高的配置项绑定拖拽事件。同理，如果 `scaleRBy` 和 `scaleDBy` 同时设置为 `'wheel'`，只会为 `scaleRBy` 绑定滚轮事件。\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### 自定义样式\n\n可以自定义鱼眼放大镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n","frontmatter":{"title":"鱼眼放大镜 Fisheye","order":"6"},"isInternal":false,"tokens":3492,"sizeBytes":16360},{"name":"Fullscreen.en.md","path":"packages/site/docs/manual/plugin/Fullscreen.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Fullscreen.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Fullscreen\norder: 7\n---\n\n## Overview\n\nThe Fullscreen plugin allows users to expand the graph visualization content to the entire screen, providing a broader view and a better immersive experience.\n\n## Use Cases\n\nThe Fullscreen plugin is mainly suitable for the following scenarios:\n\n- Provide a broader view for viewing complex graph data\n- Enhance immersive experience, focusing on graph visualization content\n- Display graph data in presentations or reports\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fullscreen plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n      onEnter: () => {\n        console.log('Entered fullscreen mode');\n      },\n      onExit: () => {\n        console.log('Exited fullscreen mode');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property | Description                                                                                                      | Type                                 | Default Value | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ------------- | -------- |\n| type     | Plugin type                                                                                                      | string                               | `fullscreen`  | ✓        |\n| key      | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                | string                               | -             |          |\n| autoFit  | Whether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen | boolean                              | true          |          |\n| trigger  | Method to trigger fullscreen, [example](#trigger)                                                                | { request?: string; exit?: string; } | -             |          |\n| onEnter  | Callback after entering fullscreen                                                                               | () => void                           | -             |          |\n| onExit   | Callback after exiting fullscreen                                                                                | () => void                           | -             |          |\n\n### trigger\n\nThe trigger property is used to control the method of triggering fullscreen. It supports two configuration methods:\n\n#### Shortcut Key Configuration\n\nUse keyboard shortcuts to trigger fullscreen and exit fullscreen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n    },\n  ],\n});\n```\n\n#### Custom Trigger\n\nControl fullscreen by calling the request and exit methods.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\nWhether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen.\n\n- When set to true, the canvas will automatically resize to fit the entire screen.\n- When set to false, the canvas size remains unchanged.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\nThis method is used to enter fullscreen mode programmatically. It can be called on the plugin instance to expand the graph visualization to the entire screen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\nThis method is used to exit fullscreen mode programmatically. It can be called on the plugin instance to revert the graph visualization back to its original size.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Fullscreen","order":"7"},"isInternal":false,"tokens":1392,"sizeBytes":5570},{"name":"Fullscreen.zh.md","path":"packages/site/docs/manual/plugin/Fullscreen.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Fullscreen.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 全屏展示 Fullscreen\norder: 7\n---\n\n## 概述\n\n全屏展示插件允许用户将图可视化内容扩展到整个屏幕，提供更广阔的视图和更好的沉浸式体验。\n\n## 使用场景\n\n全屏展示插件主要适用于以下场景：\n\n- 提供更广阔的视图，便于查看复杂图数据\n- 增强沉浸式体验，专注于图可视化内容\n- 在演示或报告中展示图数据\n\n## 基本用法\n\n以下是一个简单的 Fullscreen 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n      onEnter: () => {\n        console.log('进入全屏模式');\n      },\n      onExit: () => {\n        console.log('退出全屏模式');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性    | 描述                                                 | 类型                                 | 默认值       | 必选 |\n| ------- | ---------------------------------------------------- | ------------------------------------ | ------------ | ---- |\n| type    | 插件类型                                             | string                               | `fullscreen` | ✓    |\n| key     | 插件的唯一标识，可用于获取插件实例或更新插件选项     | string                               | -            |      |\n| autoFit | 是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸 | boolean                              | true         |      |\n| trigger | 触发全屏的方式，[示例](#trigger)                     | { request?: string; exit?: string; } | -            |      |\n| onEnter | 进入全屏后的回调                                     | () => void                           | -            |      |\n| onExit  | 退出全屏后的回调                                     | () => void                           | -            |      |\n\n### trigger\n\ntrigger 属性用于控制触发全屏的方式。它支持两种配置方式：\n\n#### 快捷键配置\n\n使用键盘快捷键来触发全屏和退出全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n    },\n  ],\n});\n```\n\n#### 自定义触发\n\n通过调用 request 和 exit 方法来控制全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\n是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸。\n\n- 设置为 true 时，画布会自动调整大小以适应整个屏幕。\n- 设置为 false 时，画布大小保持不变。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\n这个方法可以让你通过代码进入全屏模式。调用插件实例上的这个方法，就能把图形内容扩展到整个屏幕。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\n这个方法可以让你通过代码退出全屏模式。调用插件实例上的这个方法，就能把图形内容恢复到原来的大小。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"全屏展示 Fullscreen","order":"7"},"isInternal":false,"tokens":953,"sizeBytes":4856},{"name":"GridLine.en.md","path":"packages/site/docs/manual/plugin/GridLine.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/GridLine.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: GridLine\norder: 8\n---\n\n## Overview\n\nThe GridLine plugin provides visual auxiliary lines for the canvas, helping users precisely position and align graphic elements. It is an indispensable tool in graphic drawing.\n\n## Use Cases\n\nThe GridLine plugin is mainly suitable for the following scenarios:\n\n- Assisting users in precise drawing and element alignment\n- Providing visual references to enhance spatial awareness\n- Building a structured reference system when designing and editing graphics\n\n## Basic Usage\n\nBelow is a simple example of initializing the GridLine plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // Specify a unique identifier for dynamic updates\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## Configuration Options\n\n| Property        | Description                                                                                         | Type                                              | Default     | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------- | -------- |\n| type            | Plugin type                                                                                         | string                                            | `grid-line` | ✓        |\n| key             | Unique identifier for the plugin, used to get the plugin instance or update plugin options          | string                                            | -           |          |\n| border          | Whether to display the border                                                                       | boolean                                           | true        |          |\n| borderLineWidth | Border line width                                                                                   | number                                            | 1           |          |\n| borderStroke    | Border color, see [CSS border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color) | string                                            | `#eee`      |          |\n| borderStyle     | Border style, see [CSS border-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style) | string                                            | `solid`     |          |\n| follow          | Whether to follow canvas movements                                                                  | boolean \\| {translate ?: boolean, zoom?: boolean} | false       |          |\n| lineWidth       | Grid line width                                                                                     | number \\| string                                  | 1           |          |\n| size            | Grid unit size in pixels                                                                            | number                                            | 20          |          |\n| stroke          | Grid line color                                                                                     | string                                            | `#eee`      |          |\n\n### follow\n\nThe `follow` property controls whether the grid lines follow the canvas transformations. It supports two configuration methods:\n\n1. **Boolean Configuration**: When set to `true`, the grid lines follow both canvas translation and zoom; when set to `false`, they remain static.\n\n```js\n// Enable both translation and zoom following\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **Object Configuration**: Allows more precise control over the grid line following behavior.\n\n```js\n// Follow translation only, not zoom\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // Follow translation\n        zoom: false, // Do not follow zoom\n      },\n    },\n  ],\n});\n\n// Follow zoom only, not translation\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // Do not follow translation\n        zoom: true, // Follow zoom\n      },\n    },\n  ],\n});\n```\n\nWhen grid lines follow zoom, they maintain a relative position to the canvas content, making alignment references more precise. Following translation allows the grid to move with the canvas content, enhancing the visual experience of spatial continuity.\n\n## Code Examples\n\n### Basic Grid Line\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid-line'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### Custom Style\n\nYou can customize the grid line style as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid unit\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Follow Movement\n\nEnabling the follow option allows the grid to move with the canvas, enhancing user experience:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n```\n\nTry dragging/zooming the canvas to observe the grid following effect:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamic Grid Update\n\nUse the key identifier to dynamically update grid properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// Subsequent dynamic updates\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // Update grid size\n  stroke: '#ff4d4f', // Update grid color\n});\n```\n\n## Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","frontmatter":{"title":"GridLine","order":"8"},"isInternal":false,"tokens":2090,"sizeBytes":8362},{"name":"GridLine.zh.md","path":"packages/site/docs/manual/plugin/GridLine.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/GridLine.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 网格线 GridLine\norder: 8\n---\n\n## 概述\n\n网格线插件为画布提供可视化辅助线，帮助用户精确定位和对齐图形元素，是图形绘制中不可或缺的辅助工具。\n\n## 使用场景\n\n网格线插件主要适用于以下场景：\n\n- 辅助用户精确绘图和元素对齐\n- 提供视觉参考，增强空间感知\n- 在设计和编辑图形时构建结构化的参考系统\n\n## 基本用法\n\n以下是一个简单的 GridLine 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // 指定唯一标识符，便于后续动态更新\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## 配置项\n\n| 属性            | 描述                                                                                                     | 类型                                               | 默认值      | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------- | ---- |\n| type            | 插件类型                                                                                                 | string                                             | `grid-line` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                         | string                                             | -           |      |\n| border          | 是否显示边框                                                                                             | boolean                                            | true        |      |\n| borderLineWidth | 边框线宽                                                                                                 | number                                             | 1           |      |\n| borderStroke    | 边框颜色，详细属性参考 [CSS border-color](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-color) | string                                             | `#eee`      |      |\n| borderStyle     | 边框样式，详细属性参考 [CSS border-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-style) | string                                             | `solid`     |      |\n| follow          | 是否跟随画布移动                                                                                         | boolean \\｜ {translate ?: boolean, zoom?: boolean} | false       |      |\n| lineWidth       | 网格线宽度                                                                                               | number \\| string                                   | 1           |      |\n| size            | 网格单元大小，单位为像素                                                                                 | number                                             | 20          |      |\n| stroke          | 网格线颜色                                                                                               | string                                             | `#eee`      |      |\n\n### follow\n\n`follow` 属性用于控制网格线是否跟随画布的变换操作。它支持两种配置方式：\n\n1. **布尔值配置**：当设置为 `true` 时，网格线会同时跟随画布的平移和缩放；设置为 `false` 时则保持静态。\n\n```js\n// 同时启用跟随平移和缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **对象配置**：可以更精细地控制网格线的跟随行为。\n\n```js\n// 仅跟随平移，不跟随缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // 跟随平移\n        zoom: false, // 不跟随缩放\n      },\n    },\n  ],\n});\n\n// 仅跟随缩放，不跟随平移\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // 不跟随平移\n        zoom: true, // 跟随缩放\n      },\n    },\n  ],\n});\n```\n\n当网格线跟随缩放时，它会保持与画布内容的相对位置关系，使得对齐参考更加精准。跟随平移则让网格随着画布内容一起移动，增强空间连续性的视觉体验。\n\n## 代码示例\n\n### 基础网格线\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid-line'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义网格线的样式：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格单元\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 跟随移动\n\n启用 follow 选项可以让网格跟随画布移动，增强用户体验：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n```\n\n试着拖拽/缩放画布，观察网格的跟随效果：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新网格\n\n使用 key 标识符可以在运行时动态更新网格属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // 更新网格大小\n  stroke: '#ff4d4f', // 更新网格颜色\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n","frontmatter":{"title":"网格线 GridLine","order":"8"},"isInternal":false,"tokens":1685,"sizeBytes":8142},{"name":"History.en.md","path":"packages/site/docs/manual/plugin/History.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/History.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: History\norder: 9\n---\n\n## Overview\n\nThis plugin is used to implement the **Undo** and **Redo** functions in graph editing. By recording the historical state stack of user operations, it supports backtracking or restoring operations during graph interactions. The plugin provides users with comprehensive configuration options and APIs.\n\n## Usage Scenarios\n\nThe history plugin is suitable for all scenarios involving graph editing.\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## Basic Usage\n\nAdd this plugin in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['history'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property         | Description                                                                                                                                                                                                   | Type                                                           | Default Value | Required |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| afterAddCommand  | Called after a command is added to the `Undo/Redo` queue. `revert` is `true` for undo operations and `false` for redo operations                                                                              | (cmd: [Command](#command), revert: boolean) => void            | -             |          |\n| beforeAddCommand | Called before a command is added to the `Undo/Redo` queue. If this method returns `false`, the command will not be added to the queue. `revert` is `true` for undo operations and `false` for redo operations | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -             |          |\n| executeCommand   | Callback function when executing a command                                                                                                                                                                    | (cmd: [Command](#command)) => void                             | -             |          |\n| stackSize        | Maximum length of history records to be recorded                                                                                                                                                              | number                                                         | 0 (unlimited) |          |\n\n### Parameter Type Description\n\n#### `Command`\n\n```typescript\n// Single history command\ninterface Command {\n  current: CommandData; // Current data\n  original: CommandData; // Original data\n  animation: boolean; // Whether to enable animation\n}\n// Single history command data\ninterface CommandData {\n  add: GraphData; // Added data\n  update: GraphData; // Updated data\n  remove: GraphData; // Removed data\n}\n// Graph data\ninterface GraphData {\n  nodes?: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data\n  combos?: ComboData[]; // Combo data\n}\n```\n\n## API\n\nThe history plugin provides the following APIs for users to use as needed. For how to call plugin methods, please refer to the [Plugin Overview Document](/en/manual/plugin/overview#calling-plugin-methods)\n\n### History.canRedo()\n\nDetermines whether a **redo** operation can be performed. If there are records in the redo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanRedo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('Redo operation can be performed');\n} else {\n  console.log('Redo stack is empty, cannot redo');\n}\n```\n\n### History.canUndo()\n\nDetermines whether an **undo** operation can be performed. If there are records in the undo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanUndo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('Undo operation can be performed');\n} else {\n  console.log('Undo stack is empty, cannot undo');\n}\n```\n\n### History.clear()\n\nClears the history records, including the undo and redo stacks.\n\n```typescript\nclear(): void;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('History records cleared');\n```\n\n### History.on()\n\nListens to history events, allowing users to execute custom logic when specific events occur.\n\n```typescript\non(event: Loosen<HistoryEvent>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\nParameter Type Description:\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // When a command is undone\n    REDO = 'redo', // When a command is redone\n    CANCEL = 'cancel', // When a command is canceled\n    ADD = 'add', // When a command is added to the queue\n    CLEAR = 'clear', // When the history queue is cleared\n    CHANGE = 'change', // When the history queue changes\n  }\n  ```\n\n- Command\n\n  Please refer to the previous [Command](#parameter-type-description) type description\n\nExample:\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('Undo operation executed');\n});\n```\n\n### History.redo()\n\nPerforms a **redo** operation and returns the plugin instance. If the redo stack is empty, no operation is performed.\n\n```typescript\nredo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('Redo operation executed');\n```\n\n### History.undo()\n\nPerforms an **undo** operation and returns the plugin instance. If the undo stack is empty, no operation is performed.\n\n```typescript\nundo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('Undo operation executed');\n```\n\n### History.undoAndCancel()\n\nPerforms an undo operation without recording it in the history and returns the plugin instance. Note that this operation will clear the **redo** stack.\n\n```typescript\nundoAndCancel(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('Undo and cancel operation executed');\n```\n\n## History Modes\n\nThis plugin supports two history modes:\n\n### Default Mode\n\nIn default mode, every time a **render** is triggered (for example, after updating element data, the user actively executes the `graph.draw()` method to trigger rendering), the plugin records the data **before** and **after** rendering and stacks it as an operation record.\n\n### Custom Mode\n\n#### Scenario Description\n\nIn actual needs, a user's graph editing operation may involve **multiple renders**. For example, in one editing operation, first display nodes A and B, then display the connection from A to B. This involves two renders (i.e., the user needs to perform `graph.draw()` twice). In this scenario, the default mode will stack two history records, which are:\n\n- Display nodes A and B\n- Display the connection from A to B\n\nObviously, in actual business, one operation should only require one undo.\n\nBut here, when undoing this operation, the user needs to call the `undo` method twice, which means two undos are required.\n\n#### Scenario Support\n\nTo support such scenarios, G6 provides a batch controller (`BatchController`, [refer to the source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)), which is provided in the graph instance context.\n\nThe history plugin implements custom operation records based on this batch controller. The code example is as follows:\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // Start batch operation\ngraph.addNodeData(...); // Display nodes A and B\ngraph.draw(); // First render trigger\ngraph.addEdgeData(...); // Display the connection from A to B\ngraph.draw(); // Second render trigger\ngraph.context.batch.endBatch(); // End batch operation\n```\n\nIn the example:\n\n- By calling the `startBatch` method of the batch controller instance, the history plugin is informed that batch operations are now being performed. Before the batch operation ends, no matter how many renders are triggered, no history records should be stacked (the history plugin will record the change data for each render trigger).\n- After completing the last data change, call the `endBatch()` method. The history plugin listens for the completion of the batch operation and stacks this batch operation as a history record.\n\nFinally, the user only needs to perform one `undo` to undo.\n\n## Code Examples\n\nBelow are some common cases with corresponding code references.\n\n### Undo and Redo Button States\n\nIn actual business scenarios, you may need to customize the toolbar of the canvas, which involves the enable and disable states of the undo and redo buttons.\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\nIn the example, by listening to the `HistoryEvent.CHANGE` event, which is triggered when the history queue changes, it is determined in real-time whether undo and redo operations can be performed.\n\n### Determine Whether a Command is Allowed to Enter the Queue\n\nHere is a simple scenario: only the operation of removing elements is allowed to enter the history queue.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\nIn the example, the configuration option [beforeAddCommand](#beforeAddCommand) is used to determine whether there are elements removed in `cmd.current.remove`.\n","frontmatter":{"title":"History","order":"9"},"isInternal":false,"tokens":2683,"sizeBytes":10729},{"name":"History.zh.md","path":"packages/site/docs/manual/plugin/History.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/History.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 历史记录 History\norder: 9\n---\n\n## 概述\n\n该插件用于实现图编辑的 **撤销（Undo）** 和 **重做（Redo）** 功能，通过记录用户操作的历史状态堆栈，支持在图交互过程中进行回溯或恢复操作。该插件为用户提供了完善的配置项和 API 。\n\n## 使用场景\n\n历史记录插件适用于所有涉及到图编辑的场景。\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一插件：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['history'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性             | 描述                                                                                                                                                                | 类型                                                           | 默认值      | 必选 |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------- | ---- |\n| afterAddCommand  | 当一个命令被添加到 `Undo/Redo` 队列后被调用。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作                                                           | (cmd: [Command](#command), revert: boolean) => void            | -           |      |\n| beforeAddCommand | 当一个命令被添加到 `Undo/Redo` 队列前被调用，如果该方法返回 `false`，那么这个命令将不会被添加到队列中。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作 | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -           |      |\n| executeCommand   | 执行命令时的回调函数                                                                                                                                                | (cmd: [Command](#command)) => void                             | -           |      |\n| stackSize        | 最多记录该数据长度的历史记录                                                                                                                                        | number                                                         | 0（不限制） |      |\n\n### 参数类型说明\n\n#### `Command`\n\n```typescript\n// 单条历史记录命令\ninterface Command {\n  current: CommandData; // 当前数据\n  original: CommandData; // 原始数据\n  animation: boolean; // 是否开启动画\n}\n// 单条历史记录命令数据\ninterface CommandData {\n  add: GraphData; // 新增的数据\n  update: GraphData; // 更新的数据\n  remove: GraphData; // 移除的数据\n}\n// 图数据\ninterface GraphData {\n  nodes?: NodeData[]; // 节点数据\n  edges?: EdgeData[]; // 边数据\n  combos?: ComboData[]; // Combo 数据\n}\n```\n\n## API\n\nhistory 插件提供了以下 API 供用户按需使用，调用插件方法的方式请参考 [插件总览文档](/manual/plugin/overview#调用插件方法)\n\n### History.canRedo()\n\n判断是否可以进行**重做**操作。如果重做堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanRedo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('可以进行重做操作');\n} else {\n  console.log('重做堆栈为空，无法重做');\n}\n```\n\n### History.canUndo()\n\n判断是否可以进行**撤销**操作。如果撤销堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanUndo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('可以进行撤销操作');\n} else {\n  console.log('撤销堆栈为空，无法撤销');\n}\n```\n\n### History.clear()\n\n清空历史记录，包括撤销和重做堆栈。\n\n```typescript\nclear(): void;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('历史记录已清空');\n```\n\n### History.on()\n\n监听历史记录事件，允许用户在特定事件发生时执行自定义逻辑。\n\n```typescript\non(event: Loosen/<HistoryEvent/>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\n参数类型说明：\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // 当命令被撤销时\n    REDO = 'redo', // 当命令被重做时\n    CANCEL = 'cancel', // 当命令被取消时\n    ADD = 'add', // 当命令被添加到队列时\n    CLEAR = 'clear', // 当历史队列被清空时\n    CHANGE = 'change', // 当历史队列发生变化时\n  }\n  ```\n\n- Command\n\n  请参考前面的 [Command](#参数类型说明) 类型说明\n\n示例：\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('执行了撤销操作');\n});\n```\n\n### History.redo()\n\n执行**重做**操作，并返回插件实例。如果重做堆栈为空，则不执行任何操作。\n\n```typescript\nredo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('执行了重做操作');\n```\n\n### History.undo()\n\n执行**撤销**操作，并返回插件实例。如果撤销堆栈为空，则不执行任何操作。\n\n```typescript\nundo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('执行了撤销操作');\n```\n\n### History.undoAndCancel()\n\n执行撤销操作且不计入历史记录，并返回插件实例。注意，执行该操作会清空**重做**栈。\n\n```typescript\nundoAndCancel(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('执行了撤销并取消操作');\n```\n\n## 历史记录模式\n\n该插件支持两种历史记录模式：\n\n### 默认模式\n\n默认模式下，每一次触发**渲染后**（比如更新元素数据后，用户主动执行 `graph.draw()` 方法触发渲染），插件会把**渲染前**和**渲染后**的数据记录下来并作为一次操作记录入栈。\n\n### 自定义模式\n\n#### 场景描述\n\n实际需求中，用户的一次图编辑操作可能涉及到**多次渲染**，比如，一次编辑操作中，首先把节点 A、B 展示出来，然后展示 A->B 的连线，这里就涉及到两次渲染（即用户需要进行两次 `graph.draw()` ），这种场景下，默认模式会入栈两次历史记录，分别是：\n\n- 展示节点 A 和 B\n- 展示 A->B 的连线\n\n显然，实际业务中，一次操作，也应该只需一次撤销。\n\n但这里在撤销本次操作时，用户需要调用两次 `undo` 方法，也就是需要进行两次撤销。\n\n#### 场景支持\n\n为了支持这样的场景，G6 提供了一个批量控制器（ `BatchController`，[可参考源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)），在图实例上下文中提供了这个批量控制器实例。\n\n历史记录插件则基于这个批量控制器，来实现自定义操作记录，代码示例如下：\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // 开始批量操作\ngraph.addNodeData(...); // 把节点 A、B 展示出来\ngraph.draw(); // 第一次触发渲染\ngraph.addEdgeData(...); // 把 A->B 连线展示出来\ngraph.draw(); // 第二次触发渲染\ngraph.context.batch.endBatch(); // 结束批量操作\n```\n\n示例中：\n\n- 通过调用批量控制器实例的 `startBatch` 方法，告诉历史记录插件，现在开始进行批量操作，在批量操作没有结束前，不管触发多少次渲染，都不能进行历史记录入栈（历史记录插件会把每次触发渲染的变更数据记录下来）\n- 在完成最后一次数据变更后，调用 `endBatch()` 方法，历史记录插件监听到批量操作完成，则把本次批量操作作为一次历史记录入栈\n\n最终，用户只需要进行一次 `undo` 即可撤销。\n\n## 代码示例\n\n下面列举一些常见的案例，并给出相应的代码参考\n\n### 撤销、重做按钮状态\n\n实际业务场景中，可能需要自定义画布的工具栏，也就涉及到撤销和重做按钮的启禁用状态\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\n示例中通过监听 `HistoryEvent.CHANGE` 事件，这个事件在历史队列发生变化时会触发，每次发生变化后，实时判断当前是否可以进行撤销和重做操作\n\n### 判断是否允许命令进入队列\n\n这里实现一个简单的场景：只有移除元素的操作才允许进入历史记录队列\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\n示例中通过配置项 [beforeAddCommand](#beforeAddCommand) 来实现，判断 `cmd.current.remove` 里面是否存在被移除的元素\n","frontmatter":{"title":"历史记录 History","order":"9"},"isInternal":false,"tokens":1668,"sizeBytes":9921},{"name":"Hull.en.md","path":"packages/site/docs/manual/plugin/Hull.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Hull.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Hull\norder: 10\n---\n\n## Overview\n\nHull is used to process and represent the convex or concave polygon bounding box of a set of points. It can wrap a set of nodes in a minimal geometric shape, helping users better understand and analyze datasets.\n\n- **Convex Hull**: This is a convex polygon that contains all the points and has no indentations.\n- **Concave Hull**: This is a concave polygon that also contains all the points but may have indentations. The degree of indentation is controlled by the concavity parameter.\n\n## Usage Scenarios\n\nThe hull plugin is mainly applicable to the following scenarios:\n\n- Wrapping node collections in data visualization\n- Providing visual references to enhance spatial awareness\n- Identifying the collection relationship of specific nodes in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the Hull plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // Specify a unique identifier for subsequent dynamic updates\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n      concavity: Infinity, // Default to convex hull\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## Configuration Options\n\n| Property         | Description                                                                                              | Type                                               | Default Value | Required |\n| ---------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type             | Plugin type                                                                                              | string                                             | `hull`        | ✓        |\n| key              | Unique identifier for the plugin, used for subsequent updates                                            | string                                             | -             |          |\n| members          | Elements within the Hull, including nodes and edges                                                      | string[]                                           | -             | ✓        |\n| concavity        | Concavity, the larger the value, the smaller the concavity; default is Infinity representing Convex Hull | number                                             | Infinity      |          |\n| corner           | Corner type, options are `rounded` \\| `smooth` \\| `sharp`                                                | string                                             | `rounded`     |          |\n| padding          | Padding                                                                                                  | number                                             | `10`          |          |\n| label            | Whether to display the label                                                                             | boolean                                            | true          |          |\n| labelPlacement   | Label position                                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`      |          |\n| labelBackground  | Whether to display the background                                                                        | boolean                                            | false         |          |\n| labelPadding     | Label padding                                                                                            | number \\| number[]                                 | 0             |          |\n| labelCloseToPath | Whether the label is close to the hull                                                                   | boolean                                            | true          |          |\n| labelAutoRotate  | Whether the label rotates with the hull, effective only when closeToPath is true                         | boolean                                            | true          |          |\n| labelOffsetX     | X-axis offset                                                                                            | number                                             | 0             |          |\n| labelOffsetY     | Y-axis offset                                                                                            | number                                             | 0             |          |\n| labelMaxWidth    | Maximum width of the text, exceeding will automatically ellipsis                                         | number                                             | 0             |          |\n\nFor complete label styles, see [this link](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nThe concavity attribute is used to control the concavity of the Hull. When set to Infinity, a convex hull is generated; otherwise, a concave hull is generated.\n\n```js\n// Convex hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // Convex hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// Concave hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // Concave hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hull\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style of the Hull as needed, such as adjusting color, transparency, and other properties.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visual effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n","frontmatter":{"title":"Hull","order":"10"},"isInternal":false,"tokens":3438,"sizeBytes":13754},{"name":"Hull.zh.md","path":"packages/site/docs/manual/plugin/Hull.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Hull.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 轮廓包围 Hull\norder: 10\n---\n\n## 概述\n\n轮廓包围（Hull）用于处理和表示一组点的凸多边形或凹多边形包围盒。它可以将一组节点包裹在一个最小的几何形状中，帮助用户更好地理解和分析数据集。\n\n- **凸包（Convex Hull）**：这是一个凸多边形，它包含所有的点，并且没有任何凹陷。\n- **凹包（Concave Hull）**：这是一个凹多边形，它同样包含所有的点，但是可能会有凹陷。凹包的凹陷程度由 concavity 参数控制。\n\n## 使用场景\n\n轮廓包围插件主要适用于以下场景：\n\n- 数据可视化中的节点集合包裹\n- 提供视觉参考，增强空间感知\n- 在复杂网络图中标识特定节点的集合关系\n\n## 基本用法\n\n以下是一个简单的 Hull 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // 指定唯一标识符，便于后续动态更新\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n      concavity: Infinity, // 默认为凸包\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## 配置项\n\n| 属性             | 描述                                                       | 类型                                               | 默认值    | 必选 |\n| ---------------- | ---------------------------------------------------------- | -------------------------------------------------- | --------- | ---- |\n| type             | 插件类型                                                   | string                                             | `hull`    | ✓    |\n| key              | 插件唯一标识符，用于后续更新                               | string                                             | -         |      |\n| members          | Hull 内的元素，包括节点和边                                | string[]                                           | -         | ✓    |\n| concavity        | 凹度，数值越大凹度越小；默认为 Infinity 代表为 Convex Hull | number                                             | Infinity  |      |\n| corner           | 拐角类型，可选值为 `rounded` \\| `smooth` \\| `sharp`        | string                                             | `rounded` |      |\n| padding          | 内边距                                                     | number                                             | `10`      |      |\n| label            | 是否显示标签                                               | boolean                                            | true      |      |\n| labelPlacement   | 标签位置                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`  |      |\n| labelBackground  | 是否显示背景                                               | boolean                                            | false     |      |\n| labelPadding     | 标签内边距                                                 | number \\| number[]                                 | 0         |      |\n| labelCloseToPath | 标签是否贴合轮廓                                           | boolean                                            | true      |      |\n| labelAutoRotate  | 标签是否跟随轮廓旋转，仅在 closeToPath 为 true 时生效      | boolean                                            | true      |      |\n| labelOffsetX     | x 轴偏移量                                                 | number                                             | 0         |      |\n| labelOffsetY     | y 轴偏移量                                                 | number                                             | 0         |      |\n| labelMaxWidth    | 文本的最大宽度，超出会自动省略                             | number                                             | 0         |      |\n\n完整的标签样式见[此链接](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nconcavity 属性用于控制 Hull 的凹度。当设置为 Infinity 时，生成的是凸包；否则会生成凹包。\n\n```js\n// 凸包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // 凸包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// 凹包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // 凹包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础 Hull\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义 Hull 的样式，例如调整颜色、透明度等属性。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n```\n\n```\n","frontmatter":{"title":"轮廓包围 Hull","order":"10"},"isInternal":false,"tokens":2842,"sizeBytes":12700},{"name":"Legend.en.md","path":"packages/site/docs/manual/plugin/Legend.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Legend.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Legend\norder: 11\n---\n\n## Overview\n\nThe Legend plugin is used to display classification information of elements in the graph, supporting the display of classification information for nodes, edges, and combos. Through the legend, users can quickly perceive the classification information of related elements in the graph and quickly locate elements by clicking on the corresponding legend items, improving user browsing efficiency.\n\n## Usage Scenarios\n\nThis plugin is mainly used for:\n\n- Quickly classifying elements through the legend\n- Quickly highlighting and locating corresponding elements through the legend\n\n## Basic Usage\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property          | Description                                                                                                                                                                                    | Type                                                                                        | Default Value | Required |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type              | Plugin type                                                                                                                                                                                    | string                                                                                      | `legend`      | ✓        |\n| key               | Unique identifier for the plugin, used for subsequent updates                                                                                                                                  | string                                                                                      | -             |          |\n| trigger           | How the legend item triggers the corresponding item highlight: <br/>- `hover`: Triggered when the mouse enters the legend item <br/>- `click`: Triggered when the mouse clicks the legend item | `hover` \\| `click`                                                                          | `hover`       |          |\n| position          | Relative position of the legend on the canvas, [optional values](#cardinalplacement)                                                                                                           | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`      |          |\n| container         | Container to which the legend is mounted, if not provided, it is mounted to the container where the Graph is located                                                                           | HTMLElement \\| string                                                                       | -             |          |\n| className         | Legend canvas class name, not effective when an external container is passed                                                                                                                   | string                                                                                      | -             |          |\n| containerStyle    | Style of the legend container, not effective when an external container is passed                                                                                                              | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| nodeField         | Node classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| edgeField         | Edge classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| comboField        | Combo classification identifier                                                                                                                                                                | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| orientation       | Layout direction of legend items: <br/>- `horizontal`: Horizontal direction <br/>- `vertical`: Vertical direction                                                                              | `horizontal` \\| `vertical`                                                                  | 'horizontal'  |          |\n| layout            | Layout method: <br/>- `flex`: Flexible layout <br/>- `grid`: Grid layout                                                                                                                       | `flex` \\| `grid`                                                                            | `flex`        |          |\n| showTitle         | Whether to display the title                                                                                                                                                                   | boolean                                                                                     | false         |\n| titleText         | Title content                                                                                                                                                                                  | string                                                                                      | \"\"            |\n| x                 | Relative horizontal position of the legend on the canvas, higher priority than position                                                                                                        | number                                                                                      | -             |          |\n| y                 | Relative vertical position of the legend on the canvas, higher priority than position                                                                                                          | number                                                                                      | -             |          |\n| width             | Width of the legend                                                                                                                                                                            | number                                                                                      | 240           |          |\n| height            | Height of the legend                                                                                                                                                                           | number                                                                                      | 160           |          |\n| itemSpacing       | Spacing between the text of the legend item and the corresponding marker                                                                                                                       | number                                                                                      | 4             |          |\n| rowPadding        | Spacing between each row in the legend                                                                                                                                                         | number                                                                                      | 10            |          |\n| colPadding        | Spacing between each column in the legend                                                                                                                                                      | number                                                                                      | 10            |          |\n| itemMarkerSize    | Size of the legend item marker                                                                                                                                                                 | number                                                                                      | 16            |          |\n| itemLabelFontSize | Font size of the legend item text                                                                                                                                                              | number                                                                                      | 16            |          |\n| gridCol           | Maximum number of columns allowed for legend items when width permits                                                                                                                          | number                                                                                      | -             |          |\n| gridRow           | Maximum number of rows allowed for legend items when height permits                                                                                                                            | number                                                                                      | -             |          |\n\n### CardinalPlacement\n\nThe `position` property supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side near the top\n- `'left-bottom'`: Left side near the bottom\n- `'right-top'`: Right side near the top\n- `'right-bottom'`: Right side near the bottom\n\n## Code Examples\n\n### Basic Legend\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n### Custom Legend Position\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // You can quickly specify the position through position\n      // position: \"top-left\",\n      // Or you can more flexibly control the position of the legend through x, y\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### Custom Legend Item Layout\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // Control to display only one row\n      gridRow: 1,\n      // Control to display 10 columns in one row, a page button will be displayed when the column width is insufficient\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Setting orientation is ineffective?\n\n`orientation` mainly controls the direction of the layout, and the specific display of **multiple columns in one row** or **multiple rows in one column** is mainly controlled by `gridRow` and `gridCol`. For example, if you want it to look like a vertical legend item, you can configure it like this:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // Control to display 1 column in one row\n      gridCol:1,\n      // Control to display up to 20 rows\n      gridRow: 20,\n    },\n  ],\n```\n\nThis way, it becomes a legend with only one column, conforming to the visual vertical arrangement.\n\n### 2. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// Update legend position\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Legend","order":"11"},"isInternal":false,"tokens":3696,"sizeBytes":14785},{"name":"Legend.zh.md","path":"packages/site/docs/manual/plugin/Legend.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Legend.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 图例 Legend\norder: 11\n---\n\n## 概述\n\n图例（Legend）插件用于展示图中元素的分类信息，支持节点、边、组合的分类信息展示。通过图例，用户可以快速感知到图中相关元素的分类信息，也可以通过点击对应图例项来快速定位到元素，提高用户的浏览效率。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 通过图例快速对元素进行分类\n- 通过图例快速高亮定位到对应元素\n\n## 基本用法\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性              | 描述                                                                                                  | 类型                                                                                        | 默认值       | 必选 |\n| ----------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type              | 插件类型                                                                                              | string                                                                                      | `legend`     | ✓    |\n| key               | 插件唯一标识符，用于后续更新                                                                          | string                                                                                      | -            |      |\n| trigger           | 图例项触发对应项高亮的方式：<br/>- `hover`：鼠标移入图例项时触发 <br/>- `click`：鼠标点击图例项时触发 | `hover` \\| `click`                                                                          | `hover`      |      |\n| position          | 图例在画布中的相对位置，[可选值](#cardinalplacement)                                                  | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`     |      |\n| container         | 图例挂载的容器，无则挂载到 Graph 所在容器                                                             | HTMLElement \\| string                                                                       | -            |      |\n| className         | 图例画布类名，传入外置容器时不生效                                                                    | string                                                                                      | -            |      |\n| containerStyle    | 图例的容器样式，传入外置容器时不生效                                                                  | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| nodeField         | 节点分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| edgeField         | 边分类标识                                                                                            | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| comboField        | 组合分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| orientation       | 图例项的布局方向：<br/>- `horizontal`：水平方向 <br/>- `vertical`：垂直方向                           | `horizontal` \\| `vertical`                                                                  | 'horizontal' |      |\n| layout            | 布局方式：<br/>- `flex`：弹性布局 <br/>- `grid`：网格布局                                             | `flex` \\| `grid`                                                                            | `flex`       |      |\n| showTitle         | 是否显示标题                                                                                          | boolean                                                                                     | false        |\n| titleText         | 标题内容                                                                                              | string                                                                                      | \"\"           |\n| x                 | 图例在画布中的相对的横向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| y                 | 图例在画布中的相对的纵向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| width             | 图例的宽度                                                                                            | number                                                                                      | 240          |      |\n| height            | 图例的高度                                                                                            | number                                                                                      | 160          |      |\n| itemSpacing       | 图例项的文本和对应标记之间的间距                                                                      | number                                                                                      | 4            |      |\n| rowPadding        | 图例中每行之间的间距                                                                                  | number                                                                                      | 10           |      |\n| colPadding        | 图例中每列之间的间距                                                                                  | number                                                                                      | 10           |      |\n| itemMarkerSize    | 图例项标记的大小                                                                                      | number                                                                                      | 16           |      |\n| itemLabelFontSize | 图例项文本的字体大小                                                                                  | number                                                                                      | 16           |      |\n| gridCol           | 图例项在宽度允许情况下的最大列数                                                                      | number                                                                                      | -            |      |\n| gridRow           | 图例项在高度允许情况下的最大行数                                                                      | number                                                                                      | -            |      |\n\n### CardinalPlacement\n\n`position` 属性支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n## 代码示例\n\n### 基础图例\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n### 自定义图例位置\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // 可以通过 position 快捷的来指定位置\n      // position: \"top-left\",\n      // 也可以通过x,y来更加灵活的控制图例的位置\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### 自定义图例项布局\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // 控制只显示一行\n      gridRow: 1,\n      // 控制一行显示10列，当列宽不足时会显示翻页按钮\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 设置了 orientation 无效？\n\n`orientation`主要控制布局的方向，具体展示**一行多列**还是**一列多行**，主要通过 `gridRow` 以及`gridCol`来控制，例如想要看起来像是竖向的图例项，则可以通过这样配置:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // 控制一行显示1列\n      gridCol:1,\n      // 控制显示最多20行\n      gridRow: 20,\n    },\n  ],\n```\n\n这样就变成了只有一列的图例，符合视觉上的竖向排列。\n\n### 2. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// 更新图例位置\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"图例 Legend","order":"11"},"isInternal":false,"tokens":2606,"sizeBytes":12072},{"name":"Minimap.en.md","path":"packages/site/docs/manual/plugin/Minimap.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Minimap.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Minimap\norder: 12\n---\n\n## Overview\n\nThe main function of the Minimap is to provide users with an overall layout of the current graph content in the form of a thumbnail, allowing quick positioning of graph operation locations.\n\n**⚠️ Note**, The Minimap plugin is currently incompatible with React Node rendering mechanism. When using Minimap functionality, it is recommended to implement node rendering through [built-in nodes](/en/manual/element/node/overview) or [custom nodes](/en/manual/element/node/custom-node).\n\n## Usage Scenarios\n\nThe Minimap plugin is mainly applicable to the following scenarios:\n\n- Providing a global view for quick area positioning\n- Navigation and interaction assistance, allowing quick positioning to the target location through the minimap\n\n## Basic Usage\n\nBelow is a simple example of initializing the Minimap plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                             | Type                                                                                                                                                                                                   | Default Value  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- |\n| type           | Plugin type                                                                                                             | string                                                                                                                                                                                                 | `minimap`      | ✓        |\n| key            | Unique identifier for the plugin, used for subsequent updates                                                           | string                                                                                                                                                                                                 | -              |          |\n| className      | Class name of the thumbnail canvas, not effective when an external container is passed                                  | string                                                                                                                                                                                                 |                |          |\n| container      | Container to which the thumbnail is mounted, if not provided, it is mounted to the container where the Graph is located | HTMLElement \\| string                                                                                                                                                                                  |                |          |\n| containerStyle | Style of the thumbnail container, not effective when an external container is passed                                    | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| delay          | Delay update time (milliseconds) for performance optimization                                                           | number                                                                                                                                                                                                 | 128            |          |\n| filter         | Filter for filtering out elements that do not need to be displayed                                                      | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |          |\n| maskStyle      | Style of the mask                                                                                                       | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| padding        | Padding                                                                                                                 | number \\| number[]                                                                                                                                                                                     | 10             |          |\n| position       | Position of the thumbnail relative to the canvas                                                                        | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |          |\n| renderer       | Renderer, default is Canvas renderer                                                                                    | IRenderer                                                                                                                                                                                              |                |          |\n| shape          | Method for generating element thumbnails                                                                                | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |          |\n| size           | Width and height                                                                                                        | [number, number]                                                                                                                                                                                       | [240, 160]     |          |\n\n### containerStyle\n\nSet the style of the thumbnail container, not effective when an external container is passed. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value    | Required |\n| ------------ | -------------------------- | ------ | ---------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd` | ✓        |\n| background   | Container background color | string | `#fff`           | ✓        |\n| borderRadius | Container border radius    | string | -                |          |\n| boxShadow    | Container shadow effect    | string | -                |          |\n| padding      | Container padding          | string | -                |          |\n| margin       | Container margin           | string | -                |          |\n| opacity      | Opacity                    | string | -                |          |\n\n### maskStyle\n\nSpecify the style of the mask. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value        | Required |\n| ------------ | -------------------------- | ------ | -------------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd`     | ✓        |\n| background   | Container background color | string | `rgba(0, 0, 0, 0.1)` | ✓        |\n| borderRadius | Container border radius    | string | -                    | -        |\n| boxShadow    | Container shadow effect    | string | -                    | -        |\n| padding      | Container padding          | string | -                    | -        |\n| margin       | Container margin           | string | -                    | -        |\n| opacity      | Opacity                    | string | -                    | -        |\n\n### position\n\nPosition of the thumbnail relative to the canvas, the thumbnail position configuration supports array form and preset value form.\n\n- Array form [number, number] represents relative position, with a value range of 0~1. For example: [0, 0] represents the top left corner of the canvas, [1, 1] represents the bottom right corner of the canvas.\n- Preset value form is used to set the fixed position of the thumbnail on the canvas, optional values are: `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // Modify the position of the minimap here\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\nSet the width and height of the minimap, default value is [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // Set the width and height of the minimap\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Minimap","order":"12"},"isInternal":false,"tokens":3003,"sizeBytes":12023},{"name":"Minimap.zh.md","path":"packages/site/docs/manual/plugin/Minimap.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Minimap.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 小地图 Minimap\norder: 12\n---\n\n## 概述\n\nMinimap（小地图）的主要作用是为用户提供以缩略图形式展示当前图内容的整体布局，可以快速定位图操作位置。\n\n**⚠️ 需要注意**，Minimap 插件当前不兼容 React Node 渲染机制，在需要使用 Minimap 功能的场景中，建议通过 [内置节点](/manual/element/node/overview) 或者[自定义节点](/manual/element/node/custom-node) 实现节点渲染。\n\n## 使用场景\n\nMinimap（小地图）插件主要适用于以下场景：\n\n- 提供全局视野，快速定位区域\n- 导航与交互辅助，通过操作小地图可以快速定位到目标位置\n\n## 基本用法\n\n以下是一个简单的 Minimap 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                        | 类型                                                                                                                                                                                                   | 默认值         | 必选 |\n| -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ---- |\n| type           | 插件类型                                    | string                                                                                                                                                                                                 | `minimap`      | ✓    |\n| key            | 插件唯一标识符，用于后续更新                | string                                                                                                                                                                                                 | -              |      |\n| className      | 缩略图画布类名，传入外置容器时不生效        | string                                                                                                                                                                                                 |                |      |\n| container      | 缩略图挂载的容器，无则挂载到 Graph 所在容器 | HTMLElement \\| string                                                                                                                                                                                  |                |      |\n| containerStyle | 缩略图的容器样式，传入外置容器时不生效      | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| delay          | 延迟更新时间(毫秒)，用于性能优化            | number                                                                                                                                                                                                 | 128            |      |\n| filter         | 过滤器，用于过滤不必显示的元素              | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |      |\n| maskStyle      | 遮罩的样式                                  | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| padding        | 内边距                                      | number \\| number[]                                                                                                                                                                                     | 10             |      |\n| position       | 缩略图相对于画布的位置                      | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |      |\n| renderer       | 渲染器，默认使用 Canvas 渲染器              | IRenderer                                                                                                                                                                                              |                |      |\n| shape          | 元素缩略图形的生成方法                      | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |      |\n| size           | 宽度和高度                                  | [number, number]                                                                                                                                                                                       | [240, 160]     |      |\n\n### containerStyle\n\n设置缩略图的容器样式，传入外置容器时不生效。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值           | 必选 |\n| ------------ | ------------ | ------ | ---------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd` | ✓    |\n| background   | 容器背景颜色 | string | `#fff`           | ✓    |\n| borderRadius | 容器圆角大小 | string | -                |      |\n| boxShadow    | 容器阴影效果 | string | -                |      |\n| padding      | 容器内边距   | string | -                |      |\n| margin       | 容器外边距   | string | -                |      |\n| opacity      | 透明度       | string | -                |      |\n\n### maskStyle\n\n指定遮罩的样式。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值               | 必选 |\n| ------------ | ------------ | ------ | -------------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd`     | ✓    |\n| background   | 容器背景颜色 | string | `rgba(0, 0, 0, 0.1)` | ✓    |\n| borderRadius | 容器圆角大小 | string | -                    | -    |\n| boxShadow    | 容器阴影效果 | string | -                    | -    |\n| padding      | 容器内边距   | string | -                    | -    |\n| margin       | 容器外边距   | string | -                    | -    |\n| opacity      | 透明度       | string | -                    | -    |\n\n### position\n\n缩略图相对于画布的位置，缩略图位置配置支持数组形式和预设值形式。\n\n- 数组形式 [number, number] 表示相对位置，取值范围为 0~1。举例：[0, 0] 代表画布左上角，[1, 1] 代表画布右下角。\n- 预设值形式用于设定缩略图所在画布固定方位，可选值有：`left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // 这里进行修改minimap所在位置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\n设置小地图的宽度和高度，默认值为 [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // minimap的宽度和高度的设置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"小地图 Minimap","order":"12"},"isInternal":false,"tokens":2231,"sizeBytes":10376},{"name":"overview.en.md","path":"packages/site/docs/manual/plugin/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/overview.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Plugin Overview\norder: 0\n---\n\n## What is a Plugin\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nA Plugin is the most flexible extension mechanism in G6, allowing users to extend G6's functionality, such as adding graphical components to the canvas or implementing undo/redo features.\n\nMost customization needs can be achieved through plugins. G6 comes with some built-in plugins, such as: [Tooltip](/en/manual/plugin/tooltip), [Grid](/en/manual/plugin/grid-line), [History](/en/manual/plugin/history).\n\n## Built-in Plugins\n\nG6 provides a rich set of built-in plugins covering various common functional scenarios:\n\n| Category                     | Plugin Name                                                                                         | Registration Type  | Description                                                            |\n| ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |\n| **Visual Style Enhancement** |                                                                                                     |                    |                                                                        |\n|                              | [Grid Line](/en/manual/plugin/grid-line)                                                            | `grid-line`        | Displays grid reference lines on the canvas                            |\n|                              | [Background](/en/manual/plugin/background)                                                          | `background`       | Adds background images or colors to the canvas                         |\n|                              | [Watermark](/en/manual/plugin/watermark)                                                            | `watermark`        | Adds a watermark to the canvas to protect copyright                    |\n|                              | [Hull](/en/manual/plugin/hull)                                                                      | `hull`             | Creates an outline for a specified set of nodes                        |\n|                              | [Bubble Sets](/en/manual/plugin/bubble-sets)                                                        | `bubble-sets`      | Creates smooth bubble-like element outlines                            |\n|                              | [Snapline](/en/manual/plugin/snapline)                                                              | `snapline`         | Displays alignment reference lines when dragging elements              |\n| **Navigation and Overview**  |                                                                                                     |                    |                                                                        |\n|                              | [Minimap](/en/manual/plugin/minimap)                                                                | `minimap`          | Displays a thumbnail preview of the graph, supporting navigation       |\n|                              | [Fullscreen](/en/manual/plugin/fullscreen)                                                          | `fullscreen`       | Supports full-screen display and exit for charts                       |\n|                              | [Timebar](/en/manual/plugin/timebar)                                                                | `timebar`          | Provides filtering and playback control for temporal data              |\n| **Interactive Controls**     |                                                                                                     |                    |                                                                        |\n|                              | [Toolbar](/en/manual/plugin/toolbar)                                                                | `toolbar`          | Provides a collection of common operation buttons                      |\n|                              | [Context Menu](/en/manual/plugin/contextmenu)                                                       | `contextmenu`      | Displays a menu of selectable operations on right-click                |\n|                              | [Tooltip](/en/manual/plugin/tooltip)                                                                | `tooltip`          | Displays detailed information about elements on hover                  |\n|                              | [Legend](/en/manual/plugin/legend)                                                                  | `legend`           | Displays categories and corresponding style descriptions of chart data |\n| **Data Exploration**         |                                                                                                     |                    |                                                                        |\n|                              | [Fisheye](/en/manual/plugin/fisheye)                                                                | `fisheye`          | Provides a focus + context exploration experience                      |\n|                              | [Edge Filter Lens](/en/manual/plugin/edge-filter-lens)                                              | `edge-filter-lens` | Filters and displays edges within a specified area                     |\n|                              | [Edge Bundling](/en/manual/plugin/edge-bundling)                                                    | `edge-bundling`    | Bundles edges with similar paths together to reduce visual clutter     |\n| **Advanced Features**        |                                                                                                     |                    |                                                                        |\n|                              | [History](/en/manual/plugin/history)                                                                | `history`          | Supports undo/redo operations                                          |\n|                              | [Camera Setting](/enhttps://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | Configures camera parameters in a 3D scene                             |\n\nFor detailed configuration of each plugin, refer to the [Built-in Plugin Documentation](/en/manual/plugin/grid-line).\n\n## Configuration Methods\n\n### Basic Configuration\n\nSpecify the required plugins through the `plugins` array when initializing the graph instance:\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### Configuring Plugin Parameters\n\nFor plugins that require custom parameters, you can configure properties using the `object` form:\n\n```javascript {5-9}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // Specify a key for the plugin for future updates\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### Dynamically Updating Plugins\n\nG6 supports dynamic management of plugins during the runtime of the graph instance to meet complex interaction needs:\n\nUse the [getPlugins](/en/api/plugin#graphgetplugins) method to get the current list of plugins:\n\n```javascript\n// Get the list of plugins\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\nYou can adjust plugins using the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method:\n\n```javascript\n// Add a new plugin\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// Remove a plugin\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\nYou can update the configuration of a plugin using the [updatePlugin](/en/api/plugin#graphupdatepluginplugin) method:\n\n```javascript {6,14}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n\n// Update a single plugin\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>Updated content: ${e.target.id}</div>`,\n});\n```\n\n:::warning{title=Note}\nWhen using the `updatePlugin` method, you need to specify a unique `key` for the plugin during initialization.\n:::\n\n### Uninstalling Plugins\n\nUse the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method to uninstall plugins by setting the plugin configuration list to empty:\n\n```javascript\n// Uninstall all plugins\ngraph.setPlugins([]);\n```\n\n### Calling Plugin Methods\n\nSome plugins provide API methods for users to call, such as the `history` plugin providing `undo` and `redo` methods, allowing users to implement undo and redo operations by calling these methods.\n\nTo call these methods, you need to first get the plugin instance, which can be obtained through the [getPluginInstance](/en/api/plugin#graphgetplugininstancekey) method:\n\n```javascript\n// Configure the plugin\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// Get the plugin instance\nconst history = graph.getPluginInstance('my-history');\n\n// Call plugin methods\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=Note}\nThe `graph.getPluginInstance` method takes the plugin key value as a parameter, so if you need to get the plugin instance, you need to configure the corresponding plugin in the form of an `object` and pass in the `key` value.\n:::\n\nFor more plugin-related APIs, please refer to the [Plugin API Documentation](/en/api/plugin).\n\n## Custom Plugins\n\nWhen built-in plugins cannot meet your needs, you can:\n\n- Inherit and extend existing plugins\n- Create brand new custom plugins\n\nCustom plugins need to be registered before use. For detailed tutorials, please refer to the [Custom Plugin](/en/manual/plugin/custom-plugin) documentation.\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// Register custom plugin\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// Use custom plugin\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\nBy reasonably combining and configuring plugins, you can build graph visualization applications with rich features and excellent interactive experiences.\n","frontmatter":{"title":"Plugin Overview","order":"0"},"isInternal":false,"tokens":2643,"sizeBytes":10573},{"name":"overview.zh.md","path":"packages/site/docs/manual/plugin/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/overview.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 插件总览\norder: 0\n---\n\n## 什么是插件\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n插件(Plugin)是 G6 中最灵活的扩展机制，用户可以通过插件来扩展 G6 的功能，例如在画布中额外挂载图形组件、实现撤销重做等功能。\n\n绝大多数的定制需求都可以通过插件来实现，G6 内置了一些常用的插件，例如：[Tooltip](/manual/plugin/tooltip)、[Grid](/manual/plugin/grid-line)、[History](/manual/plugin/history)。\n\n## 内置插件\n\nG6 提供了丰富的内置插件，涵盖多种常见功能场景：\n\n| 分类             | 插件名称                                                                                   | 注册类型           | 功能描述                               |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------ | -------------------------------------- |\n| **视觉样式增强** |                                                                                            |                    |                                        |\n|                  | [网格线](/manual/plugin/grid-line)                                                         | `grid-line`        | 在画布上显示网格参考线                 |\n|                  | [背景](/manual/plugin/background)                                                          | `background`       | 为画布添加背景图片或颜色               |\n|                  | [水印](/manual/plugin/watermark)                                                           | `watermark`        | 为画布添加水印，保护版权               |\n|                  | [轮廓包围](/manual/plugin/hull)                                                            | `hull`             | 为指定节点集合创建轮廓                 |\n|                  | [气泡集](/manual/plugin/bubble-sets)                                                       | `bubble-sets`      | 创建平滑气泡状的元素集合轮廓           |\n|                  | [对齐线](/manual/plugin/snapline)                                                          | `snapline`         | 拖动元素时显示对齐参考线               |\n| **导航与概览**   |                                                                                            |                    |                                        |\n|                  | [缩略图](/manual/plugin/minimap)                                                           | `minimap`          | 显示图的缩略预览，支持导航             |\n|                  | [全屏](/manual/plugin/fullscreen)                                                          | `fullscreen`       | 支持图表全屏显示和退出                 |\n|                  | [时间轴](/manual/plugin/timebar)                                                           | `timebar`          | 提供时序数据的筛选和播放控制           |\n| **交互控件**     |                                                                                            |                    |                                        |\n|                  | [工具栏](/manual/plugin/toolbar)                                                           | `toolbar`          | 提供常用操作按钮集合                   |\n|                  | [上下文菜单](/manual/plugin/contextmenu)                                                   | `contextmenu`      | 右键点击时显示可选操作菜单             |\n|                  | [提示框](/manual/plugin/tooltip)                                                           | `tooltip`          | 悬停时显示元素详细信息                 |\n|                  | [图例](/manual/plugin/legend)                                                              | `legend`           | 显示图表数据的类别和对应样式说明       |\n| **数据探索**     |                                                                                            |                    |                                        |\n|                  | [鱼眼放大镜](/manual/plugin/fisheye)                                                       | `fisheye`          | 提供焦点+上下文的探索体验              |\n|                  | [边过滤镜](/manual/plugin/edge-filter-lens)                                                | `edge-filter-lens` | 在指定区域内筛选显示边                 |\n|                  | [边绑定](/manual/plugin/edge-bundling)                                                     | `edge-bundling`    | 将相似路径的边捆绑在一起，减少视觉混乱 |\n| **高级功能**     |                                                                                            |                    |                                        |\n|                  | [历史记录](/manual/plugin/history)                                                         | `history`          | 支持撤销/重做操作                      |\n|                  | [相机设置](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | 配置3D场景下的相机参数                 |\n\n各插件的详细配置可参考 [内置插件文档](/manual/plugin/grid-line)。\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `plugins` 数组指定需要的插件：\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### 配置插件参数\n\n对于需要自定义参数的插件，可以使用 `object` 形式配置属性：\n\n```javascript {5-9}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // 为插件指定key，便于后续更新\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### 动态更新插件\n\nG6 支持在图实例运行期间动态管理插件，满足复杂交互需求：\n\n通过 [getPlugins](/api/plugin#graphgetplugins) 方法获取当前插件列表：\n\n```javascript\n// 获取插件列表\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\n可以通过 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法调整插件：\n\n```javascript\n// 添加新插件\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// 移除插件\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\n可以通过 [updatePlugin](/api/plugin#graphupdatepluginplugin) 方法更新插件的配置：\n\n```javascript {6,14}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n\n// 更新单个插件\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>更新的内容：${e.target.id}</div>`,\n});\n```\n\n:::warning{title=注意}\n使用 `updatePlugin` 方法时，需要在初始化时为插件指定唯一的 `key`。\n:::\n\n### 卸载插件\n\n使用 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法同样可以卸载插件，将插件配置列表置为空即可：\n\n```javascript\n// 卸载所有插件\ngraph.setPlugins([]);\n```\n\n### 调用插件方法\n\n一些插件提供了可供用户调用的 API 方法，例如 `history` 插件提供了 `undo` 和 `redo` 方法，用户可以通过调用这些方法来实现撤销和重做操作。\n\n要调用这些方法，需要先获取到插件实例，可通过 [getPluginInstance](/api/plugin#graphgetplugininstancekey) 方法获取：\n\n```javascript\n// 配置插件\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// 获取插件实例\nconst history = graph.getPluginInstance('my-history');\n\n// 调用插件方法\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=注意}\n`graph.getPluginInstance` 方法接收插件 key 值作为参数，因此如果需要获取插件实例，需要将对应插件配置为 `object` 的形式，并传入 `key` 值。\n:::\n\n更多与插件相关的 API 请参考 [插件 API 文档](/api/plugin)。\n\n## 自定义插件\n\n当内置插件无法满足需求时，你可以：\n\n- 继承和扩展现有插件\n- 创建全新的自定义插件\n\n自定义插件需要先注册后使用。详细教程请参考 [自定义插件](/manual/plugin/custom-plugin) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// 注册自定义插件\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// 使用自定义插件\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\n通过合理组合和配置插件，你可以构建出功能丰富、交互体验出色的图可视化应用。\n","frontmatter":{"title":"插件总览","order":"0"},"isInternal":false,"tokens":1769,"sizeBytes":9051},{"name":"Snapline.en.md","path":"packages/site/docs/manual/plugin/Snapline.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Snapline.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Snapline\norder: 13\n---\n\n## Overview\n\nThe Snapline plugin provides intelligent alignment guidelines for the canvas, automatically displaying guide lines when moving nodes and supporting automatic snapping. It helps users achieve precise alignment and is an important tool for improving efficiency and accuracy in graphic editing.\n\n## Use Cases\n\nThe Snapline plugin is mainly suitable for the following scenarios:\n\n- When manually adjusting node positions and precise alignment with other nodes is needed\n- When dragging multiple nodes while maintaining their alignment relationships\n- When creating standardized graphic layouts to ensure consistency in node spacing and positioning\n- When improving node layout efficiency through automatic snapping functionality\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // Specify unique identifier\n      tolerance: 5, // Alignment snap threshold\n      offset: 20, // Guide line extension distance\n      autoSnap: true, // Enable automatic snapping\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## Options\n\n| Property            | Description                                                                                                                                                                                            | Type                                      | Default                 | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ----------------------- | -------- |\n| type                | Plugin type                                                                                                                                                                                            | string                                    | `'snapline'`            | ✓        |\n| key                 | Plugin unique identifier                                                                                                                                                                               | string                                    | -                       |          |\n| tolerance           | The alignment accuracy, that is, when the distance between the moved node and the target position is less than tolerance, the alignment line is displayed                                              | number                                    | 5                       |          |\n| offset              | The extension distance of the snapline                                                                                                                                                                 | number                                    | 20                      |          |\n| autoSnap            | Whether to enable automatic snapping                                                                                                                                                                   | boolean                                   | true                    |          |\n| shape               | Specifies which shape on the element to use as the reference shape:<br/>- `'key'`: uses the key shape of the element as the reference shape<br/>- `Function`: receives the element and returns a shape | string \\| ((node: Node) => DisplayObject) | `'key'`                 |          |\n| verticalLineStyle   | Vertical snapline style                                                                                                                                                                                | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| horizontalLineStyle | Horizontal snapline style                                                                                                                                                                              | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| filter              | Filter nodes that do not need to participate in alignment                                                                                                                                              | (node: Node) => boolean                   | `() => true`            |          |\n\n### shape\n\nThe `shape` property specifies the reference shape for elements and supports the following configurations:\n\n```js\n// Use the key shape as reference\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// Use custom function to return reference shape\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### Snapline Style Configuration\n\n| Property       | Description             | Type                                     | Default     |\n| -------------- | ----------------------- | ---------------------------------------- | ----------- |\n| stroke         | Line color              | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | Overall opacity         | number \\| string                         | 1           |\n| strokeOpacity  | Stroke opacity          | number \\| string                         | 1           |\n| lineWidth      | Line width              | number \\| string                         | 1           |\n| lineCap        | Line end style          | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | Line join style         | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | Dash line configuration | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | Dash line offset        | number                                   | 0           |\n| shadowBlur     | Shadow blur             | number                                   | 0           |\n| shadowColor    | Shadow color            | string                                   | -           |\n| shadowOffsetX  | Shadow X offset         | number                                   | 0           |\n| shadowOffsetY  | Shadow Y offset         | number                                   | 0           |\n| cursor         | Mouse cursor style      | string                                   | `'default'` |\n| zIndex         | Rendering level         | number                                   | 0           |\n\nExample configuration:\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## Code Examples\n\n### Basic Snapline\n\nThe simplest usage:\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### Custom Configuration\n\nYou can customize the snapline behavior according to your needs:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // Larger snap range\n      offset: 30, // Longer extension lines\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // Filter nodes by id, exclude from alignment\n    },\n  ],\n});\n```\n\n## Live Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Snapline","order":"13"},"isInternal":false,"tokens":2139,"sizeBytes":8555},{"name":"Snapline.zh.md","path":"packages/site/docs/manual/plugin/Snapline.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Snapline.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 对齐线 Snapline\norder: 13\n---\n\n## 概述\n\n对齐线插件为画布提供智能对齐参考线，在移动节点时自动显示辅助线并支持自动吸附，帮助用户实现精确对齐，是图形编辑中提升效率和精确度的重要工具。\n\n## 使用场景\n\n对齐线插件主要适用于以下场景：\n\n- 手动调整节点位置时,需要与其他节点精确对齐\n- 拖拽移动多个节点时,保持它们之间的对齐关系\n- 制作规范的图形布局时,确保节点间距和位置的一致性\n- 通过自动吸附功能提高节点排版效率\n\n## 基本用法\n\n以下是一个简单的 Snapline 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // 指定唯一标识符\n      tolerance: 5, // 对齐吸附阈值\n      offset: 20, // 对齐线延伸距离\n      autoSnap: true, // 启用自动吸附\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## 配置项\n\n| 属性                | 描述                                                                                                                    | 类型                                                                                                                            | 默认值                  | 必选 |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type                | 插件类型                                                                                                                | string                                                                                                                          | `'snapline'`            | ✓    |\n| key                 | 插件唯一标识符                                                                                                          | string                                                                                                                          | -                       |      |\n| tolerance           | 对齐精度，即触发对齐的距离阈值                                                                                          | number                                                                                                                          | 5                       |      |\n| offset              | 对齐线头尾的延伸距离                                                                                                    | number                                                                                                                          | 20                      |      |\n| autoSnap            | 是否启用自动吸附                                                                                                        | boolean                                                                                                                         | true                    |      |\n| shape               | 指定元素的参照图形：<br/>- `'key'`: 使用元素的主图形作为参照图形<br/>- `Function`: 传入函数时接收元素对象，返回一个图形 | string \\| ((node: Node) => DisplayObject)                                                                                       | `'key'`                 |      |\n| verticalLineStyle   | 垂直对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| horizontalLineStyle | 水平对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| filter              | 过滤不需要参与对齐的节点                                                                                                | (node: Node) => boolean                                                                                                         | `() => true`            |      |\n\n### shape\n\n`shape` 属性用于指定元素的参照图形，支持以下配置方式：\n\n```js\n// 使用主图形作为参照\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// 使用自定义函数返回参照图形\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### 对齐线样式配置\n\n| 配置项         | 说明            | 类型                                     | 默认值      |\n| -------------- | --------------- | ---------------------------------------- | ----------- |\n| stroke         | 线条颜色        | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | 整体透明度      | number \\| string                         | 1           |\n| strokeOpacity  | 描边透明度      | number \\| string                         | 1           |\n| lineWidth      | 线宽度          | number \\| string                         | 1           |\n| lineCap        | 线段端点样式    | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | 线段连接处样式  | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | 虚线配置        | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | 虚线偏移量      | number                                   | 0           |\n| shadowBlur     | 阴影模糊程度    | number                                   | 0           |\n| shadowColor    | 阴影颜色        | string                                   | -           |\n| shadowOffsetX  | 阴影 X 方向偏移 | number                                   | 0           |\n| shadowOffsetY  | 阴影 Y 方向偏移 | number                                   | 0           |\n| cursor         | 鼠标样式        | string                                   | `'default'` |\n| zIndex         | 渲染层级        | number                                   | 0           |\n\n示例配置\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## 代码示例\n\n### 基础对齐线\n\n最简单的使用方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### 自定义配置\n\n可以根据需要自定义对齐线的行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // 更大的吸附范围\n      offset: 30, // 更长的延伸线\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // 根据id过滤节点，不参与对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"对齐线 Snapline","order":"13"},"isInternal":false,"tokens":1820,"sizeBytes":8498},{"name":"Timebar.en.md","path":"packages/site/docs/manual/plugin/Timebar.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Timebar.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Timebar\norder: 14\n---\n\n## Overview\n\nThe Timebar plugin is an important tool for exploring time-series data. It can display the time distribution of data in the form of a timeline or trend chart, and supports interactions such as time interval filtering and dynamic playback, helping users better understand the changes in data over time.\n\n## Use Cases\n\n- Need to display and analyze the time distribution of time-series data\n- Need to filter and explore graph data through the time dimension\n- Need to dynamically display the process of data changing over time\n\n## Basic Usage\n\nBelow is a simple example of initializing the Timebar plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // Time data\n      width: 450, // Timebar width\n      height: 60, // Timebar height\n      position: 'bottom', // Position\n      loop: false, // Whether to loop playback\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                              | Type                                               | Default Value | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type           | Plugin type                                                                                                                                                                              | string                                             | `timebar`     | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                        | string                                             | -             |          |\n| className      | Additional class name for the toolbar DOM                                                                                                                                                | string                                             | `g6-timebar`  |          |\n| x              | X position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| y              | Y position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| width          | Timebar width                                                                                                                                                                            | number                                             | 450           |          |\n| height         | Timebar height                                                                                                                                                                           | number                                             | 60            |          |\n| position       | Timebar position                                                                                                                                                                         | `bottom` \\| `top`                                  | `bottom`      |          |\n| padding        | Padding                                                                                                                                                                                  | number \\| number[]                                 | 10            |          |\n| data           | Time data                                                                                                                                                                                | number[] \\| { time: number; value: number }[]      | -             | ✓        |\n| timebarType    | Timebar display type                                                                                                                                                                     | `time` \\| `chart`                                  | `time`        |          |\n| elementTypes   | Filter element types                                                                                                                                                                     | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]      |          |\n| mode           | Control element filtering method, supports the following two configurations: <br/>- `modify`: filter by modifying graph data <br/>- `visibility`: filter by modifying element visibility | `modify` \\| `visibility`                           | `modify`      |          |\n| values         | Current time value                                                                                                                                                                       | number \\| [number, number] \\| Date \\| [Date, Date] | -             |          |\n| loop           | Whether to loop playback                                                                                                                                                                 | boolean                                            | false         |          |\n| getTime        | Method to get element time                                                                                                                                                               | (datum: ElementDatum) => number                    | -             |          |\n| labelFormatter | Custom time formatting in chart mode                                                                                                                                                     | (time: number \\| Date) => string                   | -             |          |\n| onChange       | Callback when the time interval changes                                                                                                                                                  | (values: number \\| [number, number]) => void       | -             |          |\n| onReset        | Callback when reset                                                                                                                                                                      | () => void                                         | -             |          |\n| onSpeedChange  | Callback when playback speed changes                                                                                                                                                     | (speed: number) => void                            | -             |          |\n| onPlay         | Callback when playback starts                                                                                                                                                            | () => void                                         | -             |          |\n| onPause        | Callback when paused                                                                                                                                                                     | () => void                                         | -             |          |\n| onBackward     | Callback when moving backward                                                                                                                                                            | () => void                                         | -             |          |\n| onForward      | Callback when moving forward                                                                                                                                                             | () => void                                         | -             |          |\n\n### timebarType\n\nThe `timebarType` property is used to control the display type of the timebar, supporting the following two configurations:\n\n- `time`: Displayed as a timeline, refer to [Time Mode Example](/examples/plugin/timebar/#timer)\n- `chart`: Displayed as a trend chart, at this time the `data` configuration item under `timebar` needs to pass an additional `value` field as chart data, refer to [Chart Mode Example](/examples/plugin/timebar/#chart)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        // By default, elementTypes=['node'], so nodes need to set data.timestamp to display sequentially according to the timeline\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // Scenario 1: By default, elementTypes = ['node']\n        // - Edges do not need to set data.timestamp, the display/hide of edges depends entirely on whether the two connected nodes are visible\n\n        // Scenario 2: If elementTypes includes 'edge', for example, elementTypes = ['node', 'edge']\n        // - At this time, edges must set data.timestamp, and the display of edges is controlled by it\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\n`width`, `height`, `padding`, `className` can customize the display effect of the timebar, but note that `className` only acts on the outer DOM container and cannot affect the internal Canvas rendering content of the timebar (timeline, chart, play button, etc.).\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // Note: Since the content is Canvas rendered, CSS styles cannot affect the internal content of the timebar\n      width: 400, // Set timebar width\n      height: 80, // Set timebar height\n      padding: [20, 20, 10, 20], // Set padding [top, right, bottom, left]\n      position: 'bottom', // Keep position at the bottom\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\nCSS can only set the style of the timebar container:\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## Real Cases\n\n- [Time Mode](/examples/plugin/timebar/#timer)\n- [Chart Mode](/examples/plugin/timebar/#chart)\n","frontmatter":{"title":"Timebar","order":"14"},"isInternal":false,"tokens":3902,"sizeBytes":15609},{"name":"Timebar.zh.md","path":"packages/site/docs/manual/plugin/Timebar.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Timebar.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 时间条 Timebar\norder: 14\n---\n\n## 概述\n\n时间条插件是一个用于时序数据探索的重要工具，它能够通过时间轴或趋势图的形式展示数据的时间分布，并支持时间区间筛选、动态播放等交互方式，帮助用户更好地理解数据随时间的变化。\n\n## 使用场景\n\n- 需要展示和分析时序数据的时间分布\n- 需要通过时间维度筛选和探索图数据\n- 需要动态展示数据随时间变化的过程\n\n## 基本用法\n\n以下是一个简单的 Timebar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // 时间数据\n      width: 450, // 时间条宽度\n      height: 60, // 时间条高度\n      position: 'bottom', // 位置\n      loop: false, // 是否循环播放\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                           | 类型                                               | 默认值       | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------------ | ---- |\n| type           | 插件类型                                                                                                                       | string                                             | `timebar`    | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                               | string                                             | -            |      |\n| className      | 给工具栏的 DOM 追加的类名                                                                                                      | string                                             | `g6-timebar` |      |\n| x              | X 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| y              | Y 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| width          | 时间条宽度                                                                                                                     | number                                             | 450          |      |\n| height         | 时间条高度                                                                                                                     | number                                             | 60           |      |\n| position       | 时间条位置                                                                                                                     | `bottom` \\| `top`                                  | `bottom`     |      |\n| padding        | 边距                                                                                                                           | number \\| number[]                                 | 10           |      |\n| data           | 时间数据                                                                                                                       | number[] \\| { time: number; value: number }[]      | -            | ✓    |\n| timebarType    | 时间条展示类型                                                                                                                 | `time` \\| `chart`                                  | `time`       |      |\n| elementTypes   | 筛选元素类型                                                                                                                   | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]     |      |\n| mode           | 控制元素的筛选方式，支持以下两种配置： <br/>- `modify`：通过修改图数据进行筛选 <br/>- `visibility`：通过修改元素可见性进行筛选 | `modify` \\| `visibility`                           | `modify`     |      |\n| values         | 当前时间值                                                                                                                     | number \\| [number, number] \\| Date \\| [Date, Date] | -            |      |\n| loop           | 是否循环播放                                                                                                                   | boolean                                            | false        |      |\n| getTime        | 获取元素时间的方法                                                                                                             | (datum: ElementDatum) => number                    | -            |      |\n| labelFormatter | 图表模式下自定义时间格式化                                                                                                     | (time: number \\| Date) => string                   | -            |      |\n| onChange       | 时间区间变化时的回调                                                                                                           | (values: number \\| [number, number]) => void       | -            |      |\n| onReset        | 重置时的回调                                                                                                                   | () => void                                         | -            |      |\n| onSpeedChange  | 播放速度变化时的回调                                                                                                           | (speed: number) => void                            | -            |      |\n| onPlay         | 开始播放时的回调                                                                                                               | () => void                                         | -            |      |\n| onPause        | 暂停时的回调                                                                                                                   | () => void                                         | -            |      |\n| onBackward     | 后退时的回调                                                                                                                   | () => void                                         | -            |      |\n| onForward      | 前进时的回调                                                                                                                   | () => void                                         | -            |      |\n\n### timebarType\n\n`timebarType` 属性用于控制时间条的展示类型，支持以下两种配置：\n\n- `time`：显示为时间轴形式，参考 [时间模式示例](/examples/plugin/timebar/#timer)\n- `chart`：显示为趋势图形式，此时`timebar`下的`data`配置项，每个数组项需要额外传入 `value` 字段作为图表数据，参考 [图表模式示例](/examples/plugin/timebar/#chart)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        // 默认情况下 elementTypes=['node']，所以节点需要设置 data.timestamp，才能按照时间轴内的时间依次展示\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // 场景一：默认情况 elementTypes = ['node']\n        // - 边不需要设置 data.timestamp，边的显示/隐藏完全取决于其连接的两个节点是否可见\n\n        // 场景二：如果elementTypes包含了'edge'，比如 elementTypes = ['node', 'edge']\n        // - 此时必须为边设置 data.timestamp，边的显示受其控制\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n`width`、`height`、`padding`、`className` 可自定义时间条的展示效果，但需要注意 `className` 仅作用于外层 DOM 容器，无法影响时间条内部的 Canvas 渲染内容（时间轴、图表、播放按钮等）。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // 注意：由于内容是 Canvas 渲染，CSS 样式无法影响到时间条的内部内容\n      width: 400, // 设置时间条宽度\n      height: 80, // 设置时间条高度\n      padding: [20, 20, 10, 20], // 设置内边距 [上, 右, 下, 左]\n      position: 'bottom', // 位置保持在底部\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\n通过 CSS 只能设置时间条容器的样式：\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\n效果如下：\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## 实际案例\n\n- [时间模式](/examples/plugin/timebar/#timer)\n- [图表模式](/examples/plugin/timebar/#chart)\n","frontmatter":{"title":"时间条 Timebar","order":"14"},"isInternal":false,"tokens":3090,"sizeBytes":13953},{"name":"Title.en.md","path":"packages/site/docs/manual/plugin/Title.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Title.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Title\norder: 15\n---\n\n## Overview\n\nTitle indicates the name of the image and conveys the brief content of the image.\n\n## Basic Usage\n\nThe following is a simple example of initializing the Title plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: 'This is a title',\n      subTitle: 'This is a subtitle',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                   | Type                          | Default      | Required |\n| --------- | ------------------------------------------------------------- | ----------------------------- | ------------ | -------- |\n| type      | Plugin type                                                   | string                        | `title`      | ✓        |\n| key       | Unique identifier for the plugin, used for subsequent updates | string                        | -            |          |\n| title     | title content [style config](#title)                          | `TitleStyle`                  | -            | ✓        |\n| subtitle  | subtitle content [style config](#subtitle)                    | `SubTitleStyle`               | -            |          |\n| spacing   | Vertical spacing between main title and subtitle              | number                        | 8            |          |\n| className | Class name of the title canvas                                | string                        | -            |          |\n| align     | Graph title alignment                                         | `left` \\| `center` \\| `right` | `left`       |          |\n| size      | Height of the title plugin                                    | number                        | 44           |          |\n| padding   | Padding                                                       | number \\| number[]            | [16,24,0,24] |          |\n\n### size\n\n<description> _number_ **optional** </description>\n\nUsed to configure the space height of the title plugin. Default is `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\nUsed to configure the horizontal alignment of the title plugin. Default is `left`. You can choose `left`, `center`, or `right`, representing left-aligned, center-aligned, and right-aligned respectively.\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: 'Ciallo' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: 'This is a title This is a title',\n        subtitle: 'This is a sub-',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\nUsed to configure the spacing between the chart main title and subtitle. Default is `8`. Appropriate spacing can make the chart look more harmonious overall.\n\n### title\n\nThe title, specifically the main title, can be customized with the following configurations for various title styles.\n\n| Attr               | Desc                                               | Type       | Default               |\n| ------------------ | -------------------------------------------------- | ---------- | --------------------- |\n| title              | Title text content                                 | `string`   | -                     |\n| titleFontSize      | Title text size                                    | `number`   | 16                    |\n| titleFontFamily    | Title text font                                    | `string`   | system-ui, sans-serif |\n| titleFontWeight    | Title font weight                                  | `number`   | bold                  |\n| titleLineHeight    | Title text line height                             | `number`   | 16                    |\n| titleTextAlign     | Horizontal alignment of content in title text line | `string`   | left                  |\n| titleTextBaseline  | Vertical baseline of title text                    | `string`   | top                   |\n| titleFill          | Fill color of title text                           | `string`   | #1D2129               |\n| titleFillOpacity   | Fill transparency of title text                    | `number`   | 0.9                   |\n| titleStroke        | Stroke color of title text                         | `string`   | transparent           |\n| titleStrokeOpacity | Stroke transparency of title text                  | `number`   | 1                     |\n| titleLineWidth     | Stroke width of title text                         | `number`   | 0                     |\n| titleLineDash      | Dash style of title text                           | `number[]` | []                    |\n| titleOpacity       | Overall transparency of title text                 | `number`   | 1                     |\n| titleShadowColor   | Shadow color of title text                         | `string`   | transparent           |\n| titleShadowBlur    | Gaussian blur coefficient of title text shadow     | `number`   | 0                     |\n| titleShadowOffsetX | Horizontal offset of title text shadow             | `number`   | 0                     |\n| titleShadowOffsetY | Vertical offset of title text shadow               | `number`   | 0                     |\n| titleCursor        | Mouse style of title text                          | `string`   | default               |\n| titleDx            | Horizontal offset of title text                    | `number`   | 0                     |\n| titleDy            | Vertical offset of title text                      | `number`   | 0                     |\n\n### subtitle\n\nThe subtitle, which can be customized with the following configurations for various subtitle styles.\n\n| Attr                  | Desc                                            | Type       | Default               |\n| --------------------- | ----------------------------------------------- | ---------- | --------------------- |\n| subtitle              | Subtitle text content                           | `string`   | -                     |\n| subtitleFontSize      | Subtitle text size                              | `number`   | 12                    |\n| subtitleFontFamily    | Subtitle text font                              | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | Subtitle font weight                            | `number`   | normal                |\n| subtitleLineHeight    | Subtitle text line height                       | `number`   | 12                    |\n| subtitleTextAlign     | Subtitle text line content horizontal alignment | `string`   | left                  |\n| subtitleTextBaseline  | Subtitle text vertical baseline                 | `string`   | top                   |\n| subtitleFill          | Subtitle text fill color                        | `string`   | #1D2129               |\n| subtitleFillOpacity   | Subtitle text fill transparency                 | `number`   | 0.65                  |\n| subtitleStroke        | Subtitle text stroke color                      | `string`   | transparent           |\n| subtitleStrokeOpacity | Subtitle text stroke transparency               | `number`   | 1                     |\n| subtitleLineWidth     | Subtitle text stroke width                      | `number`   | 0                     |\n| subtitleLineDash      | Subtitle text dashed line style                 | `number[]` | []                    |\n| subtitleOpacity       | Subtitle text overall transparency              | `number`   | 1                     |\n| subtitleShadowColor   | Subtitle text shadow color                      | `string`   | transparent           |\n| subtitleShadowBlur    | Subtitle text shadow Gaussian blur coefficient  | `number`   | 0                     |\n| subtitleShadowOffsetX | Subtitle text shadow horizontal offset          | `number`   | 0                     |\n| subtitleShadowOffsetY | Subtitle text shadow vertical offset            | `number`   | 0                     |\n| subtitleCursor        | Subtitle text mouse style                       | `string`   | default               |\n| subtitleDx            | Subtitle text horizontal offset                 | `number`   | 0                     |\n| subtitleDy            | Subtitle text vertical offset                   | `number`   | 0                     |\n\n## Try it\n\nFeel free to modify this example and try different configurations\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // Alignment of title\n      spacing: 4, // Spacing between main title and subtitle\n      size: 60, // Height of title, default is 44\n\n      // title\n      title: 'This is a title This is a title', // Title text\n      titleFontSize: 28, // Main title font size\n      titleFontFamily: 'sans-serif', // Main title font\n      titleFontWeight: 600, // Main title font weight\n      titleFill: '#fff', // Main title text color\n      titleFillOpacity: 1, // Main title text transparency\n      titleStroke: '#000', // Main title text stroke color\n      titleLineWidth: 2, // Main title text stroke line width\n      titleStrokeOpacity: 1, // Main title text stroke transparency\n\n      // subtitle\n      subtitle: 'This is a sub-', // Subtitle text\n      subtitleFontSize: 16, // Subtitle font size\n      subtitleFontFamily: 'Arial', // Subtitle font\n      subtitleFontWeight: 300, // Subtitle font weight\n      subtitleFill: '#2989FF', // Subtitle text color\n      subtitleFillOpacity: 1, // Subtitle text transparency\n      subtitleStroke: '#000', // Subtitle text stroke color\n      subtitleLineWidth: 1, // Subtitle text stroke line width\n      subtitleStrokeOpacity: 0.5, // Subtitle text stroke transparency\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: 'Ciallo' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Title","order":"15"},"isInternal":false,"tokens":2676,"sizeBytes":10707},{"name":"Title.zh.md","path":"packages/site/docs/manual/plugin/Title.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Title.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 标题 Title\norder: 15\n---\n\n## 概述\n\nTitle（标题）表明了这张图的名称，传达图的简略内容\n\n## 基本用法\n\n以下是一个简单的 Title 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: '这是一个标题',\n      subTitle: '这是一个副标题',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                             | 类型                          | 默认值       | 必选 |\n| --------- | -------------------------------- | ----------------------------- | ------------ | ---- |\n| type      | 插件类型                         | string                        | `title`      | ✓    |\n| key       | 插件唯一标识符，用于后续更新     | string                        | -            |      |\n| title     | 标题内容 [样式配置](#title)      | `TitleStyle`                  | -            | ✓    |\n| subtitle  | 副标题内容 [样式配置](#subtitle) | `SubTitleStyle`               | -            |      |\n| spacing   | 主标题、副标题之间的上下间距     | number                        | 8            |      |\n| className | 标题画布类名                     | string                        | -            |      |\n| align     | 标题相对于画布的位置             | `left` \\| `center` \\| `right` | `left`       |      |\n| size      | 整个标题插件的高度               | number                        | 44           |      |\n| padding   | 内边距                           | number \\| number[]            | [16,24,0,24] |      |\n\n### size\n\n<description> _number_ **optional** </description>\n\n用于配置标题的空间高度大小，默认为 `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\n用于配置标题的的左右对齐方式，默认为 `left`，可以选择使用 `left`，`center`，`right`，分别代表着居左对齐、居中对齐、居右对齐。\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: '你好' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: '这是一个标题这是一个标题',\n        subtitle: '这是一个副标',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\n用于配置主标题和副标题之间的间距，默认为 `8`，合适的间距，可以让看起来整体更协调。\n\n### title\n\n的标题，具体来说是主标题，可以用以下的配置来定制标题的各种样式。\n\n| 属性               | 描述                           | 类型       | 默认值                |\n| ------------------ | ------------------------------ | ---------- | --------------------- |\n| title              | 标题文字内容                   | `string`   | -                     |\n| titleFontSize      | 标题文字大小                   | `number`   | 16                    |\n| titleFontFamily    | 标题文字字体                   | `string`   | system-ui, sans-serif |\n| titleFontWeight    | 标题字体粗细                   | `number`   | bold                  |\n| titleLineHeight    | 标题文字的行高                 | `number`   | 16                    |\n| titleTextAlign     | 标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| titleTextBaseline  | 标题文字垂直方向的基线         | `string`   | top                   |\n| titleFill          | 标题文字的填充色               | `string`   | #1D2129               |\n| titleFillOpacity   | 标题文字的填充透明度           | `number`   | 0.9                   |\n| titleStroke        | 标题文字的描边颜色             | `string`   | transparent           |\n| titleStrokeOpacity | 标题文字的描边透明度           | `number`   | 1                     |\n| titleLineWidth     | 标题文字描边宽度               | `number`   | 0                     |\n| titleLineDash      | 标题文字虚线样式               | `number[]` | []                    |\n| titleOpacity       | 标题文字整体透明度             | `number`   | 1                     |\n| titleShadowColor   | 标题文字阴影颜色               | `string`   | transparent           |\n| titleShadowBlur    | 标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| titleShadowOffsetX | 标题文字阴影水平偏移量         | `number`   | 0                     |\n| titleShadowOffsetY | 标题文字阴影垂直偏移量         | `number`   | 0                     |\n| titleCursor        | 标题文字鼠标样式               | `string`   | default               |\n| titleDx            | 标题文字在水平方向的偏移量     | `number`   | 0                     |\n| titleDy            | 标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n### subtitle\n\n的副标题，可以用以下的配置来定制副标题的各种样式。\n\n| 属性                  | 描述                             | 类型       | 默认值                |\n| --------------------- | -------------------------------- | ---------- | --------------------- |\n| subtitle              | 副标题文字内容                   | `string`   | -                     |\n| subtitleFontSize      | 副标题文字大小                   | `number`   | 12                    |\n| subtitleFontFamily    | 副标题文字字体                   | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | 副标题字体粗细                   | `number`   | normal                |\n| subtitleLineHeight    | 副标题文字的行高                 | `number`   | 12                    |\n| subtitleTextAlign     | 副标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| subtitleTextBaseline  | 副标题文字垂直方向的基线         | `string`   | top                   |\n| subtitleFill          | 副标题文字的填充色               | `string`   | #1D2129               |\n| subtitleFillOpacity   | 副标题文字的填充透明度           | `number`   | 0.65                  |\n| subtitleStroke        | 副标题文字的描边颜色             | `string`   | transparent           |\n| subtitleStrokeOpacity | 副标题文字的描边透明度           | `number`   | 1                     |\n| subtitleLineWidth     | 副标题文字描边宽度               | `number`   | 0                     |\n| subtitleLineDash      | 副标题文字虚线样式               | `number[]` | []                    |\n| subtitleOpacity       | 副标题文字整体透明度             | `number`   | 1                     |\n| subtitleShadowColor   | 副标题文字阴影颜色               | `string`   | transparent           |\n| subtitleShadowBlur    | 副标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| subtitleShadowOffsetX | 副标题文字阴影水平偏移量         | `number`   | 0                     |\n| subtitleShadowOffsetY | 副标题文字阴影垂直偏移量         | `number`   | 0                     |\n| subtitleCursor        | 副标题文字鼠标样式               | `string`   | default               |\n| subtitleDx            | 副标题文字在水平方向的偏移量     | `number`   | 0                     |\n| subtitleDy            | 副标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n## 尝试一下\n\n你可以在这个例子里随意修改并尝试不同的配置\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // 标题的对齐方式\n      spacing: 4, // 主标题和副标题之间的间距\n      size: 60, // 标题的高度，默认为 44\n\n      // 标题\n      title: '这是一个标题这是一个标题', // 标题的文本\n      titleFontSize: 28, // 主标题的字体大小\n      titleFontFamily: 'sans-serif', // 主标题的字体\n      titleFontWeight: 600, // 主标题的字体粗细\n      titleFill: '#fff', // 主标题的文字颜色\n      titleFillOpacity: 1, // 主标题的文字透明度\n      titleStroke: '#000', // 主标题的文字描边颜色\n      titleLineWidth: 2, // 主标题的文字描边线宽\n      titleStrokeOpacity: 1, // 主标题的文字描边透明度\n\n      // 副标题\n      subtitle: '这是一个副标', // 副标题的文本\n      subtitleFontSize: 16, // 副标题的字体大小\n      subtitleFontFamily: 'Arial', // 副标题的字体\n      subtitleFontWeight: 300, // 副标题的字体粗细\n      subtitleFill: '#2989FF', // 副标题的文字颜色\n      subtitleFillOpacity: 1, // 副标题的文字透明度\n      subtitleStroke: '#000', // 副标题的文字描边颜色\n      subtitleLineWidth: 1, // 副标题的文字描边线宽\n      subtitleStrokeOpacity: 0.5, // 副标题的文字描边透明度\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: '你好' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"标题 Title","order":"15"},"isInternal":false,"tokens":1997,"sizeBytes":9976},{"name":"Toolbar.en.md","path":"packages/site/docs/manual/plugin/Toolbar.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Toolbar.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Toolbar\norder: 15\n---\n\n## Overview\n\nThe Toolbar is a plugin in G6 used to provide a collection of operation buttons, supporting common chart operations such as zoom in, zoom out, auto-fit, and reset. Through the toolbar, users can quickly access common functions of the chart, improving operational efficiency and user experience.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Quickly accessing common functions of the chart\n\n## Basic Usage\n\nBelow is a simple example of initializing the Toolbar plugin:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // Handle button click events\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property  | Description                                                                  | Type                                                                                        | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type      | Plugin type                                                                  | string                                                                                      | `toolbar`     | ✓        |\n| key       | Unique identifier for the plugin, used for updates                           | string                                                                                      | -             |          |\n| className | Additional CSS class name for the toolbar DOM element                        | string                                                                                      | -             |          |\n| position  | Toolbar position relative to the canvas, [optional values](#position)        | string                                                                                      | `'top-left'`  |          |\n| style     | Custom style for the toolbar DOM element, [common values](#style-attributes) | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| getItems  | Returns the list of toolbar items                                            | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -             | ✓        |\n| onClick   | Callback function after a toolbar item is clicked                            | (value: string, target: Element) => void                                                    | -             |          |\n\n### position\n\nThe `position` parameter supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side, top\n- `'left-bottom'`: Left side, bottom\n- `'right-top'`: Right side, top\n- `'right-bottom'`: Right side, bottom\n\n### style Attributes\n\n| Attribute       | Description      | Type   | Default Value       |\n| --------------- | ---------------- | ------ | ------------------- |\n| backgroundColor | Background color | string | `#fff`              |\n| border          | Border           | string | `1px solid #e8e8e8` |\n| borderRadius    | Border radius    | string | `4px`               |\n| height          | Height           | string | `auto`              |\n| margin          | Margin           | string | `12px`              |\n| opacity         | Opacity          | number | 0.9                 |\n| padding         | Padding          | string | `8px`               |\n| width           | Width            | string | `auto`              |\n\n### ToolbarItem\n\nEach toolbar item (ToolbarItem) includes the following attributes:\n\n| Attribute | Description                                                | Type     | Required |\n| --------- | ---------------------------------------------------------- | -------- | -------- |\n| id        | Icon ID of the item, see [Built-in Icons](#built-in-icons) | `string` | ✓        |\n| value     | Value returned when the item is clicked                    | `string` | ✓        |\n\n### Built-in Icons\n\nThe Toolbar provides the following built-in icon IDs:\n\n- `'zoom-in'`: Zoom in\n- `'zoom-out'`: Zoom out\n- `'redo'`: Redo\n- `'undo'`: Undo\n- `'edit'`: Edit\n- `'delete'`: Delete\n- `'auto-fit'`: Auto-fit view\n- `'export'`: Export chart\n- `'reset'`: Reset view\n- `'request-fullscreen'`: Request fullscreen\n- `'exit-fullscreen'`: Exit fullscreen\n\n### Custom Icons\n\nIn addition to using built-in icons, you can also use custom icons by introducing third-party icon libraries (such as Alibaba iconfont):\n\n```js\n// Introduce iconfont script\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // Replace with your iconfont script URL\ndocument.head.appendChild(iconFont);\n\n// Use custom icons in the toolbar\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // Use icons from iconfont\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Note: Custom icon IDs usually start with `icon-` and need to correspond to the icon names in the introduced iconfont.\n\n## Code Examples\n\n### Basic Toolbar\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo, undo need to be used with the history plugin\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### Custom Styles\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Common style attributes include:\n>\n> - `backgroundColor`: Background color\n> - `padding`: Padding\n> - `margin`/`marginTop`/`marginLeft`, etc.: Margin\n> - `border`: Border\n> - `borderRadius`: Border radius\n> - `boxShadow`: Shadow effect\n> - `opacity`: Opacity\n> - `width`/`height`: Width and height (default is content adaptive)\n> - `zIndex`: Layer (default is 100)\n> - `display`: Display mode (default is flex)\n\nThe toolbar container is set to `display: flex` by default, and child items use row layout by default (or change according to the direction configured by position). You can customize its appearance and position through `style`.\n\n### Asynchronous Loading of Toolbar Items\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Toolbar icons not displaying?\n\n- Check if the correct built-in icon ID is used\n- Ensure CSS styles are not overridden or conflicting\n\n### 2. How to use with other plugins?\n\nThe toolbar is often used in conjunction with other plugins (such as history):\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// Update toolbar position\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"Toolbar","order":"15"},"isInternal":false,"tokens":2848,"sizeBytes":11431},{"name":"Toolbar.zh.md","path":"packages/site/docs/manual/plugin/Toolbar.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Toolbar.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 工具栏 Toolbar\norder: 15\n---\n\n## 概述\n\nToolbar 是 G6 中用于提供操作按钮集合的插件，支持放大、缩小、自适应、重置等常用图表操作。通过工具栏，用户可以快速访问图表的常用功能，提高操作效率和用户体验。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 快速访问图表的常用功能\n\n## 基本用法\n\n以下是一个简单的 Toolbar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // 处理按钮点击事件\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                             | 类型                                                                                        | 默认值       | 必选 |\n| --------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type      | 插件类型                                         | string                                                                                      | `toolbar`    | ✓    |\n| key       | 插件唯一标识符，用于后续更新                     | string                                                                                      | -            |      |\n| className | 工具栏DOM元素的额外CSS类名                       | string                                                                                      | -            |      |\n| position  | 工具栏位置，相对于画布，[可选值](#position)      | string                                                                                      | `'top-left'` |      |\n| style     | 工具栏DOM元素的自定义样式，[常用值](#style-属性) | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| getItems  | 返回工具栏项目列表                               | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -            | ✓    |\n| onClick   | 工具栏项目点击后的回调函数                       | (value: string, target: Element) => void                                                    | -            |      |\n\n### position\n\n`position` 参数支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n### style 属性\n\n| 属性            | 描述     | 类型   | 默认值              |\n| --------------- | -------- | ------ | ------------------- |\n| backgroundColor | 背景颜色 | string | `#fff`              |\n| border          | 边框     | string | `1px solid #e8e8e8` |\n| borderRadius    | 圆角     | string | `4px`               |\n| height          | 高度     | string | `auto`              |\n| margin          | 外边距   | string | `12px`              |\n| opacity         | 透明度   | number | 0.9                 |\n| padding         | 内边距   | string | `8px`               |\n| width           | 宽度     | string | `auto`              |\n\n### ToolbarItem\n\n每个工具栏项目 (ToolbarItem) 包含以下属性：\n\n| 属性  | 描述                                            | 类型     | 必选 |\n| ----- | ----------------------------------------------- | -------- | ---- |\n| id    | 项目的图标ID，内置图标ID见[内置图标](#内置图标) | `string` | ✓    |\n| value | 点击项目时返回的值                              | `string` | ✓    |\n\n### 内置图标\n\nToolbar 提供以下内置图标 ID：\n\n- `'zoom-in'`：放大\n- `'zoom-out'`：缩小\n- `'redo'`：重做\n- `'undo'`：撤销\n- `'edit'`：编辑\n- `'delete'`：删除\n- `'auto-fit'`：自适应视图\n- `'export'`：导出图表\n- `'reset'`：重置视图\n- `'request-fullscreen'`：请求全屏\n- `'exit-fullscreen'`：退出全屏\n\n### 自定义图标\n\n除了使用内置图标外，还可以通过引入第三方图标库（如阿里巴巴 iconfont）来使用自定义图标：\n\n```js\n// 引入 iconfont 脚本\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // 替换为你的 iconfont 脚本地址\ndocument.head.appendChild(iconFont);\n\n// 在工具栏中使用自定义图标\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // 使用 iconfont 中的图标\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 注意：自定义图标的 ID 通常以 `icon-` 开头，需要与引入的 iconfont 中的图标名称对应。\n\n## 代码示例\n\n### 基础工具栏\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo、undo 需要配合 history 插件使用\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### 自定义样式\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 常用的样式属性包括：\n>\n> - `backgroundColor`：背景颜色\n> - `padding`：内边距\n> - `margin`/`marginTop`/`marginLeft` 等：外边距\n> - `border`：边框\n> - `borderRadius`：圆角\n> - `boxShadow`：阴影效果\n> - `opacity`：透明度\n> - `width`/`height`：宽高（默认自适应内容）\n> - `zIndex`：层级（默认为 100）\n> - `display`：显示方式（默认为 flex）\n\n工具栏容器默认设置 `display: flex`，子项目默认使用行布局（或根据 position 配置的方向改变）。你可以通过 `style` 自定义其外观和位置。\n\n### 异步加载工具栏项\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 工具栏图标不显示？\n\n- 检查是否使用了正确的内置图标 ID\n- 确保 CSS 样式未被覆盖或冲突\n\n### 2. 如何结合其他插件使用？\n\n工具栏常常与其他插件（如历史记录）配合使用：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// 更新工具栏位置\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"工具栏 Toolbar","order":"15"},"isInternal":false,"tokens":2268,"sizeBytes":10768},{"name":"Tooltip.en.md","path":"packages/site/docs/manual/plugin/Tooltip.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Tooltip.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Tooltip\norder: 16\n---\n\n## Overview\n\nThe Tooltip plugin is used to display additional information when users hover over or click on elements in the graph. It helps users better understand the data in the graph and improves the interactive experience.\n\n## Use Cases\n\n- **Detailed Information Display**: When users need to understand detailed information about elements, use Tooltip to display this information\n- **Data Visualization Assistance**: In data visualization, Tooltip can display detailed information about data points in charts, helping users better understand the data\n- **Interactive Feedback**: Provide immediate visual feedback for user mouse operations\n\n## Basic Usage\n\nThe simplest Tooltip plugin configuration:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property     | Description               | Type                                                                                                                                          | Default Value                         | Required |\n| ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------- |\n| type         | Plugin type               | string                                                                                                                                        | `tooltip`                             | ✓        |\n| key          | Identifier                | string                                                                                                                                        | -                                     |          |\n| position     | Tooltip position          | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                                        | `top-right`                           |          |\n| enable       | Whether plugin is enabled | boolean \\| ((event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |          |\n| getContent   | Custom content            | (event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |          |\n| onOpenChange | Show/hide callback        | (open: boolean) => void                                                                                                                       | -                                     |          |\n| trigger      | Trigger behavior          | `hover` \\| `click`                                                                                                                            | `hover`                               |\n| container    | Custom render container   | string \\| HTMLElement                                                                                                                         | -                                     |          |\n| offset       | Offset distance           | [number,number]                                                                                                                               | [10,10]                               |          |\n| enterable    | Whether pointer can enter | boolean                                                                                                                                       | false                                 |          |\n| title        | Title                     | string                                                                                                                                        | -                                     |\n| style        | Style object              | Record<string,any>                                                                                                                            | {'.tooltip': { visibility: 'hidden'}} |          |\n\n## Detailed Configuration\n\n### enable - Conditional Enable\n\nControls whether the plugin is enabled, supports passing functions to dynamically adjust enable logic.\n\n**Example: Enable Tooltip only for nodes**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Server Node' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Database Node' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: 'Connection' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // Enable only for nodes, not for edges\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>Node: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - Custom Content\n\nCustomize Tooltip content rendering, supports returning HTMLElement or string.\n\n**Example: Dynamically render custom HTML content**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: 'Server A', type: 'Application Server', status: 'Running', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: 'Database B', type: 'MySQL Database', status: 'Normal', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Type:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Status:</strong>\n                <span style=\"color: ${item.data.status === 'Running' || item.data.status === 'Normal' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Memory:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Connections:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Size:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">Connection Info</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Bandwidth:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Latency:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return 'No information available';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - Trigger Mode\n\nControls the trigger behavior of Tooltip.\n\n**Available values:**\n\n- `hover`: Trigger when mouse enters element (default)\n- `click`: Trigger when mouse clicks element\n\n**Example: Click-triggered Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Click me' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Click me too' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              Click Triggered 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              Element ID: ${items[0].id}<br/>\n              Name: ${items[0].data?.name || 'Unnamed'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - Display Position\n\nControls the display position of Tooltip relative to mouse position.\n\n**Available values:**\n\n- `top`: Top\n- `bottom`: Bottom\n- `left`: Left\n- `right`: Right\n- `top-left`: Top left\n- `top-right`: Top right (default)\n- `bottom-left`: Bottom left\n- `bottom-right`: Bottom right\n\n**Example: Tooltips at different positions**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Display at top ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Display at bottom ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `Display at left ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `Display at right ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - Offset\n\nSet the offset for Tooltip display position, with mouse position as the base point.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'Default offset' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'Custom offset' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Default offset [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // Offset 30px to the right, 10px up\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Custom offset [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - Mouse Enterable\n\nControls whether the mouse pointer can enter the tooltip box, commonly used for scenarios requiring interaction within the Tooltip.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'User A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: 'User B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">User Actions</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>Name:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>Email:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('Send message to ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Message\n              </button>\n              <button onclick=\"alert('View ${item.data.name} details')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Details\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - Style Customization\n\nCustomize Tooltip styles.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: 'Dark Theme' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: 'Light Theme' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Basic Tooltip](/en/examples/plugin/tooltip/#basic)\n- [Click-triggered Tooltip](/en/examples/plugin/tooltip/#click)\n- [Different tooltips for hover and click on the same element](/en/examples/plugin/tooltip/#dual)\n- [Custom styled Tooltip](/en/examples/plugin/tooltip/#custom-style)\n- [Asynchronous content loading Tooltip](/en/examples/plugin/tooltip/#async)\n\n## API\n","frontmatter":{"title":"Tooltip","order":"16"},"isInternal":false,"tokens":4033,"sizeBytes":16159},{"name":"Tooltip.zh.md","path":"packages/site/docs/manual/plugin/Tooltip.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Tooltip.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 提示框 Tooltip\norder: 16\n---\n\n## 概述\n\nTooltip 插件用于在用户将鼠标悬停或点击图中的元素时，显示额外的信息。它可以帮助用户更好地理解图中的数据，提高交互体验。\n\n## 使用场景\n\n- **详细信息展示**：当用户需要了解元素的详细信息时，使用 Tooltip 提示框来展示这些信息\n- **数据可视化辅助**：在数据可视化中，Tooltip 可以显示图表中数据点的详细信息，帮助用户更好地理解数据\n- **交互反馈**：为用户的鼠标操作提供即时的视觉反馈\n\n## 基本使用\n\n最简单的 Tooltip 插件配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性         | 描述                    | 类型                                                                                                                            | 默认值                                | 必选 |\n| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ---- |\n| type         | 插件类型                | string                                                                                                                          | `tooltip`                             | ✓    |\n| key          | 标识符                  | string                                                                                                                          | -                                     |      |\n| position     | 气泡框位置              | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                          | `top-right`                           |      |\n| enable       | 插件是否启用            | boolean \\| ((event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |      |\n| getContent   | 自定义内容              | (event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |      |\n| onOpenChange | 显示隐藏的回调          | (open: boolean) => void                                                                                                         | -                                     |      |\n| trigger      | 触发行为                | `hover` \\| `click`                                                                                                              | `hover`                               |\n| container    | tooltip自定义渲染的容器 | string \\| HTMLElement                                                                                                           | -                                     |      |\n| offset       | 偏移距离                | [number,number]                                                                                                                 | [10,10]                               |      |\n| enterable    | 指针是否可以进入        | boolean                                                                                                                         | false                                 |      |\n| title        | 标题                    | string                                                                                                                          | -                                     |\n| style        | 样式对象                | Record<string,any>                                                                                                              | {'.tooltip': { visibility: 'hidden'}} |      |\n\n## 详细配置说明\n\n### enable - 条件启用\n\n控制插件是否启用，支持传入函数动态调整启用逻辑。\n\n**示例：只对节点启用 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '服务器节点' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '数据库节点' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: '连接线' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // 只对节点启用，边不显示tooltip\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>节点: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - 自定义内容\n\n自定义渲染 Tooltip 内容，支持返回 HTMLElement 或 string。\n\n**示例：动态渲染自定义 HTML 内容**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: '服务器A', type: '应用服务器', status: '运行中', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: '数据库B', type: 'MySQL数据库', status: '正常', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>类型:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>状态:</strong>\n                <span style=\"color: ${item.data.status === '运行中' || item.data.status === '正常' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>内存:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>连接数:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>大小:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">连接信息</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>带宽:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>延迟:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return '暂无信息';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - 触发方式\n\n控制 Tooltip 的触发行为。\n\n**可选值：**\n\n- `hover`：鼠标移入元素时触发（默认）\n- `click`：鼠标点击元素时触发\n\n**示例：点击触发 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '点击我' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '也点击我' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              点击触发 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              元素ID: ${items[0].id}<br/>\n              名称: ${items[0].data?.name || '未命名'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - 显示位置\n\n控制 Tooltip 相对于鼠标位置的显示位置。\n\n**可选值：**\n\n- `top`: 顶部\n- `bottom`: 底部\n- `left`: 左侧\n- `right`: 右侧\n- `top-left`: 顶部靠左\n- `top-right`: 顶部靠右（默认）\n- `bottom-left`: 底部靠左\n- `bottom-right`: 底部靠右\n\n**示例：不同位置的 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `顶部显示 ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `底部显示 ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `左侧显示 ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `右侧显示 ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - 偏移量\n\n设置 Tooltip 显示位置的偏移量，以鼠标位置为基点。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: '默认偏移' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: '自定义偏移' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `默认偏移 [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // 向右偏移30px，向上偏移10px\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `自定义偏移 [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - 鼠标可进入\n\n控制鼠标指针是否可以进入气泡框，常用于需要在 Tooltip 内进行交互的场景。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '用户A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: '用户B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">用户操作</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>姓名:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>邮箱:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('发送消息给 ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                发消息\n              </button>\n              <button onclick=\"alert('查看 ${item.data.name} 的详情')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                详情\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - 样式自定义\n\n自定义 Tooltip 的样式。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: '深色主题' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: '浅色主题' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [基础提示框](/examples/plugin/tooltip/#basic)\n- [点击触发 Tooltip](/examples/plugin/tooltip/#click)\n- [鼠标移入和点击同一元素时显示不同的提示框](/examples/plugin/tooltip/#dual)\n- [自定义样式的 Tooltip](/examples/plugin/tooltip/#custom-style)\n- [异步加载内容的 Tooltip](/examples/plugin/tooltip/#async)\n","frontmatter":{"title":"提示框 Tooltip","order":"16"},"isInternal":false,"tokens":3549,"sizeBytes":15688},{"name":"Watermark.en.md","path":"packages/site/docs/manual/plugin/Watermark.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Watermark.en.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Watermark\norder: 17\n---\n\n## Overview\n\nThe watermark plugin supports using text and images as watermarks. The principle is to add a `background-image` attribute to the div of the Graph container, and then control the position and style of the watermark through CSS. For text watermarks, a hidden canvas is used to convert the text into an image.\n\n## Use Cases\n\n- Add copyright or ownership marks to charts\n- Mark the status of charts during presentations or previews\n- Add anti-leakage marks to sensitive data\n\n## Basic Usage\n\nBelow is a simple example of initializing the Watermark plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // Watermark text\n      opacity: 0.2, // Opacity\n      rotate: Math.PI / 12, // Rotation angle\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## Configuration Options\n\n| Property             | Description                                              | Type                                                                        | Default Value | Required |\n| -------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | -------- |\n| type                 | Plugin type                                              | string                                                                      | `watermark`   | ✓        |\n| width                | Width of a single watermark                              | number                                                                      | 200           |          |\n| height               | Height of a single watermark                             | number                                                                      | 100           |          |\n| opacity              | Opacity of the watermark                                 | number                                                                      | 0.2           |          |\n| rotate               | Rotation angle of the watermark                          | number                                                                      | Math.PI / 12  |          |\n| imageURL             | Image watermark URL, higher priority than text watermark | string                                                                      | -             |          |\n| text                 | Watermark text content                                   | string                                                                      | -             |          |\n| textFill             | Color of the text watermark                              | string                                                                      | `#000`        |          |\n| textFontSize         | Font size of the text watermark                          | number                                                                      | 16            |          |\n| textFontFamily       | Font of the text watermark                               | string                                                                      | -             |          |\n| textFontWeight       | Font weight of the text watermark                        | string                                                                      | -             |          |\n| textFontVariant      | Font variant of the text watermark                       | string                                                                      | -             |          |\n| textAlign            | Text alignment of the watermark                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`      |          |\n| textBaseline         | Baseline alignment of the text watermark                 | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`      |          |\n| backgroundRepeat     | Repeat mode of the watermark                             | string                                                                      | `repeat`      |          |\n| backgroundAttachment | Background attachment behavior of the watermark          | string                                                                      | -             |          |\n| backgroundBlendMode  | Background blend mode of the watermark                   | string                                                                      | -             |          |\n| backgroundClip       | Background clip of the watermark                         | string                                                                      | -             |          |\n| backgroundColor      | Background color of the watermark                        | string                                                                      | -             |          |\n| backgroundImage      | Background image of the watermark                        | string                                                                      | -             |          |\n| backgroundOrigin     | Background origin of the watermark                       | string                                                                      | -             |          |\n| backgroundPosition   | Background position of the watermark                     | string                                                                      | -             |          |\n| backgroundPositionX  | Horizontal position of the watermark background          | string                                                                      | -             |          |\n| backgroundPositionY  | Vertical position of the watermark background            | string                                                                      | -             |          |\n| backgroundSize       | Background size of the watermark                         | string                                                                      | -             |          |\n\n## Code Examples\n\n### Text Watermark\n\nThe simplest text watermark configuration:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Image Watermark\n\nUse an image as a watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style and position of the watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // Set font size\n      textFontFamily: 'Arial', // Set font\n      textFontWeight: 'bold', // Set font weight\n      textFill: '#1890ff', // Set text color\n      rotate: Math.PI / 6, // Set rotation angle\n      opacity: 0.15, // Set opacity\n      width: 180, // Set watermark width\n      height: 100, // Set watermark height\n      backgroundRepeat: 'space', // Set repeat mode\n      backgroundPosition: 'center', // Set position\n      textAlign: 'center', // Set text alignment\n      textBaseline: 'middle', // Set baseline alignment\n    },\n  ],\n});\n```\n\n## Real Cases\n\n- [Text Watermark](/examples/plugin/watermark/#text)\n- [Image Watermark](/examples/plugin/watermark/#repeat)\n","frontmatter":{"title":"Watermark","order":"17"},"isInternal":false,"tokens":2348,"sizeBytes":9391},{"name":"Watermark.zh.md","path":"packages/site/docs/manual/plugin/Watermark.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/plugin/Watermark.zh.md","title":"Plugin Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 水印 Watermark\norder: 17\n---\n\n## 概述\n\n水印插件支持使用文本和图片作为水印，实现原理是在 Graph 容器的 div 上加上 `background-image` 属性，然后通过 CSS 来控制水印的位置和样式。对于文本水印，会使用隐藏 canvas 将文本转换为图片的方式来实现。\n\n## 使用场景\n\n- 为图表添加版权或所有权标识\n- 在演示或预览时标记图表的状态\n- 为敏感数据添加防泄露标记\n\n## 基本用法\n\n以下是一个简单的 Watermark 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // 水印文本\n      opacity: 0.2, // 透明度\n      rotate: Math.PI / 12, // 旋转角度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## 配置项\n\n| 属性                 | 描述                               | 类型                                                                        | 默认值       | 必选 |\n| -------------------- | ---------------------------------- | --------------------------------------------------------------------------- | ------------ | ---- |\n| type                 | 插件类型                           | string                                                                      | `watermark`  | ✓    |\n| width                | 单个水印的宽度                     | number                                                                      | 200          |      |\n| height               | 单个水印的高度                     | number                                                                      | 100          |      |\n| opacity              | 水印的透明度                       | number                                                                      | 0.2          |      |\n| rotate               | 水印的旋转角度                     | number                                                                      | Math.PI / 12 |      |\n| imageURL             | 图片水印的地址，优先级高于文本水印 | string                                                                      | -            |      |\n| text                 | 水印文本内容                       | string                                                                      | -            |      |\n| textFill             | 文本水印的颜色                     | string                                                                      | `#000`       |      |\n| textFontSize         | 文本水印的字体大小                 | number                                                                      | 16           |      |\n| textFontFamily       | 文本水印的字体                     | string                                                                      | -            |      |\n| textFontWeight       | 文本水印的字体粗细                 | string                                                                      | -            |      |\n| textFontVariant      | 文本水印的字体变体                 | string                                                                      | -            |      |\n| textAlign            | 文本水印的对齐方式                 | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`     |      |\n| textBaseline         | 文本水印的基线对齐方式             | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`     |      |\n| backgroundRepeat     | 水印的重复方式                     | string                                                                      | `repeat`     |      |\n| backgroundAttachment | 水印的背景定位行为                 | string                                                                      | -            |      |\n| backgroundBlendMode  | 水印的背景混合模式                 | string                                                                      | -            |      |\n| backgroundClip       | 水印的背景裁剪                     | string                                                                      | -            |      |\n| backgroundColor      | 水印的背景颜色                     | string                                                                      | -            |      |\n| backgroundImage      | 水印的背景图片                     | string                                                                      | -            |      |\n| backgroundOrigin     | 水印的背景原点                     | string                                                                      | -            |      |\n| backgroundPosition   | 水印的背景位置                     | string                                                                      | -            |      |\n| backgroundPositionX  | 水印的背景水平位置                 | string                                                                      | -            |      |\n| backgroundPositionY  | 水印的背景垂直位置                 | string                                                                      | -            |      |\n| backgroundSize       | 水印的背景大小                     | string                                                                      | -            |      |\n\n## 代码示例\n\n### 文本水印\n\n最简单的文本水印配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 图片水印\n\n使用图片作为水印：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义水印的样式和位置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // 设置字体大小\n      textFontFamily: 'Arial', // 设置字体\n      textFontWeight: 'bold', // 设置字体粗细\n      textFill: '#1890ff', // 设置文字颜色\n      rotate: Math.PI / 6, // 设置旋转角度\n      opacity: 0.15, // 设置透明度\n      width: 180, // 设置水印宽度\n      height: 100, // 设置水印高度\n      backgroundRepeat: 'space', // 设置重复方式\n      backgroundPosition: 'center', // 设置位置\n      textAlign: 'center', // 设置文本对齐\n      textBaseline: 'middle', // 设置基线对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n- [文本水印](/examples/plugin/watermark/#text)\n- [图片水印](/examples/plugin/watermark/#repeat)\n","frontmatter":{"title":"水印 Watermark","order":"17"},"isInternal":false,"tokens":1945,"sizeBytes":8786},{"name":"custom-palette.en.md","path":"packages/site/docs/manual/theme/custom-palette.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/custom-palette.en.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Palette\norder: 4\n---\n\n## Overview\n\n[Core Concepts - Palette](/en/manual/core-concept/palette) mentions that G6 supports discrete palettes and continuous palettes. A discrete palette is essentially an array of colors, while a continuous palette is a color interpolator.\n\nTherefore, customizing a palette also adopts these two methods, and the following sections will introduce how to customize discrete and continuous palettes, respectively.\n\n## Implement Palette\n\n### Discrete Palette\n\nYou can simply define a string array that contains color values. Supported color values include: RGB color values, hexadecimal color values, and color names. Below is an example of a discrete palette:\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### Continuous Palette\n\nA continuous palette requires the definition of a color interpolator. The interpolator is a function that accepts a numerical value as a parameter and returns a color value. Below is an example of a continuous palette:\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can register a palette using the `register` method provided by G6. For more details, please refer to [Register Palette](/en/manual/core-concept/palette#register-palette)\n\n## Use Without Registration\n\nIn addition to registration, you can also bypass the registration mechanism and directly pass the palette value at the location where the palette is needed, for example:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // Pass in a color array.\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Pass in an interpolator\n    }\n  }\n}\n```\n","frontmatter":{"title":"Custom Palette","order":"4"},"isInternal":false,"tokens":485,"sizeBytes":1939},{"name":"custom-palette.zh.md","path":"packages/site/docs/manual/theme/custom-palette.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/custom-palette.zh.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义色板\norder: 4\n---\n\n## 概述\n\n[色板](/manual/theme/palette) 中提到，G6 支持离散色板和连续色板，其中离散色板本质上是一个颜色数组，而连续色板是一个颜色插值器。\n\n因此自定义色板也采用这两种方式，下面分别介绍如何自定义离散色板和连续色板。\n\n## 实现色板\n\n### 离散色板\n\n直接定义一个包含颜色值的字符串数组即可，颜值值支持：RGB 色值、16 进制、颜色名，下面是一组离散色板示例：\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### 连续色板\n\n连续色板需要定义一个颜色插值器，插值器是一个函数，接受一个数值参数，返回一个颜色值，下面是一个连续色板示例：\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n通过 G6 提供的 register 方法注册即可，详见[注册色板](/manual/theme/palette#注册色板)\n\n## 非注册方式使用\n\n除此之外，你也可以在需要使用色板的位置跳过注册机制直接传入色板值，例如：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // 传入颜色数组\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 传入插值器\n    }\n  }\n}\n```\n","frontmatter":{"title":"自定义色板","order":"4"},"isInternal":false,"tokens":246,"sizeBytes":1555},{"name":"custom-theme.en.md","path":"packages/site/docs/manual/theme/custom-theme.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/custom-theme.en.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Theme\norder: 2\n---\n\n## Overview\n\nIn G6, the theme is a subset of Graph Options and includes configurations related to the canvas and element styles. A theme can help you quickly switch between different graph styles.\n\n## Custom Theme\n\nFor element styles, the configurations within a theme are static and do not support the use of callback functions to dynamically calculate styles. Additionally, `type` is also not supported for configuration within a theme. A theme includes the following configurations:\n\n- `background`: Canvas background color\n- `node`: Node style\n- `edge`: Edge style\n- `combo`: Combo style\n\nBelow is a simple example of a theme configuration:\n\n```typescript\nconst theme = {\n  background: '#fff',\n  node: {\n    style: {\n      fill: '#e1f3fe',\n      lineWidth: 0,\n    },\n    selected: {\n      style: {\n        fill: '#3b71d6',\n        lineWidth: 1,\n      },\n    },\n  },\n  edge: {\n    // ...\n  },\n  combo: {\n    // ...\n  },\n};\n```\n\n❌ Incorrect Example\n\n```typescript\nconst theme = {\n  node: {\n    // ❌ The theme does not support configuring element types\n    type: 'rect',\n    style: {\n      // ❌ The theme does not support callback functions\n      fill: (d) => d.style.color,\n    },\n  },\n};\n```\n\n:::warning{title=Note}\nFor element state styles, please ensure that every property in the state style has a corresponding default style in the default style, otherwise it may result in the inability to clear the state style.\n:::\n\n## Register Theme\n\nYou can register a theme using the `register` method provided by G6. Here is an example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.THEME, 'custom-theme', theme);\n```\n\n## Configure Theme\n\nTo enable and configure a theme, you need to pass the `theme` option when instantiating the `Graph`:\n\n```typescript\n{\n  theme: 'custom-theme',\n}\n```\n\n### Switch Theme\n\nAfter the `Graph` instance is created, you can switch themes by using the [setTheme](/en/api/theme#graphsetthemetheme) method:\n\n```typescript\ngraph.setTheme('dark');\n```\n\nAdditionally, you can also obtain the current theme by using the `getTheme` method:\n\n```typescript\ngraph.getTheme();\n// => 'dark'\n```\n","frontmatter":{"title":"Custom Theme","order":"2"},"isInternal":false,"tokens":550,"sizeBytes":2206},{"name":"custom-theme.zh.md","path":"packages/site/docs/manual/theme/custom-theme.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/custom-theme.zh.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义主题\norder: 2\n---\n\n除了使用内置主题外，G6 还支持创建自定义主题来满足特定的视觉需求。本文将介绍如何创建和使用自定义主题。\n\n## 创建自定义主题\n\n一个自定义主题需要遵循主题的基本结构，包含画布背景色和元素样式配置：\n\n```javascript\nconst customTheme = {\n  // 1. 画布背景色\n  background: '#f0f0f0',\n\n  // 2. 节点配置\n  node: {\n    // 调色板配置\n    palette: {\n      type: 'group',\n      color: ['#1783FF', '#00C9C9' /* 自定义颜色... */],\n    },\n    // 基础样式\n    style: {\n      fill: '#fff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他节点样式\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#e8f3ff',\n        stroke: '#1783FF',\n      },\n      // ... 其他状态样式\n    },\n  },\n\n  // 3. 边配置\n  edge: {\n    style: {\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他边样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n\n  // 4. Combo 配置\n  combo: {\n    style: {\n      fill: '#f7f7f7',\n      stroke: '#d9d9d9',\n      // ... 其他 Combo 样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n};\n```\n\n## 使用限制\n\n在创建自定义主题时，需要注意以下限制：\n\n1. **仅支持静态值**\n\n   ```javascript\n   // ❌ 错误示例：不支持回调函数\n   const theme = {\n     node: {\n       style: {\n         fill: (d) => d.style.color,\n       },\n     },\n   };\n   ```\n\n2. **不支持配置元素类型**\n\n   ```javascript\n   // ❌ 错误示例：不支持在主题中配置元素类型\n   const theme = {\n     node: {\n       type: 'rect',\n       style: {\n         fill: '#fff',\n       },\n     },\n   };\n   ```\n\n3. **状态样式需要对应默认样式**\n   ```javascript\n   // ✅ 正确示例：状态样式的属性在默认样式中都有定义\n   const theme = {\n     node: {\n       style: {\n         fill: '#fff',\n         stroke: '#000',\n       },\n       state: {\n         selected: {\n           fill: '#e8f3ff',\n           stroke: '#1783FF',\n         },\n       },\n     },\n   };\n   ```\n\n## 应用自定义主题\n\n先注册主题，然后通过名称引用：\n\n```javascript\n// 1. 注册主题\nimport { register, ExtensionCategory } from '@antv/g6';\nregister(ExtensionCategory.THEME, 'custom-theme', customTheme);\n\n// 2. 使用主题\nconst graph = new Graph({\n  theme: 'custom-theme',\n  // ... 其他配置\n});\n```\n","frontmatter":{"title":"自定义主题","order":"2"},"isInternal":false,"tokens":469,"sizeBytes":2464},{"name":"overview.en.md","path":"packages/site/docs/manual/theme/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/overview.en.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Theme Overview\norder: 1\n---\n\n## Overview\n","frontmatter":{"title":"Theme Overview","order":"1"},"isInternal":false,"tokens":13,"sizeBytes":52},{"name":"overview.zh.md","path":"packages/site/docs/manual/theme/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/overview.zh.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 主题总览\norder: 1\n---\n\n## 概述\n\nG6 中的主题是 Graph Options 的子集，它包含了关于画布和元素样式的配置。多主题可以帮助你快速地切换不同的图样式。\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 主题结构\n\n一个主题由以下四个部分组成：\n\n1. **画布背景色 (background)**\n\n   - 控制整个画布的背景颜色\n\n2. **节点配置 (node)**\n\n   - 基础样式：填充色、描边、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于节点分组的颜色配置\n   - 状态样式：不同状态下的样式配置（选中、激活、禁用等）\n   - 动画配置：节点的动画效果配置\n\n3. **边配置 (edge)**\n\n   - 基础样式：线条样式、箭头、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于边分组的颜色配置\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：边的动画效果配置\n\n4. **Combo 配置 (combo)**\n   - 基础样式：填充、描边、折叠按钮等静态视觉属性\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：Combo 的动画效果配置\n\n> 注意：主题中的样式配置仅支持静态值，不支持回调函数形式的动态配置。如需动态样式，请使用图的配置项。\n\n## 内置主题\n\nG6 默认提供两种内置主题：\n\n### 亮色主题（默认）\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SPCES62UzzAAAAAAAAAAAAAAemJ7AQ/original\" alt=\"亮色主题\" />\n\n<details><summary>查看亮色主题完整配置项</summary>\n\n```js\nconst lightTheme = {\n  background: '#ffffff',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#000000',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#000000',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#000000',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fillOpacity: 0.25,\n        iconOpacity: 0.85,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.06,\n        fill: '#1B324F',\n        fillOpacity: 0.06,\n        iconFill: '#1B324F',\n        iconOpacity: 0.25,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.06,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#99ADD1',\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#99ADD1',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#99ADD1',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#1B324F',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#d9d9d9',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#ffffff',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#99ADD1',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99ADD1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99ADD1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d9d9d9',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#d9d9d9',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n### 暗色主题\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*qTlLSoAbaXYAAAAAAAAAAAAAemJ7AQ/original\" alt=\"暗色主题\" />\n\n<details><summary>查看暗色主题完整配置项</summary>\n\n```js\nconst darkTheme = {\n  background: '#000000',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#ffffff',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#d0e4ff',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#d0e4ff',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.45,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.25,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.45,\n        donutOpacity: 0.45,\n        fillOpacity: 0.45,\n        iconOpacity: 0.45,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.45,\n        strokeOpacity: 0.45,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fill: '#D0E4FF',\n        fillOpacity: 0.25,\n        iconFill: '#D0E4FF',\n        iconOpacity: 0.25,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#637088',\n        '#0F55A6',\n        '#008383',\n        '#9C5D38',\n        '#8B53A6',\n        '#4E40A6',\n        '#8F6608',\n        '#3E801D',\n        '#A65383',\n        '#175E75',\n        '#0F8248',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#637088',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#637088',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#D0E4FF',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#637088',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#000000',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#fdfdfd',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99add1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99add1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d0e4ff',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#969696',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n## 使用主题\n\n### 配置主题\n\n在创建图时通过 `theme` 选项指定要使用的主题：\n\n```javascript\nconst graph = new Graph({\n  theme: 'light', // 或 'dark'\n  // ... 其他配置\n});\n```\n\n### 切换主题\n\n创建图后，可以通过 `setTheme` 方法动态切换主题：\n\n```javascript\n// 切换到暗色主题\ngraph.setTheme('dark');\n\n// 获取当前主题\nconst currentTheme = graph.getTheme(); // 'dark'\n```\n\n## 样式优先级\n\n在 G6 中，元素的最终样式由多个层级的样式合并而成，按优先级从低到高排序：\n\n**⭐️ 主题默认样式** < 调色板样式 < 数据样式 < 图的默认样式 < **⭐️ 主题状态样式** < 图的状态样式\n\n详细说明：\n\n1. **主题默认样式**：主题系统提供的基础样式\n2. **调色板样式**：基于主题调色板配置的自动着色样式\n3. **数据样式**：在数据中定义的样式\n4. **图的默认样式**：通过图的配置项设置的样式\n5. **主题状态样式**：主题中定义的状态样式\n6. **图的状态样式**：通过图的配置项设置的状态样式\n\n更多关于自定义主题的内容，请参考[自定义主题](/manual/theme/custom-theme)。\n","frontmatter":{"title":"主题总览","order":"1"},"isInternal":false,"tokens":3498,"sizeBytes":15332},{"name":"palette.en.md","path":"packages/site/docs/manual/theme/palette.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/palette.en.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Palette\norder: 3\n---\n\n## Overview\n\nA palette refers to a set of predefined color collections that help users more conveniently select colors. In G6, a palette is a common option that allows users to configure the colors of elements such as nodes, edges, and links through the palette.\n\nPalettes are divided into two types: `discrete palette` and `continuous palette`.\n\nA discrete palette is an array of colors used to map discrete values within elements to different colors, such as the type of nodes, the relationship of edges, etc. Below is a simple example of a discrete palette:\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\nA continuous palette is an interpolator that takes a value between 0 and 1 and returns the corresponding color. It is used to map continuous values within elements to different colors, such as the degree of nodes, the weight of edges, etc. Below is a simple example of a continuous palette:\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can directly use the built-in palettes, but if you want to use other palettes, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=note}\n\nDuring the process of registering a palette, there is no distinction made between discrete and continuous palettes. It is necessary to ensure the consistency between the palette type and the data type when using the palette.\n:::\n\n### Built-in Palettes\n\nCurrently, G6 has 5 sets of commonly used discrete palettes that users can directly utilize:\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## Configure Palette\n\nCurrently, the configuration of palettes is mainly focused on elements, taking nodes as an example:\n\n### Discrete Palette\n\n1. Default Configuration: By directly setting the value of `palette` to the name of the palette, each node will be assigned a different color by default\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral is the Palette Name\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> When the number of elements exceeds the number of colors in the palette, the colors in the palette will be reused in a cyclic manner.\n\n2. Standard Configuration: The attributes for configuring a discrete palette include: `type: 'group'`, `field`, `color`, `invert`.\n\nAmong them, `type: 'group'` explicitly specifies that the current palette type is a discrete palette; `field` designates the field for grouping in the element data; `color` is the name of the palette; `invert` indicates whether to invert the palette.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\nIn the data, `node-1` and `node-4` belong to category A, `node-2` and `node-5` belong to category B, `node-3` and `node-6` belong to category C.\n\nConfigure the color of the nodes in such a way that nodes of the same category have the same color:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // Specify the palette type as a categorical palette.\n      field: 'category', // Specify the grouping field in the data.\n      color: 'tableau', // Use a Tableau-like palette.\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### Continuous Palette\n\nA continuous palette only supports standard configuration methods, with configuration properties including: `type: 'value'`, `field`, `color`, `invert`.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\nNow, create an interpolator that maps the maximum value to red (`rgb(255, 0, 0)`) and the minimum value to black (`rgb(0, 0, 0)`):\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\nConfigure the following so that the color of the nodes is mapped to different colors based on the value of the `value` field in the data:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // Specify the palette type as a continuous palette\n      field: 'value', // Specify the numerical field in the data\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Use an interpolator\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=note}\n\nThe built-in continuous palette does not support specifying a value range. If there is a need for more complex color mapping, it can be customized within the style mapping.\n:::\n\n## Custom Palette\n\nIf the built-in palette does not meet your requirements, you can customize the palette. For details, please refer to [Custom Palette](/en/manual/custom-extension/palette).\n\n## Priority\n\nThe palette generates styles based on the type of element. For nodes and combos, the color is mapped to the `fill` attribute; for edges, the color is mapped to the `stroke` attribute.\n\nIf both a palette and a style mapping are configured, the style mapping will override the palette colors. In the following example, the color of the nodes is always red:\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","frontmatter":{"title":"Palette","order":"3"},"isInternal":false,"tokens":2182,"sizeBytes":8727},{"name":"palette.zh.md","path":"packages/site/docs/manual/theme/palette.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/theme/palette.zh.md","title":"Theme Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 色板\norder: 3\n---\n\n## 概述\n\n色板(Palette)是指一组预定义的颜色集合，用于帮助用户更方便的选择颜色。在 G6 中，色板是一种常见的配置项，用户可以通过色板来配置节点、边、连线等元素的颜色。\n\n色板分为`离散色板`和`连续色板`两种类型。\n\n离散色板是一组颜色数组，用于将元素中的离散值映射到不同的颜色上，例如节点的类型、边的关系等。下面是一个简单的离散色板示例：\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\n连续色板是一个插值器，输入 0~1 的值，返回对应的颜色，用于将元素中的连续值映射到不同的颜色上，例如节点的度数、边的权重等。下面是一个简单的连续色板示例：\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n你可以直接使用内置色板，如果想使用其他色板，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=注意}\n在注册色板过程中并不会区分离散色板和连续色板，使用色板过程中需要自行保证色板类型和数据类型的一致性。\n:::\n\n### 内置色板\n\n目前 G6 内置了 5 套常用的离散色板，用户可以直接使用：\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## 配置色板\n\n目前开放色板配置的地方主要以元素为主，以节点为例：\n\n### 离散色板\n\n1. 默认配置，直接配置 `palette` 的值为色板名，会默认为每个节点分配不同的颜色\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral 为色板名\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> 当元素数量超过色板颜色数量时，会循环使用色板中的颜色\n\n2. 标准配置，离散色板配置属性包括：`type: 'group'`，`field`，`color`，`invert`\n\n其中 `type: 'group'` 显式指定了当前色板类型为离散色板；`field` 指定元素数据中的分组字段；`color` 为色板名；`invert` 为是否反转色板。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\n数据中 `node-1`，`node-4` 属于 A 类别，`node-2`，`node-5` 属于 B 类别，`node-3`，`node-6` 属于 C 类别。\n\n通过以下方式配置节点的颜色，使得同类别的节点颜色相同：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // 指定色板类型为分类色板\n      field: 'category', // 指定数据中的分组字段\n      color: 'tableau', // 使用 tableau 色板\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### 连续色板\n\n连续色板只支持标准方式配置，配置属性包括：`type: 'value'`，`field`，`color`，`invert`。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\n现在创建一个插值器，将最大值映射为红色(`rgb(255, 0, 0)`)，最小值映射为黑色(`rgb(0, 0, 0)`)：\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\n通过以下配置使得节点的颜色根据数据中的 `value` 字段的值映射到不同的颜色：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // 指定色板类型为连续色板\n      field: 'value', // 指定数据中的数值字段\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 使用插值器\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=注意}\n内置连续色板不支持指定值域范围，如果有更复杂的颜色映射需求，可以在样式映射中自定义\n:::\n\n## 自定义色板\n\n如果内置色板无法满足需求，可以自定义色板，具体请参考[自定义色板](/manual/theme/custom-palette)。\n\n## 优先级\n\n色板会基于元素类型生成样式，对于节点和组合，会将颜色映射到 `fill` 属性；对于边，会将颜色映射到 `stroke` 属性。\n\n如果同时配置了色板和样式映射，样式映射会覆盖色板颜色。下面的例子中，节点的颜色始终为红色：\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n","frontmatter":{"title":"色板","order":"3"},"isInternal":false,"tokens":1530,"sizeBytes":7873},{"name":"custom-transform.en.md","path":"packages/site/docs/manual/transform/custom-transform.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/custom-transform.en.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Custom Transform\norder: 4\n---\n","frontmatter":{"title":"Custom Transform","order":"4"},"isInternal":false,"tokens":11,"sizeBytes":41},{"name":"custom-transform.zh.md","path":"packages/site/docs/manual/transform/custom-transform.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/custom-transform.zh.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 自定义数据处理\norder: 4\n---\n\n## 概述\n\n自定义数据处理允许用户在业务实现过程中，把额外的数据处理封装起来，在渲染前或者布局后对数据进行进一步处理。用户通过自定义数据处理，实现部分数据处理解耦，更好地进行管理、编排代码以及提高代码可维护性。\n\n## 开始前\n\n用户在进行自定义数据处理前，需要仔细阅读并掌握数据处理器的 [实现原理和执行时机](/manual/transform/overview#实现原理) 。\n\n## 代码示例\n\n接下来将讲述两个可能的业务场景，并通过自定义数据处理来实现：\n\n### 不展示游离节点\n\n- **需求**\n\n  游离节点，即没有连线的节点，画布渲染时不展示游离节点\n\n- **实现**\n\n  ```typescript\n  import type { DrawData, DrawContext } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory } from '@antv/g6';\n\n  class HideFreeNode extends BaseTransform {\n    public beforeDraw(input: DrawData, context: DrawContext): DrawData {\n      const { model } = this.context;\n      const { add, update, remove } = input;\n\n      add.nodes.forEach((nodeData, nodeId) => {\n        // 获取节点的相关连线\n        const edges = model.getRelatedEdgesData(nodeId);\n        // 没有任何连线的的节点则从add里面移除，添加到remove里面\n        if (!edges.length) {\n          add.nodes.delete(nodeId);\n          remove.nodes.set(nodeId, nodeData);\n        }\n      });\n\n      return input;\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/hide-free-node.md\"></embed>\n\n- **说明**\n\n  示例中总共有6个节点，id为1-6，id为4的节点没有连线，因此被移除了。\n\n  通过 `getRelatedEdgesData` 获取节点的相关连线，没有则把该节点放到 `remove.nodes` 里面去，并从 `add.nodes` 里面移除。\n\n### 环形布局径向label\n\n- **需求**\n\n  使用 [环形布局](/manual/layout/circular-layout) 时，节点 label 的也需要像内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 一样实现径向展示（但 PlaceRadialLabels 只支持径向布局，环形布局不是径向布局）\n\n- **实现**\n\n  ```typescript\n  import type { RuntimeContext, DrawContext, Point, TransformArray, Vector2, Vector3 } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory, BaseTransformOptions } from '@antv/g6';\n\n  // 目前circular布局没有暴露方法可以获取布局中心，这里简单处理先固定一个，配置circular布局时center与这里保持一致即可\n  const circularCenter = [300, 300];\n\n  // 下面的函数 G6 没有暴露出来，先自行声明\n  function subtract(a: Vector2 | Vector3, b: Vector2 | Vector3): Vector2 | Vector3 {\n    return a.map((v, i) => v - b[i]) as Vector2 | Vector3;\n  }\n  function rad(a: Vector2 | Vector3): number {\n    const [x, y] = a;\n    if (!x && !y) return 0;\n    return Math.atan2(y, x);\n  }\n  function rad2deg(rad: number): number {\n    return rad * (180 / Math.PI);\n  }\n\n  interface CircularRadialLabelsOptions extends BaseTransformOptions {\n    offset?: number; // 偏移量\n  }\n\n  class CircularRadialLabels extends BaseTransform<CircularRadialLabelsOptions> {\n    static defaultOptions = {\n      offset: 5,\n    };\n    constructor(context: RuntimeContext, options: CircularRadialLabelsOptions) {\n      super(context, Object.assign({}, CircularRadialLabels.defaultOptions, options));\n    }\n    get center(): Point {\n      return circularCenter;\n    }\n    public afterLayout() {\n      const { graph, model } = this.context;\n      const data = model.getData();\n      data.nodes?.forEach((datum) => {\n        const radian = rad(subtract([datum.style.x, datum.style.y], this.center));\n        const isLeft = Math.abs(radian) > Math.PI / 2;\n        const isLeaf = !datum.children || datum.children.length === 0;\n        const nodeId = datum.id;\n        const node = this.context.element?.getElement(nodeId);\n        if (!node || !node.isVisible()) return;\n\n        const nodeHalfWidth = graph.getElementRenderStyle(nodeId).size / 2;\n        const offset = (isLeaf ? 1 : -1) * (nodeHalfWidth + this.options.offset);\n\n        const labelTransform: TransformArray = [\n          ['translate', offset * Math.cos(radian), offset * Math.sin(radian)],\n          ['rotate', isLeft ? rad2deg(radian) + 180 : rad2deg(radian)],\n        ];\n\n        model.updateNodeData([\n          {\n            id: datum.id,\n            style: {\n              labelTextAlign: isLeft === isLeaf ? 'right' : 'left',\n              labelTextBaseline: 'middle',\n              labelTransform,\n            },\n          },\n        ]);\n      });\n\n      graph.draw();\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/circular-radial-labels.md\"></embed>\n\n- **说明**\n  上面的实现基本是参考内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 来实现的，区别是这里的实现是通过拿到布局中心来计算偏移和旋转，具体可参考 PlaceRadialLabels 的 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/place-radial-labels.ts)\n","frontmatter":{"title":"自定义数据处理","order":"4"},"isInternal":false,"tokens":1046,"sizeBytes":5186},{"name":"MapNodeSize.en.md","path":"packages/site/docs/manual/transform/MapNodeSize.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/MapNodeSize.en.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: MapNodeSize\norder: 1\n---\n\nIn graph visualization, the size of a node is usually used to convey the importance or influence of the node. By adjusting the size of the node based on the centrality of the node, we can more intuitively show the importance of each node in the network, helping users better understand and analyze complex network structures.\n\n## Options\n\n### centrality\n\n> [NodeCentralityOptions](#nodecentralityoptions) _\\| ((graphData:_ [GraphData](/manual/core-concept/data#图数据graphdata)_) =>_ _Map**&lt;**string, number>)_ **Default:** `type: 'eigenvector'`\n\nThe method of measuring the node centrality\n\n- `'degree'`: Degree centrality, measures centrality by the degree (number of connected edges) of a node. Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measures centrality by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measures centrality by the reciprocal of the average shortest path length from a node to all other nodes. Nodes with high closeness centrality usually can reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measures centrality by the degree of connection between a node and other central nodes. Nodes with high eigenvector centrality usually connect to other important nodes\n- `'pagerank'`: PageRank centrality, measures centrality by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to the page ranking algorithm\n- Custom centrality calculation method: `(graphData: GraphData) => Map<ID, number>`, where `graphData` is the graph data, and `Map<ID, number>` is the mapping from node ID to centrality value\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n### mapLabelSize\n\n> _boolean \\| [number, number]_ **Default:** `false`\n\nWhether to map label size synchronously\n\n### maxSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `80`\n\nThe maximum size of the node\n\n### minSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `20`\n\nThe minimum size of the node\n\n### scale\n\n> _'linear' \\| 'log' \\| 'pow' \\| 'sqrt' \\| ((value: number, domain: [number, number], range: [number, number]) => number)_ **Default:** `'log'`\n\nScale type\n\n- `'linear'`: Linear scale, maps a value from one range to another range linearly, commonly used for cases where the difference in centrality values is small\n\n- `'log'`: Logarithmic scale, maps a value from one range to another range logarithmically, commonly used for cases where the difference in centrality values is large\n\n- `'pow'`: Power-law scale, maps a value from one range to another range using power law, commonly used for cases where the difference in centrality values is large\n\n- `'sqrt'`: Square root scale, maps a value from one range to another range using square root, commonly used for cases where the difference in centrality values is large\n\n- Custom scale: `(value: number, domain: [number, number], range: [number, number]) => number`，where `value` is the value to be mapped, `domain` is the input range, and `range` is the output range\n","frontmatter":{"title":"MapNodeSize","order":"1"},"isInternal":false,"tokens":954,"sizeBytes":3822},{"name":"MapNodeSize.zh.md","path":"packages/site/docs/manual/transform/MapNodeSize.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/MapNodeSize.zh.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 动态调整节点大小 MapNodeSize\norder: 1\n---\n\n## 概述\n\n在图可视化中，节点的大小通常用于传达节点的重要性或影响力。通过根据节点中心性调整节点的大小，我们可以更直观地展示网络中各个节点的重要性，从而帮助用户更好地理解和分析复杂的网络结构。\n\n## 使用场景\n\n需要通过节点大小来突出节点的重要性和影响力时，可使用此数据处理。\n\n以下为常见的场景：\n\n- **社交网络分析**：比如分析社交媒体平台中用户的活跃度与影响力，通过节点大小突出高互动用户。\n\n- **金融风险传导网络**：比如识别金融系统中承担关键资金流转职能的机构，预防系统性风险。\n\n- **交通枢纽规划**：比如优化城市地铁网络设计，识别换乘压力点。\n\n## 配置项\n\n| 属性         | 描述                                                       | 类型                                                                                                                               | 默认值               | 必选 |\n| ------------ | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type         | 数据处理类型                                               | map-node-size                                                                                                                      | -                    | ✓    |\n| centrality   | 节点中心性的度量方法，[配置项](#centrality)                | [NodeCentralityOptions](#nodecentralityoptions) \\| ((graphData: [GraphData](/manual/data#图数据graphdata)) => Map<string, number>) | `{ type: 'degree' }` |      |\n| mapLabelSize | 是否同步调整标签大小                                       | boolean \\| [number, number]                                                                                                        | false                |      |\n| maxSize      | 节点最大尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 80                   |      |\n| minSize      | 节点最小尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 20                   |      |\n| scale        | 插值函数，用于将节点中心性映射到节点大小，[配置项](#scale) | `linear` \\| `log` \\| `pow` \\| `sqrt` \\| ((value: number, domain: [number, number], range: [number, number]) => number)             | `log`                |      |\n\n### centrality\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n- 自定义中心性计算方法：`(graphData: GraphData) => Map<ID, number>`，其中 `graphData` 为图数据，`Map<ID, number>` 为节点 ID 到中心性值的映射\n\n**示例：**\n\n```typescript {6-9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n        direction: 'both',\n      },\n    },\n  ],\n});\n```\n\n效果如下（可切换度量方法查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-centrality.md\"></embed>\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n`direction`：表示统计哪些方向的边，`in` -入边、 `out` -出边、 `both` -入边和出边都考虑进去\n\n`directed`：是否为有向图\n\n`weightPropertyName`：边的权重属性名\n\n`epsilon`：PageRank 算法的收敛容差\n\n`linkProb`：PageRank 算法的阻尼系数，指任意时刻，用户访问到某节点后继续访问该节点链接的下一个节点的概率，经验值 0.85\n\n### scale\n\n- `'linear'`：线性插值函数，将一个值从一个范围线性映射到另一个范围，常用于处理中心性值的差异较小的情况\n- `'log'`：对数插值函数，将一个值从一个范围对数映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'pow'`：幂律插值函数，将一个值从一个范围幂律映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'sqrt'`：平方根插值函数，将一个值从一个范围平方根映射到另一个范围，常用于处理中心性值的差异较大的情况\n- 自定义插值函数：`(value: number, domain: [number, number], range: [number, number]) => number`，其中 `value` 为需要映射的值，`domain` 为输入值的范围，`range` 为输出值的范围\n\n**示例：**\n\n```typescript {9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n      },\n      scale: 'linear',\n    },\n  ],\n});\n```\n\n效果如下（该示例为基于度中心性 `degree` ，可切换插值函数查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-scale.md\"></embed>\n\n## 实际案例\n\n- [场景案例：独角兽和他们的投资者](/examples/feature/default/#unicorns-investors)\n","frontmatter":{"title":"动态调整节点大小 MapNodeSize","order":"1"},"isInternal":false,"tokens":1130,"sizeBytes":6744},{"name":"overview.en.md","path":"packages/site/docs/manual/transform/overview.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/overview.en.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Data Transformation Overview\norder: 0\n---\n\n## Overview\n","frontmatter":{"title":"Data Transformation Overview","order":"0"},"isInternal":false,"tokens":17,"sizeBytes":66},{"name":"overview.zh.md","path":"packages/site/docs/manual/transform/overview.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/overview.zh.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 数据处理总览\norder: 0\n---\n\n## 什么是数据处理\n\n数据处理（ `transform` ），也叫数据转换器，是 G6 提供的支持在 **渲染前( `beforeDraw` )** 或者 **布局后( `afterLayout` )** 对绘制数据进行转化处理的机制，用户可以通过数据处理很方便地对数据处理逻辑进行封装解耦。\n\n## 实现原理\n\n### 基类\n\n所有的数据处理器都是基于 [BaseTransform](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/base-transform.ts) 这个基类进行实现，里面定义了两个基类方法 `beforeDraw` 和 `afterLayout` ：\n\n```typescript\nexport abstract class BaseTransform<T extends BaseTransformOptions = BaseTransformOptions> extends BaseExtension<T> {\n  public beforeDraw(data: DrawData, context: DrawContext): DrawData {\n    return data;\n  }\n\n  public afterLayout(type: 'pre', data: DrawData): void;\n  public afterLayout(type: 'post', data?: undefined): void;\n  public afterLayout(type: 'pre' | 'post', data?: DrawData) {}\n}\n```\n\n以下是这两个方法里核心的参数类型说明：\n\n- **DrawData**\n\n  ```typescript\n  type ProcedureData = {\n    nodes: Map<ID, NodeData>;\n    edges: Map<ID, EdgeData>;\n    combos: Map<ID, ComboData>;\n  };\n\n  type DrawData = {\n    add: ProcedureData; // 本次渲染需要新增的元素\n    update: ProcedureData; // 本次渲染需要更新的元素\n    remove: ProcedureData; // 本次渲染需要移除的元素\n  };\n  ```\n\n- **pre | post**\n\n  pre：绘制前进行的布局（只会在首次布局触发）\n\n  post：完成绘制后进行的布局\n\n### 执行时机\n\n- **beforeDraw**\n\n  下面是每次渲染时数据处理的执行流程/时机：\n\n  <img width=\"300px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Pb3kRI2yHo8AAAAAAAAAAAAAemJ7AQ/original\"/>\n\n  **详细说明：**\n\n  1. G6 在每次渲染前计算出 `add`、`update`、`remove`，分别对应为需要新增、更新、移除的元素，以下简称为 `DrawData`\n  2. 此时数据处理介入，按配置顺序执行每个数据处理的 `beforeDraw` 方法，参数则为 `DrawData`\n  3. 数据处理器中，对 `DrawData` 里面的元素数据进行改动，即可以按需对 `add`、`update`、`remove` 里面的元素数据进行修改、移除或者插入元素数据等，最终把改动后的 `DrawData` 返回给渲染主体逻辑\n  4. 在执行数据处理后，执行对应的新增、更新、移除元素的操作，完成渲染\n\n:::info{title=提示}\n触发渲染的场景分为主动和被动，列举如下：\n\n- **主动：** 用户主动调用 `graph.render()` 、 `graph.draw()` 或者在自定义插件、交互等实例里面通过上下文拿到元素控制器（ [ElementController](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/element.ts) ）实例调用 `this.context.element.draw()`，等（ `graph.render()` 和 `graph.draw()` 也是调用元素控制器的 `draw` 方法）\n- **被动：** 部分内置交互和插件有触发渲染，布局执行后也有触发渲染更新元素位置，等\n\n:::\n\n- **afterLayout**：在执行完布局计算并开始更新节点位置后，执行数据处理\n\n## 内置数据处理\n\n- **G6 提供给用户的内置数据处理如下：**\n\n各数据处理详细配置可参考 [内置数据处理文档](/manual/transform/map-node-size)。\n\n| 数据处理名称                                        | 注册类型                 | 功能描述                                             | 执行时机   |\n| --------------------------------------------------- | ------------------------ | ---------------------------------------------------- | ---------- |\n| [动态调整节点大小](/manual/transform/map-node-size) | `map-node-size`          | 根据节点中心性调整节点的大小                         | beforeDraw |\n| [径向标签](/manual/transform/place-radial-labels)   | `place-radial-labels`    | 根据径向布局自动调整节点标签样式，包括位置和旋转角度 | afterDraw  |\n| [平行边](/manual/transform/process-parallel-edges)  | `process-parallel-edges` | 处理平行边，即多条边共享同一源节点和目标节点         | beforeDraw |\n\n- **G6 内嵌的数据处理如下：**\n\n除了提供给用户选用的数据处理外， G6 也封装并使用了以下数据处理机制来实现基础功能。以下数据处理不开放给用户配置使用，默认必带（列举出来供用户有需要时点击查看并参考源码）：\n\n| 数据处理名称                                                                                                            | 注册类型                | 功能描述                                                                                                                                                      | 执行时机   |\n| ----------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| [调整combo绘制顺序](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/arrange-draw-order.ts)              | `arrange-draw-order`    | combo 嵌套时，优先绘制子 combo                                                                                                                                | beforeDraw |\n| [处理组合的展开收起](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-combo.ts)          | `collapse-expand-combo` | 收起时，移除 combo 内部元素、销毁内部边，外部边则连到收起的 combo 上；<br />展开时，反之；                                                                    | beforeDraw |\n| [处理（树图）节点的收起和展开](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-node.ts) | `collapse-expand-node`  | 绘制前，处理（树图）节点的收起和展开                                                                                                                          | beforeDraw |\n| [获取边的实际端点](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/get-edge-actual-ends.ts)             | `get-edge-actual-ends`  | 配合`collapse-expand-combo`实现收起时，combo 外部连到内部节点的边改为连到收起的 combo 上（`collapse-expand-combo`只是在收起时判断并标记了这些边需要更新端点） | beforeDraw |\n| [更新节点、combo相关边](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/update-related-edge.ts)         | `update-related-edges`  | 如果更新了节点/combo，则把连接的边也一起更新了                                                                                                                | beforeDraw |\n\n:::warning{title=注意}\n\n上面 G6 为实现自身基础功能使用的数据处理仅供参考，不可改动。如有需要在这些数据处理基础上做特殊处理，可通过 [自定义数据处理](#自定义数据处理) 实现。\n\n:::\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `transforms` 数组指定需要的数据处理：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n### 配置数据处理参数\n\n对于需要自定义参数的数据处理，可以使用 `object` 形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    'place-radial-labels',\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges-1',\n      mode: 'bundle',\n      distance: 30,\n    },\n  ],\n});\n```\n\n### 动态更新数据处理\n\nG6 支持在图实例运行期间动态管理数据处理：\n\n- 可以通过 [setTransforms](/api/transform#graphsettransformstransforms) 方法调整数据处理器：\n\n```javascript\n// 添加新的数据处理器\ngraph.setTransforms((transforms) => [...transforms, 'place-radial-labels']);\n\n// 移除数据处理器\ngraph.setTransforms((transforms) => transforms.filter((t) => t !== 'place-radial-labels'));\n```\n\n- 可以通过 [updateTransform](/api/transform#graphupdatetransformtransform) 方法更新数据处理的配置：\n\n```javascript\n// 更新单个数据处理器\ngraph.updateTransform({\n  key: 'process-parallel-edges-1',\n  distance: 100,\n});\n```\n\n:::warning{title=注意}\n使用`updateTransform`方法时，需要在初始化时为数据处理指定唯一的`key`。\n:::\n\n### 卸载数据处理\n\n使用 [setTransforms](/api/transform#graphsettransformstransforms) 方法同样可以卸载数据处理，将数据处理配置列表置为空即可：\n\n```javascript\n// 卸载所有数据处理器\ngraph.setTransforms([]);\n```\n\n## 自定义数据处理\n\n当内置数据处理器无法满足需求时，你可以：\n\n- 继承和扩展现有数据处理\n- 创建全新的自定义数据处理\n\n自定义数据处理需要先注册后使用。详细教程请参考 [自定义数据处理](/manual/transform/custom-transform) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomTransform } from './my-custom-transform';\n\n// 注册自定义数据处理器\nregister(ExtensionCategory.TRANSFORM, 'my-custom-transform', MyCustomTransform);\n\n// 使用自定义数据处理\nconst graph = new Graph({\n  transforms: ['my-custom-transform'],\n});\n```\n","frontmatter":{"title":"数据处理总览","order":"0"},"isInternal":false,"tokens":1704,"sizeBytes":9557},{"name":"PlaceRadialLabels.en.md","path":"packages/site/docs/manual/transform/PlaceRadialLabels.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/PlaceRadialLabels.en.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: PlaceRadialLabels\norder: 3\n---\n\n## Options\n\n### offset\n\n> _number_\n\nOffset\n","frontmatter":{"title":"PlaceRadialLabels","order":"3"},"isInternal":false,"tokens":22,"sizeBytes":86},{"name":"PlaceRadialLabels.zh.md","path":"packages/site/docs/manual/transform/PlaceRadialLabels.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/PlaceRadialLabels.zh.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 径向标签 PlaceRadialLabels\norder: 2\n---\n\n**参考示例**：\n\n- [径向生态树](/examples/scene-case/tree-graph/#radial-dendrogram)\n- [径向紧凑树](/examples/scene-case/tree-graph/#radial-compact-tree)\n\n## 配置项\n\n### type\n\n> _`place-radial-labels` \\| string_\n\n此数据处理已内置，你可以通过 `type: 'place-radial-labels'` 来使用它。\n\n### offset\n\n> _number_\n\n偏移量\n","frontmatter":{"title":"径向标签 PlaceRadialLabels","order":"2"},"isInternal":false,"tokens":81,"sizeBytes":409},{"name":"ProcessParallelEdges.en.md","path":"packages/site/docs/manual/transform/ProcessParallelEdges.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/ProcessParallelEdges.en.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: ProcessParallelEdges\norder: 3\n---\n\nParallel Edges refer to multiple edges existing between two nodes in a graph structure. These edges share the same source and target nodes but may represent different relationships or attributes. To avoid edge overlap and confusion, two methods are provided for handling parallel edges: (1) Bundle Mode: Bundles parallel edges together and separates them from other edges by altering their curvature; (2) Merge Mode: Merges parallel edges into a single aggregated edge.\n\n## Options\n\n### distance\n\n> _number_\n\nThe distance between edges, only valid for bundling mode\n\n### edges\n\n> _string[]_\n\nThe edges to be handled, all edges by default\n\n### <Badge type=\"success\">Required</Badge> mode\n\n> _'bundle' \\| 'merge'_ **Default:** `'bundle'`\n\nProcessing mode\n\n- '`merge`': Merge parallel edges into one edge which is suitable for cases where parallel edges do not need to be distinguished\n\n- '`bundle`': Each edge will be bundled with all other parallel edges and separated from them by varying the curvature. If the number of parallel edges in a group is odd, the central edge will be drawn as a straight line, and the others will be drawn as curves\n\n### style\n\n> _PathStyleProps_ _\\| ((prev:_ [EdgeData](/api/graph/option#edgedata)_[]) =>_ _PathStyleProps)_\n\nThe style of the merged edge, only valid for merging mode\n","frontmatter":{"title":"ProcessParallelEdges","order":"3"},"isInternal":false,"tokens":340,"sizeBytes":1359},{"name":"ProcessParallelEdges.zh.md","path":"packages/site/docs/manual/transform/ProcessParallelEdges.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/transform/ProcessParallelEdges.zh.md","title":"Transform Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 平行边 ProcessParallelEdges\norder: 3\n---\n\n## 概述\n\n平行边（Parallel Edges）是指在图结构中，两个节点之间存在多条边。这些边共享相同的源节点和目标节点，但可能代表不同的关系或属性。为了避免边的重叠和混淆，提供了两种处理平行边的方式：\n\n- 捆绑模式（bundle）：将平行边捆绑在一起，通过改变曲率与其他边分开\n- 合并模式（merge）：将平行边合并为一条聚合\n\n## 使用场景\n\n下面为常见使用场景举例：\n\n- 双向数据流，比如客户端发送请求，服务端返回响应\n\n- 多依赖关系，即一个节点通过多种方式依赖另一个节点，比如微服务架构中，服务 A 调用服务 B的两个不同 API\n- 多链路，比如高可用架构中，主链路（实线，状态正常）与备份链路（灰色虚线，状态待机）同时展示\n\n## 基本用法\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges',\n      mode: 'bundle', // 默认就是捆绑模式了\n      distance: 30, // 配置捆绑模式下边之间的距离为30\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性     | 描述                                               | 类型                                                                                    | 默认值                  | 必选 |\n| -------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type     | 数据处理类型                                       | process-parallel-edges                                                                  | -                       | ✓    |\n| distance | 边之间的距离，仅在捆绑模式下有效                   | number                                                                                  | 15                      |      |\n| edges    | 考虑要处理的边，默认为全部边                       | string[]                                                                                | -                       |      |\n| mode     | 处理模式，[配置项](#mode)                          | `'bundle'`                                                                              | `'merge'` \\| `'bundle'` |      |\n| style    | 合并边的样式，仅在合并模式下有效，[配置项](#style) | PathStyleProps \\| ((prev: [EdgeData](/manual/data#边数据edgedata)[]) => PathStyleProps) | -                       |      |\n\n### mode\n\n提供了两种处理模式：\n\n- `'merge'`: 将平行边合并为一条边，适用于不需要区分平行边的情况，[示例](#合并模式)\n\n`merge` 使用的是内置的直线（ [`line`](/manual/element/edge/Line) ）来展示合并边。\n\n- `'bundle'`: 每条边都会与其他所有平行边捆绑在一起，并通过改变曲率与其他边分开。如果一组平行边的数量是奇数，那么中心的边将被绘制为直线，其他的边将被绘制为曲线，[示例](#捆绑模式)\n\n`bundle` 使用的是内置的二次贝塞尔曲线（ [`quadratic`](/manual/element/edge/Quadratic) ）来实现，数据处理过程会强制把每个 `edgeDatum.type` 改为 `quadratic`，并计算每条线的曲率。\n\n:::warning{title=注意}\n\n禁止在创建 Graph 实例时配置 `edge.type` 即默认的边类型，因为它的优先级比 `edgeDatum.type` 要高，会导致 `bundle` 模式的处理无法生效。\n\n:::\n\n### style\n\n合并边的样式，仅在合并模式下有效\n\n#### PathStyleProps\n\n下表列出了常用的属性，更多属性请参考 [PathStyleProps](https://g.antv.antgroup.com/api/basic/path#pathstyleprops)。\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| fill           | 填充色                    | string                        | `#1783FF` |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |\n| lineDash       | 描边虚线样式              | number[]                      | -         |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |\n| lineWidth      | 描边宽度                  | number                        | 1         |\n| opacity        | 透明度                    | number \\| string              | 1         |\n| shadowBlur     | 阴影模糊度                | number                        | -         |\n| shadowColor    | 阴影颜色                  | string                        | -         |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |\n| stroke         | 描边色                    | string                        | `#000`    |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |\n\n## 代码示例\n\n### 捆绑模式\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'C' },\n    { source: 'C', target: 'A' },\n    ...Array.from({ length: 10 }).map((_, i) => ({\n      id: `edge:A-B${i}`,\n      source: 'A',\n      target: 'B',\n      data: {\n        label: `A->B:${i}`,\n      },\n    })),\n    ...Array.from({ length: 5 }).map((_, i) => ({\n      id: `edge:B-C${i}`,\n      source: 'B',\n      target: 'C',\n      data: {\n        label: `B->C:${i}`,\n      },\n    })),\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      ports: [{ placement: 'center' }],\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n    },\n  },\n  behaviors: ['drag-element'],\n  transforms: ['process-parallel-edges'],\n});\n\ngraph.render();\n```\n\n### 合并模式\n\n下面是一个简单的合并模式的例子，需要注意：\n\n- 不需要合并（即两个节点间只有一条边）的边，合并样式不会在这条边上生效，比如例子中的 **A->C**\n- 合并样式实际上是赋值给 `datum.style` ，也就是优先级会比实例化 Graph 时配置的默认样式低（ `edge.style` ），所以例子中合并样式的 `startArrow` 没有生效\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'B' },\n    { source: 'B', target: 'A' },\n    { id: 'B-C:1', source: 'B', target: 'C' },\n    { id: 'B-C:2', source: 'B', target: 'C' },\n    { source: 'A', target: 'C' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n      startArrow: false,\n    },\n  },\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      mode: 'merge',\n      style: {\n        halo: true,\n        haloOpacity: 0.2,\n        haloStroke: 'red',\n        startArrow: true,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n","frontmatter":{"title":"平行边 ProcessParallelEdges","order":"3"},"isInternal":false,"tokens":1626,"sizeBytes":8416},{"name":"feature.en.md","path":"packages/site/docs/manual/whats-new/feature.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/feature.en.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Feature\norder: 1\n---\n\n## 🏖️ Brand New Design Specification for Graphs\n\nG6 version 5.0 has redesigned the Options specification. While ensuring comprehensive capabilities, it optimizes the options structure to be more intuitive and easier to understand.\n\nYou only need to quickly grasp the basic [core concepts](/en/manual/graph/graph) to get started with G6 quickly and achieve graph visualization without delay.\n\n**😰 The 4.0 Options** had a complex nested structure and was less semantically capable\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 The 5.0 Options** has a clear structure and is easy to understand\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 Brand New API Design\n\nG6 5.0 features a cleaner, easy-to-use API design that is more in line with modern front-end frameworks.\n\n## 🌲 Merging Graphs with Tree Graphs\n\nTree graphs are essentially a type of directed acyclic graph. G6 5.0 has integrated the design of graphs and tree graphs, reducing the cost of understanding and usage.\n\nNow, you can directly use `Graph` to instantiate and draw tree graphs in G6, without the need to use `TreeGraph`. You simply need to specify the layout as a tree graph layout.\n\nAdditionally, G6 provides the `treeToGraphData` utility method to help you quickly convert tree graph data into graph data.\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 Multi-Renderer Support\n\nG6 5.0 employs the next-generation @antv/g rendering engine, which has been newly designed. It offers support for multiple renderers such as `Canvas`, `SVG`, and `WebGL`. Additionally, it supports the mixed use of different renderers on layered canvases.\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other configurations\n  // Use the WebGL renderer\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 High-Performance Layouts\n\nG6 5.0 has adopted a brand-new layout engine, with some layouts implemented in Rust, providing higher performance for layout calculations. Additionally, there is support for WebGPU acceleration in certain layouts.\n\n> 🚀 To utilize high-performance layouts, you will need to install the `@antv/layout-wasm` package\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... Other Layout Configurations\n  },\n});\n```\n\n## 🎨 Multiple Themes Mechanism\n\nG6 5.0 comes with two built-in themes: light and dark, and allows for flexible customization based on the use case. For details, please refer to [Custom Theme](/en/manual/custom-extension/theme).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D Large Graphs\n\nG6 5.0 provides 3D rendering, layout, interaction capabilities, and can be used by import 3d elements, renderer, and behaviors from `@antv/g6-extension-3D` registration, see: [Using 3D](/manual/further-reading/3d).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 Plugin Optimization and Enhancement\n\nG6 5.0 has optimized and enhanced existing plugins, decoupling Graph from plugins, and providing richer capabilities while optimizing configurations.\n\nPlease visit [Plugin](/en/api/plugins/bubble-sets) to experience the capabilities of more plugins.\n\n## 💼 Optimized Package Size\n\nThanks to the well-modularized design and extension registration mechanism of G6 5.0, modules that are not used will not be packaged into the final build file, reducing the package size.\n\nCompared to 4.0, the UMD package size has been reduced from 1.8 MB to 0.96 MB, a reduction of nearly 50%.\n","frontmatter":{"title":"Feature","order":"1"},"isInternal":false,"tokens":1128,"sizeBytes":4537},{"name":"feature.zh.md","path":"packages/site/docs/manual/whats-new/feature.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/feature.zh.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 新版本特性\norder: 1\n---\n\n## 🏖️ 全新设计图配置范式\n\nG6 5.0 重新设计了图配置范式，在保证能力完善的基础上，优化配置项结构，更加直观、易于理解。\n\n仅需快速了解基本[核心概念](/manual/graph/graph)，即可快速上手 G6，快速实现图可视化。\n\n**😰 4.0 配置项** 嵌套结构复杂，语义化能力较弱\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 5.0 配置项** 结构清晰，易于理解\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 全新 API 设计\n\nG6 5.0 采用了更加简洁、易用的 API 设计，更加符合现代前端框架的设计风格。\n\n## 🌲 合并图与树图\n\n树图本质上是一种单向无环图，G6 5.0 融合了图与树图的设计，降低了理解和使用成本。\n\n现在，你可以在 G6 中直接使用 `Graph` 来实例化绘制树图，而不需要再使用 `TreeGraph`，仅需指定布局为树图布局即可。\n\n此外，G6 提供了 `treeToGraphData` 工具方法，帮助你快速将树图数据转换为图数据。\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 多渲染器支持\n\nG6 5.0 采用了新一代设计的 @antv/g 渲染引擎，提供了 `Canvas` `SVG` `WebGL` 多种渲染器支持，并且分层画布支持不同渲染器的混合使用。\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 WebGL 渲染器\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 高性能布局\n\nG6 5.0 采用了全新布局引擎，部分布局提供 Rust 实现，提供了更高性能的布局计算。另有布局支持 WebGPU 加速。\n\n> 🚀 高性能布局需要安装 `@antv/layout-wasm` 包\n\n```typescript\nimport { ForceAtlas2Layout, initThreads, supportsThreads } from '@antv/layout-wasm';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'forceatlas2-wasm', ForceAtlas2Layout);\n\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'forceatlas2-wasm',\n    threads,\n    // ... 其他布局配置\n  },\n});\n```\n\n> GPU 加速布局需要安装 `@antv/layout-gpu` 包\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他布局配置\n  },\n});\n```\n\n## 🎨 多主题机制\n\nG6 5.0 内置了亮色、暗色两套主题，并可基于使用场景进行灵活定制，具体可参考[自定义主题](/manual/theme/custom-theme)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D 大图\n\nG6 5.0 提供了 3D 大图渲染、布局、交互能力，从 `@antv/g6-extension-3d` 中引入 3D 元素、渲染器、交互等注册即可使用，详见：[使用 3D](/manual/further-reading/3d)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 插件优化增强\n\nG6 5.0 对现有插件进行了优化增强，解除了 Graph 与插件之间的耦合，并优化配置的同时提供了更加丰富了能力。\n\n敬请前往[插件](/manual/plugin/overview)体验更多插件的能力。\n\n## 💼 优化包体积\n\n得益于 G6 5.0 良好的模块化的设计以及扩展注册机制，对于未使用的模块，不会被打包到最终的构建文件中，减小了包体积。\n\n与 4.0 相比，UMD 包体积从 1.8 MB 减小到 0.96 MB，减小了近 50%。\n","frontmatter":{"title":"新版本特性","order":"1"},"isInternal":false,"tokens":781,"sizeBytes":4415},{"name":"upgrade-to-5-1.en.md","path":"packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Upgrade from 5.0 to 5.1 (Layout)\norder: 7\n---\n\nThis page focuses on layout documentation changes introduced in G6 `5.1`. Starting from `5.1`, layout pages prioritize the field naming aligned with `@antv/layout`; common `5.0` layout writeups are collected here for migration reference.\n\n## What Changed\n\n- Since `5.1`, layout docs prioritize shared `@antv/layout` fields such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`\n- Individual layout pages mainly keep the recommended `5.1` writeup\n- If you are migrating an existing `5.0` project, use this page to map old field names to the new documentation style\n\n## D3Force: center force to shortcut fields\n\nIn `5.0` documentation, the center force was commonly written inside `center`:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is the shortcut fields:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` maps to `centerX`\n- `center.y` maps to `centerY`\n- `center.strength` maps to `centerStrength`\n\nFor the full field description, see [D3Force Layout](/en/manual/layout/d3-force-layout).\n\n## ComboCombined: innerLayout / outerLayout to layout\n\nIn `5.0` documentation, the inner combo layout and the outer layout were commonly configured separately:\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is a single `layout` entry that returns different configurations for different levels based on `comboId`:\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- When `comboId` has a value, it refers to the layout inside a combo\n- When `comboId` is empty, it refers to the outermost layout\n- Multiple layout choices are unified under the `layout` entry\n\nFor the `5.1` recommended form, see [ComboCombined Layout](/en/manual/layout/combo-combined-layout).\n\n## Migration Suggestion\n\n1. Identify the matching layout type from your existing `5.0` project\n2. Map the old fields to the recommended `5.1` documentation style\n3. Return to the specific layout page to verify shared fields and defaults\n","frontmatter":{"title":"Upgrade from 5.0 to 5.1 (Layout)","order":"7"},"isInternal":false,"tokens":648,"sizeBytes":2589},{"name":"upgrade-to-5-1.zh.md","path":"packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 从 5.0 升级到 5.1（布局）\norder: 7\n---\n\n本文档聚焦 G6 `5.1` 中布局文档的写法调整。`5.1` 的布局页面会优先展示与 `@antv/layout` 对齐后的字段；`5.0` 中常见的布局写法统一收敛到本文档中，便于迁移时对照。\n\n## 总体变化\n\n- `5.1` 起，布局文档会优先展示 `@antv/layout` 的公共字段，例如 `width` `height` `center` `enableWorker` `node` `edge`\n- 各布局页主要保留 `5.1` 推荐写法，`5.0` 中常见写法请以本文档为准\n- 迁移时，建议先按旧项目中的字段定位，再映射到 `5.1` 文档里的推荐配置\n\n## D3Force：center force 改为快捷字段\n\n`5.0` 文档中，常见把中心力写在 `center` 中：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\n`5.1` 文档中推荐写成更直接的快捷字段：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` 对应 `centerX`\n- `center.y` 对应 `centerY`\n- `center.strength` 对应 `centerStrength`\n\n如果你需要继续对照完整字段说明，可查看 [D3Force 布局](/manual/layout/d3-force-layout)。\n\n## ComboCombined：innerLayout / outerLayout 收敛为 layout\n\n`5.0` 文档中，常见分别配置 Combo 内部布局和最外层布局：\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\n`5.1` 文档中推荐使用单个 `layout` 字段，根据 `comboId` 为不同层级返回布局配置：\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- `comboId` 有值时，表示当前为 Combo 内部层级\n- `comboId` 为空时，表示当前为最外层布局\n- 多层布局选择统一收敛到 `layout` 入口\n\n如果你需要查看 `5.1` 推荐写法，可查看 [ComboCombined 布局](/manual/layout/combo-combined-layout)。\n\n## 迁移建议\n\n1. 先按旧项目中的布局类型定位到本文档对应条目\n2. 再把 `5.0` 字段映射成 `5.1` 文档里的推荐写法\n3. 最后回到具体布局页，核对公共字段和默认值\n","frontmatter":{"title":"从 5.0 升级到 5.1（布局）","order":"7"},"isInternal":false,"tokens":425,"sizeBytes":2457},{"name":"upgrade.en.md","path":"packages/site/docs/manual/whats-new/upgrade.en.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/upgrade.en.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: Upgrade To 5.0\norder: 6\n---\n\nThis document will guide you through the process of upgrading from G6 version `4.x` to `5.x`. If you are using version `3.x`, please upgrade to version `4.x` first.\n\n## Preparation Before Upgrade\n\n1. Please ensure that your current git branch is clean and there is no uncommitted code.\n2. Refer to the [Installation](./getting-started/installation) document to install version `5.x` and remove the dependencies for version `4.x`.\n\n## Start Upgrade\n\n### Data\n\nThe data format in the new version has changed as follows:\n\n1. All style attributes in `nodes`, `edges`, and `combos` need to be placed within `style`, and data attributes should be stored in `data`:\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // The label is a non-stylistic attribute, placed in the data, and can be accessed in the style mapping function\n    // The `size` is a stylistic attribute, placed within the `style`\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\nSince we have redesigned and implemented the elements, please refer to the corresponding documentation to modify the new element options:\n\n- [Node](/en/api/elements/nodes/base-node)\n- [Edge](/en/api/elements/edges/base-edge)\n- [Combo](/en/api/elements/combos/base-combo)\n\n2. If you need to specify the element type in the data, you can use the `type` attribute:\n\n```typescript\n{\n  nodes: [\n    // Specify the node type as rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### Options\n\n<Badge type=\"warning\">Change</Badge> **fitView / fitCenter / fitViewPadding**\n\n- The `fitView` and `fitCenter` options have been merged into `autoFit`.\n- To use `fitView`, you can configure it as `autoFit: 'view'`\n- To use `fitCenter`, you can configure it as `autoFit: 'center'`\n- You can also pass an object for full configuration:\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- The `fitViewPadding` has been changed to `padding`.\n\n<Badge type=\"error\">Removed</Badge> **linkCenter**\n\nIn version 5.x, the edge connection mechanism will attempt to connect to nodes/Combos in the following order:\n\n1. Connect Port\n2. Outline\n3. Center\n\n<Badge type=\"error\">Removed</Badge> **groupByTypes**\n\n<Badge type=\"error\">Removed</Badge> **autoPaint**\n\nPlease manually call the `render` or `draw` method to perform rendering.\n\n<Badge type=\"warning\">Changed</Badge> **modes**\n\nIn version 5.x, interaction modes have been removed. You can switch the currently enabled behaviors by setting `behaviors`.\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">Change</Badge> **defaultNode / defaultEdge / defaultCombo**\n\nThe element styles have been moved to `[element].style`, for example, `defaultNode` has been changed to `node.style`:\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\nElement state styles have been moved to `[element].state`, for example, `nodeStateStyles` has been changed to `node.stateStyles`:\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **animate / animateCfg**\n\n- The `animate` options has been changed to `animation`\n- `animate` and `animateCfg` have been merged into `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **minZoom / maxZoom**\n\n- The `minZoom` and `maxZoom` options have been merged into `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **renderer**\n\nG6 5.x supports multi-layer canvases and defaults to using the `canvas` renderer.\n\nThe `renderer` no longer supports the string type and has been changed to a callback function:\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **enabledStack / maxStep**\n\nThe built-in undo and redo functionality has been removed in version 5.x. For related capabilities, please use a plugin to implement.\n\n### API\n\n<Badge type=\"warning\">Change</Badge> **data / save / read / changeData**\n\nVersion 5.x offers a completely new data API. For details, see [Data API](/en/api/data).\n\n- The `data` and `changeData` methods from 4.x are replaced by `setData` in 5.x.\n- The `save` method from 4.x is replaced by `getData` in 5.x.\n- The `read` method from 4.x is replaced by `setData` + `render` in 5.x.\n\n<Badge type=\"warning\">Change</Badge> **get / set**\n\nTo access Graph options, please use `getOptions` or the `getXxx` API, such as `getZoomRange`, `getBehaviors`, etc. The `set` method is analogous.\n\n<Badge type=\"warning\">Change</Badge> **getContainer**\n\nDirect API to obtain the container is not currently supported, but you can obtain it through `graph.getCanvas().getContainer()`.\n\n> In most cases, you do not need to directly manipulate the container.\n\n<Badge type=\"error\">Removed</Badge> **getGroup**\n\n<Badge type=\"warning\">Change</Badge> **getMinZoom / getMaxZoom**\n\nUse `getZoomRange` to obtain the values.\n\n<Badge type=\"warning\">Change</Badge> **setMinZoom / setMaxZoom**\n\nUse the `setZoomRange` method to set the values.\n\n<Badge type=\"warning\">Change</Badge> **getWidth / getHeight**\n\nUse `getSize` to get the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **changeSize**\n\nUse `setSize` to set the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **zoom**\n\nChanged to `zoomBy`.\n\n<Badge type=\"warning\">Change</Badge> **translate**\n\nChanged to `translateBy`.\n\n<Badge type=\"warning\">Change</Badge> **moveTo**\n\nChanged to `translateTo`.\n\n<Badge type=\"warning\">Change</Badge> **focusItem**\n\nChanged to `focusElement`.\n\n<Badge type=\"error\">Removed</Badge> **addItem / updateItem / removeItem**\n\nTo add or remove elements, use the methods `addData` / `updateData` / `removeData` to manipulate data.\n\n<Badge type=\"error\">Removed</Badge> **refreshItem**\n\n<Badge type=\"error\">Removed</Badge> **refreshPositions**\n\n<Badge type=\"error\">Removed</Badge> **updateCombo**\n\n<Badge type=\"error\">Removed</Badge> **updateCombos**\n\n<Badge type=\"error\">Removed</Badge> **updateComboTree**\n\n<Badge type=\"warning\">Change</Badge> **node / edge / combo**\n\nUse the `setNode` / `setEdge` / `setCombo` methods as alternatives.\n\n<Badge type=\"warning\">Change</Badge> **showItem / hideItem**\n\nUse the `setElementVisibility` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **getNodes / getEdges / getCombos / getComboChildren / getNeighbors / find / findById / findAll / findAllByState**\n\nIn version 5.x, direct retrieval of element instances is not supported.\n\n- To obtain element data, use the methods `getData`, `getNodeData`, `getEdgeData`, `getComboData`, which support searching by element ID.\n- To obtain child node data, use the `getChildrenData` method.\n- To obtain neighbor node data, use the `getNeighborNodesData` method.\n- To find element data based on state, use the `getElementDataByState` method.\n\n<Badge type=\"warning\">Change</Badge> **collapseCombo / expandCombo**\n\nUse the `collapseElement` / `expandElement` methods as alternatives.\n\n<Badge type=\"error\">Removed</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">Removed</Badge> **createCombo**\n\nCombos can now be added using the `addData` / `addComboData` methods.\n\n<Badge type=\"error\">Removed</Badge> **uncombo**\n\nCombos can now be removed using the `removeData` / `removeComboData` methods.\n\n<Badge type=\"warning\">Change</Badge> **setItemState**\n\nUse the `setElementState` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **clearItemStates**\n\n- To clear all states of a single element: `graph.setElementState(id, [])`\n- To clear all states of multiple elements: `graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">Removed</Badge> **priorityState**\n\nWhen using `setElementState`, the state that appears later in the array has a higher priority.\n\n<Badge type=\"error\">Removed</Badge> **setMode**\n\nUse `setBehaviors` to set the current behaviors.\n\n<Badge type=\"error\">Removed</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">Change</Badge> **layout**\n\nDoes not support parameters. To configure the layout, please use `setLayout`.\n\n<Badge type=\"warning\">Change</Badge> **updateLayout**\n\nChanged to `setLayout`.\n\n<Badge type=\"error\">Removed</Badge> **destroyLayout**\n\n<Badge type=\"warning\">Change</Badge> **addBehaviors / removeBehaviors**\n\nReplaced with `setBehaviors`.\n\n<Badge type=\"error\">Removed</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- For multiple `Hull` instances, you need to configure multiple `hull` plugins in `plugins`, such as:\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- Operations to retrieve, update, and remove `Hull` are implemented through `setPlugins`, `updatePlugin`.\n\n<Badge>Not yet available</Badge> **getNodeDegree**\n\n<Badge>Not yet available</Badge> **getShortestPathMatrix**\n\n<Badge>Not yet available</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">Removed</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\nAll undo and redo related APIs should be called after obtaining the corresponding plugin, for example:\n\n```typescript\n// 'history' is the key configured for use with the plugin\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">Removed</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\nAnimation-related information is now emitted through events:\n\n- Animation start event: `beforeanimate`\n- Animation end event: `afteranimate`\n- To stop an animation:\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">Change</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x uses a different coordinate system than 4.x. For details, see [Coordinate](/en/manual/further-reading/coordinate).\n\n<Badge type=\"error\">Removed</Badge> **setTextWaterMarker / setImageWaterMarker**\n\nFor watermark functionality, please refer to the [Watermark](/en/api/plugins/watermark)plugin.\n\n<Badge type=\"warning\">Change</Badge> **toFullDataURL**\n\nReplaced with `toDataURL`, specify the parameter as: `mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">Removed</Badge> **downloadFullImage / downloadImage**\n\nOnly the capability to export as a `DataURL` is provided. If you need to download an image, please refer to the following example code:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **clear**\n\nUse `setData` + `draw` to clear data and the canvas.\n\n### Extension Registration\n\nUnlike G6 4.x, G6 5.x uses a unified extension registration function (register). You can refer to the [Extension Register](/en/manual/core-concept/extension#register-extension) to register G6 extensions.\n\nThe following G6 4.x registration functions have been deprecated:\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### Events\n\nCompared to G6 4.x, G6 5.x has the following differences in events:\n\n- The `mouse` and `touch` events have been removed and are unified under the `pointer` event.\n- The naming convention for lifecycle events is usually in the format of: `before/after` + `object/property` + `action`, for example: `beforeelementcreate` is triggered before an element is created.\n- The following events have been removed:\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- The following element change events have been removed, but you can still access them through `beforeelementupdate` and `afterelementupdate`:\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- The following events have been changed:\n  - The `graphstatechange` event has been changed to `beforeelementstatechange` / `afterelementstatechange`.\n  - The `viewportchange` event has been changed to `beforetransform` / `aftertransform`.\n\nFor a complete list of events, please refer to [Event](/en/api/reference/g6#event).\n","frontmatter":{"title":"Upgrade To 5.0","order":"6"},"isInternal":false,"tokens":3491,"sizeBytes":13962},{"name":"upgrade.zh.md","path":"packages/site/docs/manual/whats-new/upgrade.zh.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/site/docs/manual/whats-new/upgrade.zh.md","title":"Whats-new Skill","category":"anthropic-skill","format":"markdown","content":"---\ntitle: 升级到 5.0\norder: 6\n---\n\n本文档将引导你从 G6 `4.x` 版本升级到 `5.x` 版本。如果你使用的是 `3.x` 版本，请先升级到 `4.x` 版本。\n\n## 升级前准备\n\n1. 请确保当前 git 分支是干净的，没有未提交的代码。\n2. 参考 [安装](/manual/getting-started/installation) 文档安装 `5.x` 版本，并移除 `4.x` 版本依赖。\n\n## 开始升级\n\n### 数据\n\n新版本的数据格式有所变化，具体如下：\n\n1. `nodes` `edges` `combos` 中所有样式属性都需要放在 `style` 中，`data` 中存放数据属性：\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // label 为非样式属性，放在 data 中，可在样式映射函数中访问\n    // size 为样式属性，放在 style 中\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\n由于我们重新设计实现了元素，新的元素配置项请参考相应文档进行修改：\n\n- [Node](/manual/element/node/overview)\n- [Edge](/manual/element/edge/overview)\n- [Combo](/manual/element/combo/overview)\n\n2. 如果要在数据中指定元素类型，可以使用 `type` 属性：\n\n```typescript\n{\n  nodes: [\n    // 指定节点类型为 rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### 配置项\n\n<Badge type=\"warning\">变更</Badge> **fitView / fitCenter / fitViewPadding**\n\n- `fitView` 和 `fitCenter` 配置项已经合并为 `autoFit`\n- 若要使用 `fitView`，可以配置为 `autoFit: 'view'`\n- 若要使用 `fitCenter`，可以配置为 `autoFit: 'center'`\n- 也可以传入对象进行完整配置：\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- `fitViewPadding` 已变更为 `padding`\n\n<Badge type=\"error\">移除</Badge> **linkCenter**\n\n5.x 的边连接机制会按照如下顺序依次尝试连接到节点/Combo：\n\n1. 连接桩\n2. 轮廓\n3. 中心\n\n<Badge type=\"error\">移除</Badge> **groupByTypes**\n\n<Badge type=\"error\">移除</Badge> **autoPaint**\n\n请手动调用 `render` 或 `draw` 方法进行绘制。\n\n<Badge type=\"warning\">变更</Badge> **modes**\n\n5.x 已经移除交互模式，你可以通过设置 `behaviors` 来切换当前启用的交互行为。\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">变更</Badge> **defaultNode / defaultEdge / defaultCombo**\n\n元素样式已移至 `[element].style` 中，如 `defaultNode` 变更为 `node.style`：\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\n元素状态样式已移至 `[element].state` 中，如 `nodeStateStyles` 变更为 `node.stateStyles`：\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **animate / animateCfg**\n\n- `animate` 配置项已变更为 `animation`\n- `animate` 和 `animateCfg` 已合并为 `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **minZoom / maxZoom**\n\n`minZoom` 和 `maxZoom` 已合并为 `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **renderer**\n\nG6 5.x 支持多层画布，默认使用 `canvas` 渲染。\n\nrenderer 不再支持字符串类型，变更为回调函数：\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">移除</Badge> **enabledStack / maxStep**\n\n5.x 已移除内置撤销重做功能，相关能力请使用插件实现。\n\n### API\n\n<Badge type=\"warning\">变更</Badge> **data / save / read / changeData**\n\n5.x 提供了全新的数据 API，详见 [数据 API](/api/data)。\n\n- 4.x `data` `changeData` 方法使用 5.x `setData` 替代\n- 4.x `save` 方法使用 5.x `getData` 替代\n- 4.x `read` 方法使用 5.x `setData` + `render` 替代\n\n<Badge type=\"warning\">变更</Badge> **get / set**\n\n若要访问 Graph options，请使用 `getOptions` 或者 `getXxx` API，例如 `getZoomRange` `getBehaviors` 等。 `set` 同理。\n\n<Badge type=\"warning\">变更</Badge> **getContainer**\n\n暂不支持直接获取容器的 API，但可以通过 `graph.getCanvas().getContainer()` 获取。\n\n> 绝大部分情况下，你都不需要直接操作容器。\n\n<Badge type=\"error\">移除</Badge> **getGroup**\n\n<Badge type=\"warning\">变更</Badge> **getMinZoom / getMaxZoom**\n\n使用 `getZoomRange` 获取。\n\n<Badge type=\"warning\">变更</Badge> **setMinZoom / setMaxZoom**\n\n使用 `setZoomRange` 方法设置。\n\n<Badge type=\"warning\">变更</Badge> **getWidth / getHeight**\n\n使用 `getSize` 获取。\n\n<Badge type=\"warning\">变更</Badge> **changeSize**\n\n使用 `setSize` 设置。\n\n<Badge type=\"warning\">变更</Badge> **zoom**\n\n变更为 `zoomBy`。\n\n<Badge type=\"warning\">变更</Badge> **translate**\n\n变更为 `translateBy`。\n\n<Badge type=\"warning\">变更</Badge> **moveTo**\n\n变更为 `translateTo`。\n\n<Badge type=\"warning\">变更</Badge> **focusItem**\n\n变更为 `focusElement`。\n\n<Badge type=\"error\">移除</Badge> **addItem / updateItem / removeItem**\n\n通过 `addData` / `updateData` / `removeData` 方法操作数据来添加或删除元素。\n\n<Badge type=\"error\">移除</Badge> **refreshItem**\n\n<Badge type=\"error\">移除</Badge> **refreshPositions**\n\n<Badge type=\"error\">移除</Badge> **updateCombo**\n\n<Badge type=\"error\">移除</Badge> **updateCombos**\n\n<Badge type=\"error\">移除</Badge> **updateComboTree**\n\n<Badge type=\"warning\">变更</Badge> **node / edge / combo**\n\n使用 `setNode` / `setEdge` / `setCombo` 方法替代。\n\n<Badge type=\"warning\">变更</Badge> **showItem / hideItem**\n\n使用 `setElementVisibility` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **getNodes / getEdges / getCombos / getComboChildren /getNeighbors /find /findById / findAll /findAllByState**\n\n5.x 不支持直接获取元素实例。\n\n- 若要获取元素数据，使用 `getData` `getNodeData` `getEdgeData` `getComboData` 方法，支持传入元素 id 进行查找。\n- 获取子节点数据，使用 `getChildrenData` 方法。\n- 获取邻居节点数据，使用 `getNeighborNodesData` 方法。\n- 基于状态查找元素数据，使用 `getElementDataByState`。\n\n<Badge type=\"warning\">变更</Badge> **collapseCombo / expandCombo**\n\n使用 `collapseElement` / `expandElement` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">移除</Badge> **createCombo**\n\n通过 `addData` / `addComboData` 方法添加 Combo。\n\n<Badge type=\"error\">移除</Badge> **uncombo**\n\n通过 `removeData` / `removeComboData` 方法移除 Combo。\n\n<Badge type=\"warning\">变更</Badge> **setItemState**\n\n使用 `setElementState` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **clearItemStates**\n\n- 清除单个元素所有状态：`graph.setElementState(id, [])`\n- 清除多个元素所有状态：`graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">移除</Badge> **priorityState**\n\n`setElementState` 时状态数组中靠后的状态优先级更高。\n\n<Badge type=\"error\">移除</Badge> **setMode**\n\n使用 `setBehaviors` 来设置当前交互。\n\n<Badge type=\"error\">移除</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">变更</Badge> **layout**\n\n不支持参数，如需配置布局，请使用 `setLayout`。\n\n<Badge type=\"warning\">变更</Badge> **updateLayout**\n\n变更为 `setLayout`。\n\n<Badge type=\"error\">移除</Badge> **destroyLayout**\n\n<Badge type=\"warning\">变更</Badge> **addBehaviors / removeBehaviors**\n\n使用 `setBehaviors` 替代。\n\n<Badge type=\"error\">移除</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- 多个 `Hull` 需在 `plugins` 中配置多个 `hull` 插件，如：\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- `Hull` 的获取、更新、移除操作通过 `setPlugins`, `updatePlugin` 实现。\n\n<Badge>暂未提供</Badge> **getNodeDegree**\n\n<Badge>暂未提供</Badge> **getShortestPathMatrix**\n\n<Badge>暂未提供</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">移除</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\n所有撤销重做相关 API 请获取到对应插件后调用 API，例：\n\n```typescript\n// 'history' 为使用插件时配置的 key\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">移除</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\n动画相关信息通过事件抛出：\n\n- 动画开始事件：`beforeanimate`\n- 动画结束事件：`afteranimate`\n- 停止动画：\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">变更</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x 采用了与 4.x 不同的坐标系，详见 [坐标系](/manual/further-reading/coordinate)。\n\n<Badge type=\"error\">移除</Badge> **setTextWaterMarker / setImageWaterMarker**\n\n要使用水印功能，请参考 [水印](/manual/plugin/watermark)插件。\n\n<Badge type=\"warning\">变更</Badge> **toFullDataURL**\n\n使用 `toDataURL` 替代，指定参数为：`mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">移除</Badge> **downloadFullImage / downloadImage**\n\n仅提供导出为 `DataURL` 的能力，如需下载图片，请参考如下实例代码：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">移除</Badge> **clear**\n\n使用 `setData` + `draw` 清空数据和画布。\n\n### 扩展注册\n\n与 G6 4.x 不同，G6 5.x 使用的统一的扩展注册函数(register)，你可以参考 [注册扩展](/manual/graph/extension#注册扩展) 来注册 G6 扩展。\n\n下列 G6 4.x 的注册函数已经废除：\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### 事件\n\n与 G6 4.x 相比，G6 5.x 的事件但存下如下差异：\n\n- 移除了 `mouse` 和 `touch` 事件，统一使用 `pointer` 事件\n- 生命周期事件名命名格式通常为： `before/after` + `对象/属性` + `操作`，例如：`beforeelementcreate` 表示在创建元素前触发\n- 下列事件已被移除：\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- 下列元素变更事件被移除，但你仍可通过 `beforeelementupdate` 和 `afterelementupdate` 获取：\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- 下列事件有所变更：\n  - graphstatechange 事件变更为 beforeelementstatechange / afterelementstatechange\n  - viewportchange 事件变更为 beforetransform / aftertransform\n\n完整的事件列表请参考 [事件](/api/event)。\n","frontmatter":{"title":"升级到 5.0","order":"6"},"isInternal":false,"tokens":2513,"sizeBytes":12565},{"name":"README.md","path":"packages/cli/README.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/cli/README.md","title":"cli Documentation","category":"plugin-manifest","format":"markdown","content":"# @antv/g6-cli\n\n`@antv/g6-cli` is a G6 template generation tool that comes with several templates.\n\nCurrently, it owns a built-in template called `extension`. This template handles the boilerplate setup, which encompasses a seamless local development environment, linting, code formatting, Jest for snapshot testing and bundling with Rollup etc.\n\n`@antv/g6-cli` i\n\n## Getting Started\n\nTo start using `@antv/g6-cli`, you'll first need to install it globally.\n\n```bash\nnpm i @antv/g6-cli -g\n```\n\nOnce installed, you can easily scaffold a new project:\n\n```bash\ncreate-g6\n```\n\nThen follow the prompts!\n\n![prompts](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*09BKQrIcZUMAAAAAAAAAAAAADmJ7AQ/original)\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a **G6 Extension** project, run:\n\n```bash\ncreate-g6 g6-extension-test --template extension\n```\n","isInternal":false,"tokens":236,"sizeBytes":944},{"name":"README.md","path":"packages/g6-extension-3d/README.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/g6-extension-3d/README.md","title":"g6-extension-3d Documentation","category":"plugin-manifest","format":"markdown","content":"## 3D extension for G6\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*lEL3TrCLnPsAAAAAAAAAAAAADmJ7AQ/original\" />\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yFa5RKilu6kAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension package provides 3D elements, behaviors and plugins for G6.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-3d\n```\n\n2. Import and Register\n\n> Where renderer, elements and lighting are necessary\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { DragCanvas3D, Light, Line3D, Sphere, renderer } from '@antv/g6-extension-3d';\n\n// 3d light plugin\nregister(ExtensionCategory.PLUGIN, '3d-light', Light);\n// sphere node element\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\n// line edge element\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\n// drag canvas in 3d scene\nregister(ExtensionCategory.BEHAVIOR, 'drag-canvas-3d', DragCanvas3D);\n// camera setting plugin\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting);\n```\n\n3. Use\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  renderer, // use 3d renderer\n  data: {\n    // your data\n  },\n  node: {\n    type: 'sphere', // use sphere node\n  },\n  edge: {\n    type: 'line3d', // use 3d line edge\n  },\n  behaviors: ['drag-canvas-3d'],\n  plugins: [\n    // set camera configs, see: https://g.antv.antgroup.com/en/api/camera/intro\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n    // add directional light\n    {\n      type: '3d-light',\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n```\n\n## Resources\n\n- [Lite Solar System](https://g6.antv.antgroup.com/en/examples/feature/default/#lite-solar-system)\n- [3D Node](https://g6.antv.antgroup.com/en/examples/element/node/#3d-node)\n","isInternal":false,"tokens":484,"sizeBytes":1933},{"name":"README.md","path":"packages/g6-extension-react/README.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/g6-extension-react/README.md","title":"g6-extension-react Documentation","category":"plugin-manifest","format":"markdown","content":"## React extension for G6\n\n<img width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rWSiT6dnwfcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension allows you to define G6 node by React component and JSX syntax.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-react\n```\n\n2. Import and Register\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n```\n\n3. Define Node\n\nReact Node:\n\n```jsx\nconst ReactNode = () => {\n  return <div>node</div>;\n};\n```\n\nG Node:\n\n```jsx\nimport { Group, Rect, Text } from '@antv/g6-extension-react';\n\nconst GNode = () => {\n  return <Group>\n    <Rect width={100} height={100}></Rect>\n    <Text text={\"node\"} />\n  <Group>\n};\n```\n\n4. Use\n\nUse ReactNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'react',\n    style: {\n      component: () => <ReactNode />,\n    },\n  },\n});\n```\n\nUse GNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'g',\n    style: {\n      component: () => <GNode />,\n    },\n  },\n});\n```\n\n## Q&A\n\n1. Difference between ReactNode and GNode\n\nReactNode is a React component, while GNode support jsx syntax but can only use G tag node.\n\n## Resources\n\n- [React node](https://g6.antv.antgroup.com/examples/element/custom-node/#react-node)\n- [G node with JSX syntax](https://g6.antv.antgroup.com/en/examples/element/custom-node/#react-g)\n","isInternal":false,"tokens":372,"sizeBytes":1487},{"name":"README.md","path":"packages/g6-ssr/README.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/g6-ssr/README.md","title":"g6-ssr Documentation","category":"plugin-manifest","format":"markdown","content":"## SSR extension for G6 5.0\n\nThis extension package provides SSR support for G6 5.0, which supports canvas rendering in server side.\n\n## Usage\n\n### Install\n\n```bash\nnpm install @antv/g6-ssr\n```\n\n### Render in JavaScript API\n\n> For complete options, please refer to [G6 Graph Options](https://g6.antv.antgroup.com/api/graph/option)\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  imageType: 'png', // or 'jpeg'\n  data: {\n    // data\n  },\n  // other options\n});\n\ngraph.exportToFile('image');\n// -> image.png\n\ngraph.toBuffer();\n// -> get buffer\n```\n\n### Render in CLI\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./image\n```\n\n### Export SVG / PDF\n\nWhen render in JavaScript API, you can pass `outputType` option to export SVG or PDF.\n\n```js\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  data: {\n    // data\n  },\n  outputType: 'svg', // or 'pdf'\n  // other options\n});\n```\n\nWhen render in CLI, you can pass `-t` or `--type` option to export SVG or PDF.\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./file -t pdf\n```\n\n### Register Custom G6 Extensions\n\nIf you need to register custom extensions of G6, please use the `registry` function exported from `@antv/g6-ssr`.\n\n```js\nimport { createGraph, registry } from '@antv/g6-ssr';\nimport { BaseNode, ExtensionCategory } from '@antv/g6';\n\nclass CustomNode extends BaseNode {\n  // custom node\n}\n\nregistry(ExtensionCategory.Node, 'custom-node', CustomNode);\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  node: {\n    type: 'custom-node',\n    // other options\n  },\n  // other options\n});\n```\n\n### Use Plugins\n\nWhen using G6-SSR, you can also use G render plugins. Here's how to use plugins in server-side rendering:\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\nimport { Plugin as RoughCanvasPlugin } from '@antv/g-plugin-rough-canvas-renderer';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  renderPlugins: [new RoughCanvasPlugin()],\n  data: {\n    // data\n  },\n});\n```\n\n## License\n\nMIT\n","isInternal":false,"tokens":519,"sizeBytes":2074},{"name":"README.md","path":"packages/g6/src/plugins/hull/hull/README.md","rawUrl":"https://raw.githubusercontent.com/antvis/G6/HEAD/packages/g6/src/plugins/hull/hull/README.md","title":"hull Documentation","category":"plugin-manifest","format":"markdown","content":"> Code copied from [hull-js](https://github.com/hull/hull-js), and fix the issue [[Bug]: hull.js Code Injection Vulnerability #6605](https://github.com/antvis/G6/issues/6605).\n","isInternal":false,"tokens":44,"sizeBytes":176}],"systemPromptSnippet":"<agent_rules repository=\"antvis/G6\">\n\n<!-- Skill/Rule: Cursor Rule: translation (.cursor/rules/translation.mdc) -->\n---\ndescription: 翻译\nglobs:\nalwaysApply: false\n---\n# Translation Guidelines for site/docs\n\nWhen translating files under the `site/docs` directory, please adhere to the following guidelines:\n\n1. **Consistency in Terminology**: Ensure that terminology is consistent throughout the document. Use a glossary if available to maintain uniformity in terms.\n\n   **Glossary**:\n\n   - 画布 (Canvas)\n   - 元素 (Element)\n   - 节点 (Node)\n   - 边 (Edge)\n   - 组合 (Combo)\n   - 交互 (Behavior)\n   - 布局 (Layout)\n   - 插件 (Plugin)\n   - 动画 (Animation)\n   - 数据处理 (Transform)\n   - 色板 (Palette)\n   - 配置项 (Option)\n   - 图数据 (Graph Data)\n   - 树图 (Tree Graph)\n   - 属性 (Property)\n   - 描述 (Description)\n   - 类型 (Type)\n   - 默认值 (Default Value)\n   - 必选 (Required)\n\n2. **Adjust Hyperlinks**: Review and adjust hyperlinks to ensure they point to the correct translated sections or documents. Verify that all links are functional and correctly formatted.\n\n   - **Internal Links**: In the English version, all internal links should have a `/en` prefix, while the Chinese version should not have any prefix. Ensure this prefix is added to all internal links in English documents to avoid any oversight.\n   - **Anchor Points**: For anchor points following a `#`, if they contain Chinese characters, they should be adjusted to match the corresponding title in the English version rather than being directly translated.\n   - **External Links**: Convert external links appropriately to ensure they align with the language and context of the document.\n\n3. **Direct Writing to Translated Documents**: Translations should be stored in corresponding `.en.md` or `.zh.md` files within the same directory. Ensure that the translated content is placed in the correct location within the document.\n\n   - When translating from Chinese to English, create or update the `.en.md` file in the same directory.\n   - When translating from English to Chinese, create or update the `.zh.md` file in the same directory.\n\n4. **Support for Partial Content Translation**: Allow for the selection and translation of specific sections of content. Translated sections should be inserted into the appropriate location within the document, maintaining the logical flow and structure.\n\n   - **Full Document Translation**: If the entire document is selected for translation, replace the entire content with the translated version.\n   - **Partial Content Translation**: If only specific sections are selected, find the appropriate place to replace or insert the translated content, ensuring the document's logical flow and structure are maintained.\n\n5. **Contextual Translation**: Avoid literal translations. Ensure that the translation fits the English context and conveys the intended meaning accurately.\n\n6. **Direct Modification**: Translations should be directly modified in the corresponding `.en.md` or `.zh.md` files without returning the translated content separately. Ensure that the changes are saved in the correct file and location.\n\n7. **Preserve Metadata Order**: Do not modify the `order` attribute in the page metadata during translation. This ensures that the document order remains consistent across different language versions.\n\n8. **Add '/en' Prefix to Internal Links**: Ensure that all internal links in English documentation have the '/en' prefix to maintain consistency and correct navigation.\n\nBy following these guidelines, translations will be more accurate and consistent, facilitating easier review and integration into the documentation.\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/behavior.en.md) -->\n---\ntitle: Behavior\norder: 8\n---\n\n## Overview of Behavior\n\nBehavior is a core building block of G6, precisely defining the interaction between users and the graph. Each Behavior plugin is a highly encapsulated functional unit, integrating event listening, state management, and response handling logic for specific scenarios.\n\nG6's built-in Behaviors cover most common interaction needs and provide a flexible extension mechanism, allowing developers to create customized interaction experiences based on business scenarios. For a complete list of behavior types, configuration options, and development examples, please refer to the [Behavior Overview](/en/manual/behavior/overview) section.\n\n## API Reference\n\n### Graph.getBehaviors()\n\nGet all configured behaviors in the current graph.\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**Return Value**\n\n- **Type**: [BehaviorOptions](#behavioroptions)\n- **Description**: All configured behaviors in the current graph\n\n**Example**\n\n```typescript\n// Get all current behaviors\nconst behaviors = graph.getBehaviors();\nconsole.log('Current graph behaviors:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\nSet the behaviors of the graph, replacing all existing behaviors.\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                    | Type                                                                              | Default | Required |\n| --------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------- | -------- |\n| behaviors | New behavior configuration, or a function returning new configuration based on the current one | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -       | ✓        |\n\n**Note**\n\nThe set behaviors will completely replace the original ones. To add new behaviors, you can use functional updates:\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**Example 1**: Set basic behaviors\n\n```typescript\n// Set basic behaviors\ngraph.setBehaviors([\n  'drag-canvas', // Drag canvas\n  'zoom-canvas', // Zoom canvas\n  'drag-element', // Drag element\n]);\n```\n\n**Example 2**: Set behaviors with configuration\n\n```typescript\ngraph.setBehaviors([\n  // String form (using default configuration)\n  'drag-canvas',\n\n  // Object form (custom configuration)\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // Specify a unique identifier for subsequent updates\n    sensitivity: 1.5, // Zoom sensitivity\n  },\n\n  // Enable drag only on nodes\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // Enable drag only on nodes\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new behavior\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// Replace specific behavior\ngraph.setBehaviors((currentBehaviors) => {\n  // Filter out existing zoom behaviors\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // Add new zoom behavior configuration\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\nUpdate the configuration of a specific behavior, identified by the `key`.\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                             | Type                                          | Default | Required |\n| --------- | --------------------------------------- | --------------------------------------------- | ------- | -------- |\n| behavior  | Configuration of the behavior to update | [UpdateBehaviorOption](#updatebehavioroption) | -       | ✓        |\n\n**Note**\n\nTo update a behavior, the original behavior configuration must specify the `key` field to accurately locate and update the behavior.\n\n**Example 1**: Update behavior configuration\n\n```typescript\n// Specify key when initially setting behaviors\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// Update behavior configuration\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // Specify the behavior to update\n  sensitivity: 2.0, // New zoom sensitivity\n  enableOptimize: true, // Add new configuration\n});\n```\n\n**Example 2**: Disable/Enable behavior\n\n```typescript\n// Set behaviors with keys\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// Disable drag functionality\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// Re-enable later\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## Type Definitions\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // Interaction type\n  type: string;\n\n  // Interaction key, a unique identifier for identifying and further operating this interaction\n  key?: string;\n\n  // There may be other configuration items for different types of interactions\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // Unique identifier of the behavior to update\n  key: string;\n\n  // Other configuration items to update\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/behavior.zh.md) -->\n---\ntitle: 交互\norder: 8\n---\n\n## 交互概述\n\n交互（Behavior）是 G6 的核心构建模块，它精确定义了用户与图之间的互动行为。每个 Behavior 插件都是一个高度封装的功能单元，内部集成了特定场景下的事件监听、状态管理和响应处理逻辑。\n\nG6 的内置 Behavior 涵盖了大多数常见交互需求，同时提供了灵活的扩展机制，支持开发者根据业务场景构建定制化交互体验。\n有关完整的交互行为类型、配置选项及开发示例，请参阅 [交互总览](/manual/behavior/overview) 章节。\n\n## API 参考\n\n### Graph.getBehaviors()\n\n获取当前图表中所有已配置的交互行为。\n\n```typescript\ngetBehaviors(): BehaviorOptions;\n```\n\n**返回值**\n\n- **类型**: [BehaviorOptions](#behavioroptions)\n- **描述**: 当前图表中已配置的所有交互行为\n\n**示例**\n\n```typescript\n// 获取当前所有交互行为\nconst behaviors = graph.getBehaviors();\nconsole.log('当前图表的交互行为:', behaviors);\n```\n\n### Graph.setBehaviors(behaviors)\n\n设置图表的交互行为，将替换所有现有的交互行为。\n\n```typescript\nsetBehaviors(behaviors: BehaviorOptions | ((prev: BehaviorOptions) => BehaviorOptions)): void;\n```\n\n**参数**\n\n| 参数      | 描述                                                 | 类型                                                                              | 默认值 | 必选 |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------------------------- | ------ | ---- |\n| behaviors | 新的交互行为配置，或一个基于当前配置返回新配置的函数 | [BehaviorOptions](#behavioroptions) \\| (prev: BehaviorOptions) => BehaviorOptions | -      | ✓    |\n\n**说明**\n\n设置的交互会全量替换原有的交互，如果需要新增交互可以使用函数式更新：\n\n```typescript\ngraph.setBehaviors((behaviors) => [...behaviors, { type: 'zoom-canvas' }]);\n```\n\n**示例 1**: 设置基本交互\n\n```typescript\n// 设置基本交互\ngraph.setBehaviors([\n  'drag-canvas', // 拖拽画布\n  'zoom-canvas', // 缩放画布\n  'drag-element', // 拖拽元素\n]);\n```\n\n**示例 2**: 设置带配置的交互\n\n```typescript\ngraph.setBehaviors([\n  // 字符串形式（使用默认配置）\n  'drag-canvas',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom', // 指定唯一标识，用于后续更新\n    sensitivity: 1.5, // 缩放灵敏度\n  },\n\n  // 只有节点上启用拖拽\n  {\n    type: 'drag-element',\n    key: 'drag-node-only',\n    enable: (event) => event.targetType === 'node', // 仅在节点上启用拖拽\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的交互行为\ngraph.setBehaviors((currentBehaviors) => [\n  ...currentBehaviors,\n  {\n    type: 'brush-select',\n    key: 'selection-brush',\n  },\n]);\n\n// 替换特定交互行为\ngraph.setBehaviors((currentBehaviors) => {\n  // 过滤掉现有的缩放交互\n  const filteredBehaviors = currentBehaviors.filter((behavior) => {\n    if (typeof behavior === 'string') return behavior !== 'zoom-canvas';\n    return behavior.type !== 'zoom-canvas';\n  });\n\n  // 添加新的缩放交互配置\n  return [\n    ...filteredBehaviors,\n    {\n      type: 'zoom-canvas',\n      key: 'new-zoom',\n      enableOptimize: true,\n    },\n  ];\n});\n```\n\n### Graph.updateBehavior(behavior)\n\n更新指定的交互行为配置，需要通过 `key` 标识要更新的交互。\n\n```typescript\nupdateBehavior(behavior: UpdateBehaviorOption): void;\n```\n\n**参数**\n\n| 参数     | 描述               | 类型                                          | 默认值 | 必选 |\n| -------- | ------------------ | --------------------------------------------- | ------ | ---- |\n| behavior | 更新的交互行为配置 | [UpdateBehaviorOption](#updatebehavioroption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个交互，必须在原始交互配置中指定 `key` 字段，以便能够准确找到并更新该交互。\n\n**示例 1**: 更新交互配置\n\n```typescript\n// 初始设置交互时指定 key\ngraph.setBehaviors([\n  {\n    type: 'zoom-canvas',\n    key: 'my-zoom-canvas',\n    sensitivity: 1.0,\n  },\n]);\n\n// 更新交互配置\ngraph.updateBehavior({\n  key: 'my-zoom-canvas', // 指定要更新的交互\n  sensitivity: 2.0, // 新的缩放灵敏度\n  enableOptimize: true, // 添加新配置\n});\n```\n\n**示例 2**: 禁用/启用交互\n\n```typescript\n// 设置带 key 的行为\ngraph.setBehaviors([\n  {\n    type: 'drag-canvas',\n    key: 'main-drag',\n  },\n  {\n    type: 'zoom-canvas',\n    key: 'main-zoom',\n  },\n]);\n\n// 禁用拖拽功能\ngraph.updateBehavior({\n  key: 'main-drag',\n  enable: false,\n});\n\n// 稍后重新启用\nsetTimeout(() => {\n  graph.updateBehavior({\n    key: 'main-drag',\n    enable: true,\n  });\n}, 5000);\n```\n\n## 类型定义\n\n### BehaviorOptions\n\n```typescript\ntype BehaviorOptions = (string | CustomBehaviorOption | ((this: Graph) => CustomBehaviorOption))[];\n\ntype CustomBehaviorOption = {\n  // 交互类型\n  type: string;\n\n  // 交互 key，即唯一标识，用于标识交互，从而进一步操作此交互\n  key?: string;\n\n  // 针对不同类型的交互，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateBehaviorOption\n\n```typescript\ntype UpdateBehaviorOption = {\n  // 要更新的交互的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/canvas.en.md) -->\n---\ntitle: Canvas Operations\norder: 1\n---\n\n## Overview of Canvas Operations\n\nG6 provides a series of canvas operation APIs to control and obtain basic information about the canvas. With these APIs, you can:\n\n- Get the canvas instance\n- Get and set the canvas size\n- Operate the canvas renderer and layers\n\n## API Reference\n\n### Graph.getCanvas()\n\nGet the canvas instance, which can be used for low-level canvas operations.\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**Return Value Description**\n\nThe Canvas instance includes the following main functions:\n\n- `getLayer(name?: string)`: Get the specified layer\n- `getLayers()`: Get all layers\n- `getCamera()`: Get the camera instance\n- `getRoot()`: Get the root node\n- `setCursor(cursor: string)`: Set the mouse cursor style\n\n**Example**\n\n```typescript\n// Get the canvas instance\nconst canvas = graph.getCanvas();\n\n// Get the main layer\nconst mainLayer = canvas.getLayer('main');\n\n// Set the mouse cursor style\ncanvas.setCursor('pointer');\n\n// Get the root node of the canvas\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\nGet the size of the current canvas container. Returns an array containing the width and height.\n\n```typescript\ngetSize(): [number, number];\n```\n\n**Example**\n\n```typescript\n// Get the canvas size\nconst [width, height] = graph.getSize();\nconsole.log('Canvas width:', width);\nconsole.log('Canvas height:', height);\n\n// Use the size information for calculations\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\nSet the size of the canvas container. This method will update both the canvas and container size.\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description            | Type   | Default | Required |\n| --------- | ---------------------- | ------ | ------- | -------- |\n| width     | Canvas width (pixels)  | number | -       | ✓        |\n| height    | Canvas height (pixels) | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set a fixed size\ngraph.setSize(800, 600);\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/canvas.zh.md) -->\n---\ntitle: 画布操作\norder: 1\n---\n\n## 画布操作概述\n\nG6 提供了一系列画布操作 API，用于控制和获取画布的基本信息。通过这些 API，你可以：\n\n- 获取画布实例\n- 获取和设置画布尺寸\n- 操作画布渲染器和图层\n\n## API 参考\n\n### Graph.getCanvas()\n\n获取画布实例，返回的实例可用于进行底层的画布操作。\n\n```typescript\ngetCanvas(): Canvas;\n```\n\n**返回值类型说明**\n\nCanvas 实例包含以下主要功能：\n\n- `getLayer(name?: string)`: 获取指定图层\n- `getLayers()`: 获取所有图层\n- `getCamera()`: 获取相机实例\n- `getRoot()`: 获取根节点\n- `setCursor(cursor: string)`: 设置鼠标样式\n\n**示例**\n\n```typescript\n// 获取画布实例\nconst canvas = graph.getCanvas();\n\n// 获取主图层\nconst mainLayer = canvas.getLayer('main');\n\n// 设置鼠标样式\ncanvas.setCursor('pointer');\n\n// 获取画布根节点\nconst root = canvas.getRoot();\n```\n\n### Graph.getSize()\n\n获取当前画布容器的尺寸。返回一个包含宽度和高度的数组。\n\n```typescript\ngetSize(): [number, number];\n```\n\n**示例**\n\n```typescript\n// 获取画布尺寸\nconst [width, height] = graph.getSize();\nconsole.log('画布宽度:', width);\nconsole.log('画布高度:', height);\n\n// 使用尺寸信息进行计算\nconst centerX = width / 2;\nconst centerY = height / 2;\n```\n\n### Graph.setSize(width, height)\n\n设置画布容器的尺寸。这个方法会同时更新画布和容器的大小。\n\n```typescript\nsetSize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述             | 类型   | 默认值 | 必选 |\n| ------ | ---------------- | ------ | ------ | ---- |\n| width  | 画布宽度（像素） | number | -      | ✓    |\n| height | 画布高度（像素） | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置固定尺寸\ngraph.setSize(800, 600);\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/coordinate.en.md) -->\n---\ntitle: Coordinate Transformation\norder: 12\n---\n\n## Overview of Coordinate Systems\n\nUnderstanding different coordinate systems and their transformations is crucial in graph visualization. G6 involves multiple coordinate systems, each used for different scenarios:\n\n- **Client Coordinate System**: Origin is at the top-left corner of the browser viewport, measured in pixels. Typically used for handling browser events.\n- **Screen Coordinate System**: Origin is at the top-left corner of the screen, affected by page scrolling.\n- **Page Coordinate System**: Origin is at the top-left corner of the document, considering document scrolling.\n- **Canvas Coordinate System**: Also known as the world coordinate system, used for drawing and layout, with the origin at the top-left corner of the canvas element.\n- **Viewport Coordinate System**: The visible area of the canvas, with the origin at the top-left corner of the viewport. The viewport can be panned and zoomed to view different areas of the Canvas.\n\nIn this [example](https://g.antv.antgroup.com/en/examples/canvas/canvas-basic#coordinates), moving the mouse shows the position in various coordinate systems:\n\n![Coordinate System Diagram](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\nWhen the canvas is not panned or zoomed, the Viewport and Canvas coordinate systems coincide. With user interactions like dragging or zooming, the two systems may shift.\n\nG6 provides a series of APIs for converting between different coordinate systems, detailed below.\n\n## API Reference\n\n### Graph.getCanvasByClient(point)\n\nConvert browser coordinates (client coordinates) to canvas coordinates.\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description              | Type                                         | Default | Required |\n| --------- | ------------------------ | -------------------------------------------- | ------- | -------- |\n| point     | Browser coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getCanvasByViewport(point)\n\nConvert viewport coordinates to canvas coordinates.\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                         | Default | Required |\n| --------- | ------------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Viewport coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the canvas coordinate system\n\n### Graph.getClientByCanvas(point)\n\nConvert canvas coordinates to browser client coordinates.\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the browser client coordinate system\n\n### Graph.getViewportByCanvas(point)\n\nConvert canvas coordinates to viewport coordinates.\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                         | Default | Required |\n| --------- | ----------------------- | -------------------------------------------- | ------- | -------- |\n| point     | Canvas coordinate point | [number, number] \\| [number, number, number] | -       | ✓        |\n\n**Return Value**\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Coordinate point in the viewport coordinate system\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/coordinate.zh.md) -->\n---\ntitle: 坐标转换\norder: 12\n---\n\n## 坐标系概述\n\n在图可视化中，理解不同的坐标系及其转换关系至关重要。G6 中涉及多种坐标系，它们各自用于不同的场景：\n\n- **Client 坐标系**：浏览器视口左上角为原点，单位为像素。通常用于处理浏览器事件。\n- **Screen 坐标系**：屏幕左上角为原点，会受页面滚动影响。\n- **Page 坐标系**：文档左上角为原点，考虑文档滚动。\n- **Canvas 坐标系**：也称为世界坐标系，图形绘制和布局时使用的坐标系，画布元素左上角为原点。\n- **Viewport 坐标系**：视口坐标系，当前可见的画布区域，视口左上角为原点。视口通过平移、缩放等操作，可以观察不同的 Canvas 区域。\n\n在这个[示例](https://g.antv.antgroup.com/zh/examples/canvas/canvas-basic#coordinates)中，移动鼠标可以看到鼠标所在位置在各个坐标系下的值：\n\n![坐标系关系图](https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*kPfcTKwZG90AAAAAAAAAAAAAARQnAQ)\n\n当画布没有发生平移和缩放时，Viewport 坐标系与 Canvas 坐标系重合。随着用户的交互（如拖拽画布、缩放），两个坐标系会出现偏移。\n\nG6 提供了一系列 API 用于在不同坐标系之间进行转换，下面将详细介绍这些 API。\n\n## API 参考\n\n### Graph.getCanvasByClient(point)\n\n将浏览器坐标（客户端坐标）转换为画布坐标。\n\n```typescript\ngetCanvasByClient(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述         | 类型                                         | 默认值 | 必选 |\n| ----- | ------------ | -------------------------------------------- | ------ | ---- |\n| point | 浏览器坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getCanvasByViewport(point)\n\n将视口坐标转换为画布坐标。\n\n```typescript\ngetCanvasByViewport(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 视口坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 画布坐标系下的坐标点\n\n### Graph.getClientByCanvas(point)\n\n将画布坐标转换为浏览器客户端坐标。\n\n```typescript\ngetClientByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 浏览器客户端坐标系下的坐标点\n\n### Graph.getViewportByCanvas(point)\n\n将画布坐标转换为视口坐标。\n\n```typescript\ngetViewportByCanvas(point: Point): Point;\n```\n\n**参数**\n\n| 参数  | 描述       | 类型                                         | 默认值 | 必选 |\n| ----- | ---------- | -------------------------------------------- | ------ | ---- |\n| point | 画布坐标点 | [number, number] \\| [number, number, number] | -      | ✓    |\n\n**返回值**\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 视口坐标系下的坐标点\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/data.en.md) -->\n---\ntitle: Data\norder: 0\n---\n\n## Overview of Data Operations\n\nG6 provides a comprehensive [data](/en/manual/data) operation API, covering the complete lifecycle of graph data from query, modification to update.\n\n## API Reference\n\n### Graph.getData()\n\nGet the complete data of the graph.\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**Return Value**:\n\n- **Type**: [GraphData](#graphdata)\n\n- **Description**: Returns the complete graph data containing all nodes, edges, and combo data\n\n**Example**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('Node data:', graphData.nodes);\nconsole.log('Edge data:', graphData.edges);\nconsole.log('Combo data:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\nGet node data, supporting three calling methods.\n\n```typescript\n// Get all node data\ngetNodeData(): NodeData[];\n\n// Get single node data\ngetNodeData(id: ID): NodeData;\n\n// Get multiple node data\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Node ID       | string   | -       |          |\n| ids       | Node ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **Description**: Returns the specified node data or node data array\n\n**Example**:\n\n```typescript\n// Get all nodes\nconst nodes = graph.getNodeData();\n\n// Get single node\nconst node = graph.getNodeData('node1');\nconsole.log('Node position:', node.style.x, node.style.y);\n\n// Get multiple nodes\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\nGet edge data, supporting three calling methods.\n\n```typescript\n// Get all edge data\ngetEdgeData(): EdgeData[];\n\n// Get single edge data\ngetEdgeData(id: ID): EdgeData;\n\n// Get multiple edge data\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description   | Type     | Default | Required |\n| --------- | ------------- | -------- | ------- | -------- |\n| id        | Edge ID       | string   | -       |          |\n| ids       | Edge ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **Description**: Returns the specified edge data or edge data array\n\n**Example**:\n\n```typescript\n// Get all edges\nconst edges = graph.getEdgeData();\n\n// Get single edge\nconst edge = graph.getEdgeData('edge1');\nconsole.log('Edge source and target:', edge.source, edge.target);\n\n// Get multiple edges\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\nGet combo data, supporting three calling methods.\n\n```typescript\n// Get all combo data\ngetComboData(): ComboData[];\n\n// Get single combo data\ngetComboData(id: ID): ComboData;\n\n// Get multiple combo data\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter | Description    | Type     | Default | Required |\n| --------- | -------------- | -------- | ------- | -------- |\n| id        | Combo ID       | string   | -       |          |\n| ids       | Combo ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **Description**: Returns the specified combo data or combo data array\n\n**Example**:\n\n```typescript\n// Get all combos\nconst combos = graph.getComboData();\n\n// Get single combo\nconst combo = graph.getComboData('combo1');\nconsole.log('Nodes in combo:', combo.children);\n\n// Get multiple combos\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\nGet single element data, supporting two calling methods.\n\n⚠️ **Note**: This API directly gets the data of the element without considering the element type.\n\n```typescript\n// Get single element data\ngetElementData(id: ID): ElementDatum;\n\n// Get multiple element data\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type     | Default | Required |\n| --------- | ---------------- | -------- | ------- | -------- |\n| id        | Element ID       | string   | -       |          |\n| ids       | Element ID array | string[] | -       |          |\n\n**Return Value**:\n\n- **Type**: ElementDatum \\| ElementDatum[]\n- **Description**: Directly gets the data of the element without considering the element type\n\n**Example**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('Element data:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('Multiple element data:', elements);\n```\n\n### Graph.getElementDataByState()\n\nGet element data in a specified state, supporting three calling methods.\n\n```typescript\n// Get node data in a specified state\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// Get edge data in a specified state\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// Get combo data in a specified state\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**Parameters**:\n\n| Parameter   | Description  | Type                              | Default | Required |\n| ----------- | ------------ | --------------------------------- | ------- | -------- |\n| elementType | Element type | `'node'` \\| `'edge'` \\| `'combo'` | -       | ✓        |\n| state       | State        | string                            | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **Description**: Returns node data, edge data, or combo data in the specified state\n\n**Example**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('Selected nodes:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('Selected edges:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('Selected combos:', selectedCombos);\n```\n\n**Built-in States**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\nGet the data of neighbor nodes of a node or combo.\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: NodeData[]\n- **Description**: Returns neighbor node data\n\n**Example**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('Neighbor nodes:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\nGet the data of edges related to a node or combo.\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type                          | Default | Required |\n| --------- | ---------------- | ----------------------------- | ------- | -------- |\n| id        | Node or combo ID | string                        | -       | ✓        |\n| direction | Edge direction   | `'in'` \\| `'out'` \\| `'both'` | -       |          |\n\n**Return Value**:\n\n- **Type**: EdgeData[]\n- **Description**: Returns the data of edges related to the specified node or combo\n\n**Example**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('Related edges:', relatedEdges);\n```\n\n### Graph.getParentData()\n\nGet the data of the parent element of a node or combo.\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       |          |\n\n**Return Value**:\n\n- **Type**: NodeData \\| ComboData \\| undefined\n- **Description**: Returns the parent element data, or undefined if it does not exist\n\n**Example**:\n\n```typescript\n// Get the parent node in a tree graph\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// Get the parent combo in a combo\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\nGet the data of child elements of a node or combo.\n\n```typescript\ngetChildrenData(id: ID): (NodeData \\| ComboData)[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: (NodeData \\| ComboData)[]\n- **Description**: Returns an array of child element data\n\n**Note**:\n\n- **Querying combo's child elements**: If the id corresponds to a combo element, you can directly use this API to get all its child elements.\n- **Querying node's child elements**: If the id corresponds to a node, only when the graph data is a tree structure (i.e., the node data maintains a `children` field, and `children` is an array of child node IDs for that node), can you use this API to get the child elements of that node. Otherwise, an empty array is returned.\n\n**Example**:\n\n```typescript\n// Get the child elements of a combo\nconst children = graph.getChildrenData('combo1');\nconsole.log('Number of child nodes:', children.length);\n\n// Process each child element\nchildren.forEach((child) => {\n  console.log('Child element ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\nGet the data of all ancestor elements of a node or combo.\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description            | Type                  | Default | Required |\n| --------- | ---------------------- | --------------------- | ------- | -------- |\n| id        | Node or combo ID       | string                | -       | ✓        |\n| hierarchy | Specify hierarchy type | `'tree'` \\| `'combo'` | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of ancestor element data, ordered from parent to root\n\n**Example**:\n\n```typescript\n// Get all ancestor nodes in a tree graph\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  'Ancestor node path:',\n  treeAncestors.map((node) => node.id),\n);\n\n// Get all parent combos in a combo\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\nGet the data of all descendant elements of a node or combo.\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type   | Default | Required |\n| --------- | ---------------- | ------ | ------- | -------- |\n| id        | Node or combo ID | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **Description**: Returns an array of descendant element data\n\n**Example**:\n\n```typescript\n// Get all descendants of a node\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('Number of descendants:', descendants.length);\n\n// Process all descendant elements\ndescendants.forEach((descendant) => {\n  console.log('Descendant element ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\nSet the complete data of the graph.\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                        | Default | Required |\n| --------- | ----------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | New graph data or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Directly set data\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// Use functional incremental update: get current graph data and return new graph data\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\nAdd new element data.\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                              | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Graph data to add or a function returning new graph data | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\nAdd new node data.\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                        | Default | Required |\n| --------- | -------------------------------------------------- | ----------------------------------------------------------- | ------- | -------- |\n| data      | Node data to add or a function returning node data | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single node\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: 'Node 1' },\n  },\n]);\n\n// Add multiple nodes\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// Functional addition\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\nAdd new edge data.\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                        | Type                                                          | Default | Required |\n| --------- | -------------------------------------------------- | ------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to add or a function returning edge data | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Add single edge\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: 'Relation',\n    },\n  },\n]);\n\n// Add multiple edges\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// Functional addition\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\nAdd new combo data.\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                          | Type                                                            | Default | Required |\n| --------- | ---------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to add or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\nAdd child node data to a tree graph node.\n\n⚠️ **Note**: Use addNodeData / addComboData methods to add child nodes to a combo.\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**Parameters**:\n\n| Parameter    | Description     | Type                    | Default | Required |\n| ------------ | --------------- | ----------------------- | ------- | -------- |\n| parentId     | Parent node ID  | string                  | -       | ✓        |\n| childrenData | Child node data | [NodeData](#nodedata)[] | -       | ✓        |\n\n**Example**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\nRemove element data.\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                               | Type                                               | Default | Required |\n| --------- | --------------------------------------------------------- | -------------------------------------------------- | ------- | -------- |\n| ids       | Element IDs to remove or a function returning element IDs | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\nRemove node data.\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Node IDs to remove or a function returning node IDs | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\nRemove edge data.\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                         | Type                                                            | Default | Required |\n| --------- | --------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Edge IDs to remove or a function returning edge IDs | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\nRemove combo data.\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                            | Default | Required |\n| --------- | ----------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ids       | Combo IDs to remove or a function returning combo IDs | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\nUpdate element data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                 | Type                                                                             | Default | Required |\n| --------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Element data to update or a function returning element data | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\nUpdate node data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                           | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------- | ------- | -------- |\n| data      | Node data to update or a function returning node data | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\nUpdate edge data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                           | Type                                                                                                                         | Default | Required |\n| --------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- | -------- |\n| data      | Edge data to update or a function returning edge data | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\nUpdate combo data.\n\n⚠️ **Note**: Only the data that needs to be updated needs to be passed in, not the complete data.\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**Parameters**:\n\n| Parameter | Description                                             | Type                                                            | Default | Required |\n| --------- | ------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| data      | Combo data to update or a function returning combo data | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\nDetermine if an node exists\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n| Parameter | Description | Type | Default | Required |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id | Node ID to be judged | [ID](#id) | - | ✓ |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\nDetermine if an edge exists\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description          | Type      | Default | Required |\n| --------- | -------------------- | --------- | ------- | -------- |\n| id        | Edge ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\nDetermine if combo exists\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| Parameter | Description           | Type      | Default | Required |\n| --------- | --------------------- | --------- | ------- | -------- |\n| id        | Combo ID to be judged | [ID](#id) | -       | ✓        |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## Type Definitions\n\n### ID\n\nElement ID type.\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\nMultiple element ID type.\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 graph data type.\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\nNode data type.\n\n```typescript\ninterface NodeData {\n  id: string; // Node ID\n  type?: string; // Node type\n  data?: Record<string, any>; // Node data\n  style?: Record<string, any>; // Node style\n  states?: string[]; // Initial node states\n  combo?: string; // Belonging combo\n  children?: string[]; // Array of child node IDs\n}\n```\n\nFor detailed type definitions, please refer to [Node Data](/en/manual/data#nodedata).\n\n### EdgeData\n\nEdge data type.\n\n```typescript\ninterface EdgeData {\n  source: string; // Source ID\n  target: string; // Target ID\n  id?: string; // Edge ID\n  type?: string; // Edge type\n  data?: Record<string, any>; // Edge data\n  style?: Record<string, any>; // Edge style\n  states?: string[]; // Initial edge states\n}\n```\n\nFor detailed type definitions, please refer to [Edge Data](/en/manual/data#edgedata).\n\n### ComboData\n\nCombo data type.\n\n```typescript\ninterface ComboData {\n  id: string; // Combo ID\n  type?: string; // Combo type\n  data?: Record<string, any>; // Combo data\n  style?: Record<string, any>; // Combo style\n  states?: string[]; // Initial combo states\n  combo?: string; // Parent combo ID\n}\n```\n\nFor detailed type definitions, please refer to [Combo Data](/en/manual/data#combodata).\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/data.zh.md) -->\n---\ntitle: 数据\norder: 0\n---\n\n## 数据操作概述\n\nG6 提供了一套全面的 [数据](/manual/data) 操作 API，覆盖了图数据从查询、修改到更新的完整生命周期。\n\n## API 参考\n\n### Graph.getData()\n\n获取图的完整数据。\n\n```typescript\ngetData(): Required<GraphData>;\n```\n\n**返回值**:\n\n- **类型**: [GraphData](#graphdata)\n\n- **描述**: 返回包含所有节点、边和组合数据的完整图数据\n\n**示例**:\n\n```typescript\nconst graphData = graph.getData();\nconsole.log('节点数据:', graphData.nodes);\nconsole.log('边数据:', graphData.edges);\nconsole.log('组合数据:', graphData.combos);\n```\n\n### Graph.getNodeData()\n\n获取节点数据，支持三种调用方式。\n\n```typescript\n// 获取所有节点数据\ngetNodeData(): NodeData[];\n\n// 获取单个节点数据\ngetNodeData(id: ID): NodeData;\n\n// 批量获取多个节点数据\ngetNodeData(ids: ID[]): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 节点 ID      | string   | -      |      |\n| ids  | 节点 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata) | [NodeData](#nodedata)[]\n- **描述**: 返回指定的节点数据或节点数据数组\n\n**示例**:\n\n```typescript\n// 获取所有节点\nconst nodes = graph.getNodeData();\n\n// 获取单个节点\nconst node = graph.getNodeData('node1');\nconsole.log('节点位置:', node.style.x, node.style.y);\n\n// 获取多个节点\nconst [node1, node2] = graph.getNodeData(['node1', 'node2']);\n```\n\n### Graph.getEdgeData()\n\n获取边数据，支持三种调用方式。\n\n```typescript\n// 获取所有边数据\ngetEdgeData(): EdgeData[];\n\n// 获取单条边数据\ngetEdgeData(id: ID): EdgeData;\n\n// 批量获取多条边数据\ngetEdgeData(ids: ID[]): EdgeData[];\n```\n\n**参数**:\n\n| 参数 | 描述       | 类型     | 默认值 | 必选 |\n| ---- | ---------- | -------- | ------ | ---- |\n| id   | 边 ID      | string   | -      |      |\n| ids  | 边 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [EdgeData](#edgedata) | [EdgeData](#edgedata)[]\n- **描述**: 返回指定的边数据或边数据数组\n\n**示例**:\n\n```typescript\n// 获取所有边\nconst edges = graph.getEdgeData();\n\n// 获取单条边\nconst edge = graph.getEdgeData('edge1');\nconsole.log('边的起点和终点:', edge.source, edge.target);\n\n// 获取多条边\nconst [edge1, edge2] = graph.getEdgeData(['edge1', 'edge2']);\n```\n\n### Graph.getComboData()\n\n获取组合数据,支持三种调用方式。\n\n```typescript\n// 获取所有组合数据\ngetComboData(): ComboData[];\n\n// 获取单个组合数据\ngetComboData(id: ID): ComboData;\n\n// 批量获取多个组合数据\ngetComboData(ids: ID[]): ComboData[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 组合 ID      | string   | -      |      |\n| ids  | 组合 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: [ComboData](#combodata) | [ComboData](#combodata)[]\n- **描述**: 返回指定的组合数据或组合数据数组\n\n**示例**:\n\n```typescript\n// 获取所有组合\nconst combos = graph.getComboData();\n\n// 获取单个组合\nconst combo = graph.getComboData('combo1');\nconsole.log('组合包含的节点:', combo.children);\n\n// 获取多个组合\nconst [combo1, combo2] = graph.getComboData(['combo1', 'combo2']);\n```\n\n### Graph.getElementData()\n\n获取单个元素数据，支持两种调用方式。\n\n⚠️ **注意**: 此 API 直接获取元素的数据而不必考虑元素类型。\n\n```typescript\n// 获取单个元素数据\ngetElementData(id: ID): ElementDatum;\n\n// 批量获取多个元素数据\ngetElementData(ids: ID[]): ElementDatum[];\n```\n\n**参数**:\n\n| 参数 | 描述         | 类型     | 默认值 | 必选 |\n| ---- | ------------ | -------- | ------ | ---- |\n| id   | 元素 ID      | string   | -      |      |\n| ids  | 元素 ID 数组 | string[] | -      |      |\n\n**返回值**:\n\n- **类型**: ElementDatum \\| ElementDatum[]\n- **描述**: 直接获取元素的数据而不必考虑元素类型\n\n**示例**:\n\n```typescript\nconst element = graph.getElementData('node-1');\nconsole.log('元素数据:', element);\n\nconst elements = graph.getElementData(['node-1', 'edge-1']);\nconsole.log('多个元素数据:', elements);\n```\n\n### Graph.getElementDataByState()\n\n获取指定状态下的元素数据，支持三种调用方式。\n\n```typescript\n// 获取指定状态下的节点数据\ngetElementDataByState(elementType: 'node', state: string): NodeData[];\n\n// 获取指定状态下的边数据\ngetElementDataByState(elementType: 'edge', state: string): EdgeData[];\n\n// 获取指定状态下的组合数据\ngetElementDataByState(elementType: 'combo', state: string): ComboData[];\n```\n\n**参数**:\n\n| 参数        | 描述     | 类型                              | 默认值 | 必选 |\n| ----------- | -------- | --------------------------------- | ------ | ---- |\n| elementType | 元素类型 | `'node'` \\| `'edge'` \\| `'combo'` | -      | ✓    |\n| state       | 状态     | string                            | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[] \\| EdgeData[] \\| ComboData[]\n- **描述**: 返回指定状态下的节点数据、边数据或组合数据\n\n**示例**:\n\n```typescript\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\nconsole.log('选中的节点:', selectedNodes);\n\nconst selectedEdges = graph.getElementDataByState('edge', 'selected');\nconsole.log('选中的边:', selectedEdges);\n\nconst selectedCombos = graph.getElementDataByState('combo', 'selected');\nconsole.log('选中的组合:', selectedCombos);\n```\n\n**内置状态**:\n\n- `'selected'`\n- `'highlight'`\n- `'active'`\n- `'inactive'`\n- `'disabled'`\n\n### Graph.getNeighborNodesData()\n\n获取节点或组合的一跳邻居节点数据。\n\n```typescript\ngetNeighborNodesData(id: ID): NodeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: NodeData[]\n- **描述**: 返回邻居节点数据\n\n**示例**:\n\n```typescript\nconst neighbors = graph.getNeighborNodesData('node-1');\nconsole.log('邻居节点:', neighbors);\n```\n\n### Graph.getRelatedEdgesData()\n\n获取节点或组合关联边的数据。\n\n```typescript\ngetRelatedEdgesData(id: ID, direction?: EdgeDirection): EdgeData[];\n```\n\n**参数**:\n\n| 参数      | 描述            | 类型                          | 默认值 | 必选 |\n| --------- | --------------- | ----------------------------- | ------ | ---- |\n| id        | 节点或组合的 ID | string                        | -      | ✓    |\n| direction | 边的方向        | `'in'` \\| `'out'` \\| `'both'` | -      |      |\n\n**返回值**:\n\n- **类型**: EdgeData[]\n- **描述**: 返回与指定节点或组合关联的边数据\n\n**示例**:\n\n```typescript\nconst relatedEdges = graph.getRelatedEdgesData('node-1');\nconsole.log('关联边:', relatedEdges);\n```\n\n### Graph.getParentData()\n\n获取节点或组合的父元素数据。\n\n```typescript\ngetParentData(id: ID, hierarchy: HierarchyKey): NodeLikeData | undefined;\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      |      |\n\n**返回值**:\n\n- **类型**: NodeData \\| ComboData \\| undefined\n- **描述**: 返回父元素数据,如果不存在则返回 undefined\n\n**示例**:\n\n```typescript\n// 获取树图中节点的父节点\nconst treeParent = graph.getParentData('node1', 'tree');\n\n// 获取组合中节点的父组合\nconst comboParent = graph.getParentData('node1', 'combo');\n```\n\n### Graph.getChildrenData()\n\n获取节点或组合的子元素数据。\n\n```typescript\ngetChildrenData(id: ID):(NodeData \\| ComboData)[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: (NodeData \\| ComboData)[]\n- **描述**: 返回子元素数据数组\n\n**注意**:\n\n- **查询 combo 的子元素**：如果 id 对应的是 combo 元素，可以直接通过此 API 获取其所有子元素。\n- **查询节点的子元素**：如果 id 对应的是节点，只有当图数据为树结构（即节点数据中维护有 `children` 字段，且 `children` 为该节点的子节点 ID 数组）时，才能通过此 API 获取到该节点的子元素。否则返回空数组。\n\n**示例**:\n\n```typescript\n// 获取组合的子元素\nconst children = graph.getChildrenData('combo1');\nconsole.log('子节点数量:', children.length);\n\n// 处理每个子元素\nchildren.forEach((child) => {\n  console.log('子元素ID:', child.id);\n});\n```\n\n### Graph.getAncestorsData()\n\n获取节点或组合的所有祖先元素数据。\n\n```typescript\ngetAncestorsData(id: ID, hierarchy: HierarchyKey): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数      | 描述             | 类型                  | 默认值 | 必选 |\n| --------- | ---------------- | --------------------- | ------ | ---- |\n| id        | 节点或组合的 ID  | string                | -      | ✓    |\n| hierarchy | 指定层级关系类型 | `'tree'` \\| `'combo'` | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回祖先元素数据数组，从父节点到根节点的顺序排列\n\n**示例**:\n\n```typescript\n// 获取树图中节点的所有祖先节点\nconst treeAncestors = graph.getAncestorsData('node1', 'tree');\nconsole.log(\n  '祖先节点路径:',\n  treeAncestors.map((node) => node.id),\n);\n\n// 获取组合中节点的所有父组合\nconst comboAncestors = graph.getAncestorsData('node1', 'combo');\n```\n\n### Graph.getDescendantsData()\n\n获取节点或组合的所有后代元素数据。\n\n```typescript\ngetDescendantsData(id: ID): NodeLikeData[];\n```\n\n**参数**:\n\n| 参数 | 描述            | 类型   | 默认值 | 必选 |\n| ---- | --------------- | ------ | ------ | ---- |\n| id   | 节点或组合的 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [NodeData](#nodedata)[] \\| [ComboData](#combodata)[]\n- **描述**: 返回后代元素数据数组\n\n**示例**:\n\n```typescript\n// 获取节点的所有后代\nconst descendants = graph.getDescendantsData('node1');\nconsole.log('后代数量:', descendants.length);\n\n// 处理所有后代元素\ndescendants.forEach((descendant) => {\n  console.log('后代元素ID:', descendant.id);\n});\n```\n\n### Graph.setData()\n\n设置图的完整数据。\n\n```typescript\nsetData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                           | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 新的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 直接设置数据\ngraph.setData({\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 } },\n    { id: 'node2', style: { x: 200, y: 200 } },\n  ],\n  edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n});\n\n// 使用函数式增量更新：获取当前图数据，并返回新的图数据\ngraph.setData((prev) => ({\n  ...prev,\n  nodes: [...prev.nodes, { id: 'node3', style: { x: 300, y: 300 } }],\n}));\n```\n\n### Graph.addData()\n\n新增元素数据。\n\n```typescript\naddData(data: GraphData | ((prev: GraphData) => GraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 需要添加的图数据或返回新图数据的函数 | [GraphData](#graphdata) \\| ((prev: GraphData) => GraphData) | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node-1' }, { id: 'node-2' }],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n});\n```\n\n### Graph.addNodeData()\n\n新增节点数据。\n\n```typescript\naddNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                        | 默认值 | 必选 |\n| ---- | ------------------------------------ | ----------------------------------------------------------- | ------ | ---- |\n| data | 要添加的节点数据或返回节点数据的函数 | [NodeData](#nodedata)[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node1',\n    style: { x: 100, y: 100 },\n    data: { label: '节点 1' },\n  },\n]);\n\n// 批量添加节点\ngraph.addNodeData([\n  { id: 'node2', style: { x: 200, y: 200 } },\n  { id: 'node3', style: { x: 300, y: 300 } },\n]);\n\n// 函数式添加\ngraph.addNodeData((prev) => [...prev, { id: 'node4', style: { x: 400, y: 400 } }]);\n```\n\n### Graph.addEdgeData()\n\n新增边数据。\n\n```typescript\naddEdgeData(data: EdgeData[] | ((prev: EdgeData[]) => EdgeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                          | 默认值 | 必选 |\n| ---- | -------------------------------- | ------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的边数据或返回边数据的函数 | [EdgeData](#edgedata)[] \\| ((prev: EdgeData[]) => EdgeData[]) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 添加单条边\ngraph.addEdgeData([\n  {\n    id: 'edge1',\n    source: 'node1',\n    target: 'node2',\n    data: {\n      weight: 1,\n      label: '关系',\n    },\n  },\n]);\n\n// 批量添加边\ngraph.addEdgeData([\n  { id: 'edge2', source: 'node2', target: 'node3' },\n  { id: 'edge3', source: 'node3', target: 'node1' },\n]);\n\n// 函数式添加\ngraph.addEdgeData((prev) => [...prev, { id: 'edge4', source: 'node1', target: 'node4' }]);\n```\n\n### Graph.addComboData()\n\n新增组合数据。\n\n```typescript\naddComboData(data: ComboData[] | ((prev: ComboData[]) => ComboData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要添加的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addComboData([{ id: 'combo1', children: ['node1', 'node2'] }]);\n```\n\n### Graph.addChildrenData()\n\n为树图节点添加子节点数据。\n\n⚠️ **注意**: 为组合添加子节点使用 addNodeData / addComboData 方法。\n\n```typescript\naddChildrenData(parentId: ID, childrenData: NodeData[]): void;\n```\n\n**参数**:\n\n| 参数         | 描述       | 类型                    | 默认值 | 必选 |\n| ------------ | ---------- | ----------------------- | ------ | ---- |\n| parentId     | 父节点 ID  | string                  | -      | ✓    |\n| childrenData | 子节点数据 | [NodeData](#nodedata)[] | -      | ✓    |\n\n**示例**:\n\n```typescript\ngraph.addChildrenData('node1', [{ id: 'node2' }]);\n```\n\n### Graph.removeData()\n\n删除元素数据。\n\n```typescript\nremoveData(ids: DataID | ((data: GraphData) => DataID)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                               | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的元素 ID 或返回元素 ID 的函数 | [DataID](#dataid) \\| ((data: GraphData) => DataID) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeData({\n  nodes: ['node-1', 'node-2'],\n  edges: ['edge-1'],\n});\n```\n\n### Graph.removeNodeData()\n\n删除节点数据。\n\n```typescript\nremoveNodeData(ids: ID[] | ((data: NodeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的节点 ID 或返回节点 ID 的函数 | [ID](#id)[] \\| ((data: [NodeData](#nodedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeNodeData(['node-1', 'node-2']);\n```\n\n### Graph.removeEdgeData()\n\n删除边数据。\n\n```typescript\nremoveEdgeData(ids: ID[] | ((data: EdgeData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                            | 默认值 | 必选 |\n| ---- | -------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的边 ID 或返回边 ID 的函数 | [ID](#id)[] \\| ((data: [EdgeData](#edgedata)[]) => [ID](#id)[]) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeEdgeData(['edge-1']);\n```\n\n### Graph.removeComboData()\n\n删除组合数据。\n\n```typescript\nremoveComboData(ids: ID[] | ((data: ComboData[]) => ID[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| ids  | 要删除的组合 ID 或返回组合 ID 的函数 | [ID](#id)[] \\| (data: [ComboData](#combodata)[]) => [ID](#id)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.removeComboData(['combo-1']);\n```\n\n### Graph.updateData()\n\n更新元素数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateData(data: PartialGraphData | ((prev: GraphData) => PartialGraphData)): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                                             | 默认值 | 必选 |\n| ---- | ------------------------------------ | -------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的元素数据或返回元素数据的函数 | [PartialGraphData](#partialgraphdata) \\| ((prev: GraphData) => PartialGraphData) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateData({\n  nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  edges: [{ id: 'edge-1', style: { lineWidth: 2 } }],\n});\n```\n\n### Graph.updateNodeData()\n\n更新节点数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateNodeData(data: NodeData[] | ((prev: NodeData[]) => NodeData[])): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                           | 默认值 | 必选 |\n| ---- | ------------------------------------ | ---------------------------------------------- | ------ | ---- |\n| data | 要更新的节点数据或返回节点数据的函数 | NodeData[] \\| (prev: NodeData[]) => NodeData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.updateEdgeData()\n\n更新边数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateEdgeData(data: (PartialEdgeData<EdgeData>[] | ((prev: EdgeData[]) => PartialEdgeData<EdgeData>[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                             | 类型                                                                                                                         | 默认值 | 必选 |\n| ---- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的边数据或返回边数据的函数 | [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] \\| (prev: EdgeData[]) => [PartialEdgeData\\<EdgeData\\>](#partialedgedata)[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateEdgeData([{ id: 'edge-1', style: { lineWidth: 2 } }]);\n```\n\n### Graph.updateComboData()\n\n更新组合数据。\n\n⚠️ **注意**: 只需要传入需要更新的数据即可，不必传入完整的数据。\n\n```typescript\nupdateComboData(data: (ComboData[] | ((prev: ComboData[]) => ComboData[]))): void;\n```\n\n**参数**:\n\n| 参数 | 描述                                 | 类型                                                            | 默认值 | 必选 |\n| ---- | ------------------------------------ | --------------------------------------------------------------- | ------ | ---- |\n| data | 要更新的组合数据或返回组合数据的函数 | [ComboData](#combodata)[] \\| (prev: ComboData[]) => ComboData[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\ngraph.updateComboData([{ id: 'combo-1', style: { x: 100, y: 100 } }]);\n```\n\n### Graph.hasNode()\n\n判断节点是否存在\n\n```typescript\nhasNode(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                 | 类型      | 默认值 | 必选 |\n| ---- | -------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的节点id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasNode('node-1');\n```\n\n### Graph.hasEdge()\n\n判断边是否存在\n\n```typescript\nhasEdge(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述               | 类型      | 默认值 | 必选 |\n| ---- | ------------------ | --------- | ------ | ---- |\n| id   | 需要进行判断的边id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasEdge('edge-1');\n```\n\n### Graph.hasCombo()\n\n判断combo是否存在\n\n```typescript\nhasCombo(id:ID): boolean;\n```\n\n**参数**:\n\n| 参数 | 描述                      | 类型      | 默认值 | 必选 |\n| ---- | ------------------------- | --------- | ------ | ---- |\n| id   | 需要进行判断的combo组合id | [ID](#id) | -      | ✓    |\n\n**返回值**:\n\n- **类型**: boolean\n  **示例**:\n\n```typescript\ngraph.hasCombo('combo-1');\n```\n\n## 类型定义\n\n### ID\n\n元素 ID 类型。\n\n```typescript\ntype ID = string;\n```\n\n### DataID\n\n多个元素 ID 类型。\n\n```typescript\ninterface DataID {\n  nodes?: ID[];\n  edges?: ID[];\n  combos?: ID[];\n}\n```\n\n### GraphData\n\nG6 图数据类型。\n\n```typescript\ninterface GraphData {\n  nodes?: NodeData[];\n  edges?: EdgeData[];\n  combos?: ComboData[];\n}\n```\n\n### NodeData\n\n节点数据类型。\n\n```typescript\ninterface NodeData {\n  id: string; // 节点 ID\n  type?: string; // 节点类型\n  data?: Record<string, any>; // 节点数据\n  style?: Record<string, any>; // 节点样式\n  states?: string[]; // 节点初始状态\n  combo?: string; // 所属组合\n  children?: string[]; // 子节点 ID 数组\n}\n```\n\n详细类型定义请参考 [节点数据](/manual/data#节点数据nodedata)。\n\n### EdgeData\n\n边数据类型。\n\n```typescript\ninterface EdgeData {\n  source: string; // 起点 ID\n  target: string; // 终点 ID\n  id?: string; // 边 ID\n  type?: string; // 边类型\n  data?: Record<string, any>; // 边数据\n  style?: Record<string, any>; // 边样式\n  states?: string[]; // 边初始状态\n}\n```\n\n详细类型定义请参考 [边数据](/manual/data#边数据edgedata)。\n\n### ComboData\n\n组合数据类型。\n\n```typescript\ninterface ComboData {\n  id: string; // 组合 ID\n  type?: string; // 组合类型\n  data?: Record<string, any>; // 组合数据\n  style?: Record<string, any>; // 组合样式\n  states?: string[]; // 组合初始状态\n  combo?: string; // 父组合 ID\n}\n```\n\n详细类型定义请参考 [组合数据](/manual/data#组合数据combodata)。\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/element.en.md) -->\n---\ntitle: Element Operations\norder: 1\n---\n\n## Overview of Element Operations\n\nThe [Element](/en/manual/element/overview) operation API in G6 allows you to control the behavior and attributes of elements such as nodes, edges, and Combos in the graph. These APIs can be used for:\n\n1. **Element State Management**: Set, update, or remove the state of elements\n2. **Element Display Control**: Control the z-index and visibility of elements\n3. **Element Collapse/Expand**: Operate the collapse/expand state of collapsible elements\n4. **Element Position Operations**: Move and align element positions\n5. **Element Focus**: Focus the viewport on specific elements\n\nThrough these operations, you can achieve rich interactive effects and visual presentations.\n\n## API Reference\n\n### Graph.getElementPosition(id)\n\nGet the position of an element.\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [number, number] \\| [number, number, number]\n- **Description**: Returns the coordinates of the element\n\n**Example**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\nGet the rendering bounding box of the element itself and its child nodes in the world coordinate system.\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [AABB](#aabb)\n- **Description**: Returns the rendering bounding box of the element\n\n### Graph.getElementRenderStyle(id)\n\nGet the rendering style of an element.\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Record<string, any>\n- **Description**: Returns the rendering style of the element\n\n### Graph.getElementState(id)\n\nGet the state of an element.\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: [State](#state)[]\n- **Description**: Returns the state of the element\n\n### Graph.getElementType(id)\n\nGet the type of an element.\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: string\n- **Description**: Returns the type of the element\n\n### Graph.getElementVisibility(id)\n\nGet the visibility of an element.\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden';\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: 'visible' | 'hidden'\n- **Description**: Returns the visibility of the element\n\n### Graph.getElementZIndex(id)\n\nGet the z-index of an element.\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: number\n- **Description**: Returns the z-index of the element\n\n### Graph.setElementState(id, state, options)\n\nSet the state of an element, supporting two calling methods:\n\n```typescript\n// Set the state of a single element\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// Set the state of multiple elements\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element State Setting**\n\n| Parameter | Description       | Type            | Default | Required |\n| --------- | ----------------- | --------------- | ------- | -------- | --- |\n| id        | Element ID to set | string          | -       | ✓        |\n| state     | State to set      | [State](#state) | State[] | -        | ✓   |\n| animation | Enable animation  | boolean         | -       |          |\n\n**Batch Element State Setting**\n\n| Parameter | Description                    | Type                       | Default  | Required |\n| --------- | ------------------------------ | -------------------------- | -------- | -------- | --- |\n| state     | Mapping of element ID to state | Record<ID, [State](#state) | State[]> | -        | ✓   |\n| animation | Enable animation               | boolean                    | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the state setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the state of a single element\nawait graph.setElementState('node1', 'selected');\n\n// Set the state of multiple elements\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\nSet the visibility of an element, supporting two calling methods:\n\n```typescript\n// Set the visibility of a single element\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// Set the visibility of multiple elements\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Visibility Setting**\n\n| Parameter  | Description       | Type      | Default  | Required |\n| ---------- | ----------------- | --------- | -------- | -------- | --- |\n| id         | Element ID to set | string    | -        | ✓        |\n| visibility | Visibility to set | 'visible' | 'hidden' | -        | ✓   |\n| animation  | Enable animation  | boolean   | -        |          |\n\n**Batch Element Visibility Setting**\n\n| Parameter  | Description                         | Type                 | Default   | Required |\n| ---------- | ----------------------------------- | -------------------- | --------- | -------- | --- |\n| visibility | Mapping of element ID to visibility | Record<ID, 'visible' | 'hidden'> | -        | ✓   |\n| animation  | Enable animation                    | boolean              | -         |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the visibility setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the visibility of a single element\nawait graph.setElementVisibility('node1', 'hidden');\n\n// Set the visibility of multiple elements\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\nSet the z-index of an element, supporting two calling methods:\n\n```typescript\n// Set the z-index of a single element\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// Set the z-index of multiple elements\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Z-Index Setting**\n\n| Parameter | Description | Type   | Default | Required |\n| --------- | ----------- | ------ | ------- | -------- |\n| id        | Element ID  | string | -       | ✓        |\n| zIndex    | Z-Index     | number | -       | ✓        |\n\n**Batch Element Z-Index Setting**\n\n| Parameter | Description                      | Type               | Default | Required |\n| --------- | -------------------------------- | ------------------ | ------- | -------- |\n| zIndex    | Mapping of element ID to z-index | Record<ID, number> | -       | ✓        |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the z-index setting operation is complete\n\n**Example**:\n\n```typescript\n// Set the z-index of a single element\nawait graph.setElementZIndex('node1', 10);\n\n// Set the z-index of multiple elements\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\nSet the node style mapping, i.e., the value of `options.node`.\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| node      | Node configuration | [NodeOptions](/en/manual/element/node/overview) | -       | ✓        |\n\n**Example**:\n\n```typescript\n// Set the fill color of all nodes to red\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\nSet the edge style mapping, i.e., the value of `options.edge`.\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description        | Type                                            | Default | Required |\n| --------- | ------------------ | ----------------------------------------------- | ------- | -------- |\n| edge      | Edge configuration | [EdgeOptions](/en/manual/element/edge/overview) | -       | ✓        |\n\n### Graph.setCombo(combo)\n\nSet the combo style mapping, i.e., the value of `options.combo`.\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**Parameters**:\n\n| Parameter | Description         | Type                                              | Default | Required |\n| --------- | ------------------- | ------------------------------------------------- | ------- | -------- |\n| combo     | Combo configuration | [ComboOptions](/en/manual/element/combo/overview) | -       | ✓        |\n\n### Graph.collapseElement(id, options)\n\nCollapse the specified element, usually used to collapse Combos or nodes with child elements.\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                     | Type    | Default                                                 | Required |\n| --------- | --------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to collapse                                          | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for collapsing nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the collapse operation is complete\n\n**Example**:\n\n```typescript\n// Simple collapse with default configuration\nawait graph.collapseElement('combo1');\n\n// Collapse with animation\ngraph.collapseElement('combo1', true);\n\n// Collapse while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\nExpand the specified element, usually used to expand previously collapsed Combos or nodes.\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                                                    | Type    | Default                                                 | Required |\n| --------- | -------------------------------------------------------------- | ------- | ------------------------------------------------------- | -------- | --- |\n| id        | Element ID to expand                                           | string  | -                                                       | ✓        |\n| options   | Enable animation or detailed configuration for expanding nodes | boolean | [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -        |     |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the expand operation is complete\n\n**Example**:\n\n```typescript\n// Simple expand with default configuration\nawait graph.expandElement('combo1');\n\n// Expand with animation\nawait graph.expandElement('combo1', true);\n\n// Expand while ensuring the position of expanded/collapsed nodes remains unchanged\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\nBring the specified element to the front, making it appear above other overlapping elements.\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**Parameters**:\n\n| Parameter | Description | Type   | Default  | Required |\n| --------- | ----------- | ------ | -------- | -------- | --- |\n| id        | Element ID  | string | string[] | -        | ✓   |\n\n**Return Value**:\n\n- **Type**: void\n\n**Example**:\n\n```typescript\n// Bring a node to the front\ngraph.frontElement('node1');\n\n// Bring multiple selected nodes to the front\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\nShow the specified element.\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the show operation is complete\n\n**Example**:\n\n```typescript\n// Show a single element\nawait graph.showElement('node1');\n\n// Show an element with animation\nawait graph.showElement('node1', true);\n\n// Show multiple elements\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\nHide the specified element.\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description      | Type    | Default  | Required |\n| --------- | ---------------- | ------- | -------- | -------- | --- |\n| id        | Element ID       | string  | string[] | -        | ✓   |\n| animation | Enable animation | boolean | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the hide operation is complete\n\n**Example**:\n\n```typescript\n// Hide an element without animation\nawait graph.hideElement('node1');\n\n// Hide an element with animation\nawait graph.hideElement('node1', true);\n\n// Hide multiple elements\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\nTranslate an element by a specified distance, supporting two calling methods:\n\n```typescript\n// Translate an element by a specified distance (relative translation)\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// Translate multiple elements by a specified distance (relative translation)\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Translation**\n\n| Parameter | Description                            | Type             | Default | Required |\n| --------- | -------------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                             | string           | -       | ✓        |\n| offset    | Relative translation distance [dx, dy] | [number, number] | -       | ✓        |\n| animation | Enable animation                       | boolean          | -       |          |\n\n**Batch Element Translation**\n\n| Parameter | Description                                   | Type                         | Default | Required |\n| --------- | --------------------------------------------- | ---------------------------- | ------- | -------- |\n| offsets   | Mapping of element ID to translation distance | Record<ID, [number, number]> | -       | ✓        |\n| animation | Enable animation                              | boolean                      | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the translation operation is complete\n\n**Example**:\n\n```typescript\n// Translate right by 100 pixels and down by 50 pixels\nawait graph.translateElementBy('node1', [100, 50]);\n\n// Translate with animation\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// Apply the same translation to multiple nodes\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\nMove an element to a specified position, supporting two calling methods:\n\n```typescript\n// Move an element to a specified position (absolute position)\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// Move multiple elements to specified positions (absolute position)\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**Parameters**:\n\n**Single Element Movement**\n\n| Parameter | Description                     | Type             | Default | Required |\n| --------- | ------------------------------- | ---------------- | ------- | -------- |\n| id        | Element ID                      | string           | -       | ✓        |\n| position  | Target absolute position [x, y] | [number, number] | -       | ✓        |\n| animation | Enable animation                | boolean          | -       |          |\n\n**Batch Element Movement**\n\n| Parameter | Description                              | Type                             | Default | Required |\n| --------- | ---------------------------------------- | -------------------------------- | ------- | -------- |\n| positions | Mapping of element ID to target position | Record<string, [number, number]> | -       | ✓        |\n| animation | Enable animation                         | boolean                          | -       |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the movement operation is complete\n\n**Example**:\n\n```typescript\n// Move a node to position (200, 300) on the canvas\nawait graph.translateElementTo('node1', [200, 300]);\n\n// Move with animation\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// Arrange a group of nodes neatly\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\nFocus on the specified element, centering it in the viewport.\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**:\n\n| Parameter | Description                         | Type                                                            | Default  | Required |\n| --------- | ----------------------------------- | --------------------------------------------------------------- | -------- | -------- | --- |\n| id        | One or more element IDs to focus on | string                                                          | string[] | -        | ✓   |\n| animation | Viewport animation configuration    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -        |          |\n\n**Return Value**:\n\n- **Type**: Promise<void>\n- **Description**: Returns a Promise that resolves when the focus operation is complete\n\n**Example**:\n\n```typescript\n// Focus on a single node\nawait graph.focusElement('node1');\n\n// Use custom animation configuration\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// Focus on multiple nodes\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## Type Definitions\n\n### CollapseExpandNodeOptions\n\nConfiguration options for collapsing or expanding elements.\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * Enable animation\n   */\n  animation?: boolean;\n  /**\n   * Ensure the position of expanded/collapsed nodes remains unchanged\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) is a fundamental concept in computer graphics.\n\n```typescript\ninterface AABB {\n  x: number; // x-coordinate of the top-left corner of the rectangle\n  y: number; // y-coordinate of the top-left corner of the rectangle\n  width: number; // Width of the rectangle\n  height: number; // Height of the rectangle\n}\n```\n\n### State\n\nElement state type.\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/element.zh.md) -->\n---\ntitle: 元素操作\norder: 1\n---\n\n## 元素操作概述\n\nG6 中的 [元素](/manual/element/overview) 操作 API 允许您控制图中节点、边和组合(Combo)等元素的行为和属性。这些 API 可以用于：\n\n1. **元素状态管理**：设置、更新或移除元素的状态\n2. **元素显示控制**：控制元素的层级、可见性\n3. **元素展开/收起**：操作可折叠元素的展开/收起状态\n4. **元素位置操作**：移动、对齐元素位置\n5. **元素聚焦**：将视口聚焦到特定元素\n\n通过这些操作，您可以实现丰富的交互效果和视觉呈现。\n\n## API 参考\n\n### Graph.getElementPosition(id)\n\n获取元素位置。\n\n```typescript\ngetElementPosition(id: ID): Point;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [number, number] \\| [number, number, number]\n- **描述**: 返回元素的坐标位置\n\n**示例**:\n\n```typescript\ngraph.getElementPosition('node1');\n```\n\n### Graph.getElementRenderBounds(id)\n\n获取元素自身以及子节点在世界坐标系下的渲染包围盒。\n\n```typescript\ngetElementRenderBounds(id: ID): AABB;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [AABB](#aabb)\n- **描述**: 返回元素的渲染包围盒\n\n### Graph.getElementRenderStyle(id)\n\n获取元素的渲染样式。\n\n```typescript\ngetElementRenderStyle(id: ID): Record<string, any>;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Record\\<string, any\\>\n- **描述**: 返回元素的渲染样式\n\n### Graph.getElementState(id)\n\n获取元素的状态。\n\n```typescript\ngetElementState(id: ID): State[];\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: [State](#state)[]\n- **描述**: 返回元素的状态\n\n### Graph.getElementType(id)\n\n获取元素类型。\n\n```typescript\ngetElementType(id: ID): string;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: string\n- **描述**: 返回元素的类型\n\n### Graph.getElementVisibility(id)\n\n获取元素可见性。\n\n```typescript\ngetElementVisibility(id: ID): 'visible' | 'hidden' ;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: 'visible' | 'hidden'\n- **描述**: 返回元素的可见性\n\n### Graph.getElementZIndex(id)\n\n获取元素层级。\n\n```typescript\ngetElementZIndex(id: ID): number;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型   | 默认值 | 必选 |\n| ---- | ------- | ------ | ------ | ---- |\n| id   | 元素 ID | string | -      | ✓    |\n\n**返回值**:\n\n- **类型**: number\n- **描述**: 返回元素的层级\n\n### Graph.setElementState(id, state, options)\n\n设置元素状态，支持两种调用方式：\n\n```typescript\n// 设置单个元素状态\nsetElementState(id: ID, state: State | State[], animation?: boolean): Promise<void>;\n\n// 批量设置元素状态\nsetElementState(state: Record<ID, State | State[]>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素状态设置**\n\n| 参数      | 描述                | 类型                       | 默认值 | 必选 |\n| --------- | ------------------- | -------------------------- | ------ | ---- |\n| id        | 要设置状态的元素 ID | string                     | -      | ✓    |\n| state     | 要设置的状态        | [State](#state) \\| State[] | -      | ✓    |\n| animation | 是否启用动画        | boolean                    | -      |      |\n\n**批量元素状态设置**\n\n| 参数      | 描述               | 类型                                   | 默认值 | 必选 |\n| --------- | ------------------ | -------------------------------------- | ------ | ---- |\n| state     | 元素ID到状态的映射 | Record<ID, [State](#state) \\| State[]> | -      | ✓    |\n| animation | 是否启用动画       | boolean                                | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，状态设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素状态\nawait graph.setElementState('node1', 'selected');\n\n// 设置多个元素状态\nawait graph.setElementState({\n  node1: 'selected',\n  node2: 'hover',\n  node3: ['selected', 'hover'],\n});\n```\n\n### Graph.setElementVisibility(id, visibility, animation)\n\n设置元素的可见性，支持两种调用方式：\n\n```typescript\n// 设置单个元素可见性\nsetElementVisibility(id: ID, visibility: 'visible' | 'hidden', animation?: boolean): Promise<void>;\n\n// 批量设置元素可见性\nsetElementVisibility(visibility: Record<ID, 'visible' | 'hidden'>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素可见性设置**\n\n| 参数       | 描述                  | 类型                      | 默认值 | 必选 |\n| ---------- | --------------------- | ------------------------- | ------ | ---- |\n| id         | 要设置可见性的元素 ID | string                    | -      | ✓    |\n| visibility | 要设置的可见性        | `'visible'` \\| `'hidden'` | -      | ✓    |\n| animation  | 是否启用动画          | boolean                   | -      |      |\n\n**批量元素可见性设置**\n\n| 参数       | 描述                 | 类型                                  | 默认值 | 必选 |\n| ---------- | -------------------- | ------------------------------------- | ------ | ---- |\n| visibility | 元素ID到可见性的映射 | Record<ID, `'visible'` \\| `'hidden'`> | -      | ✓    |\n| animation  | 是否启用动画         | boolean                               | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，可见性设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素可见性\nawait graph.setElementVisibility('node1', 'hidden');\n\n// 设置多个元素可见性\nawait graph.setElementVisibility({\n  node1: 'hidden',\n  node2: 'visibility',\n});\n```\n\n### Graph.setElementZIndex(id, zIndex)\n\n设置元素的层级，有两种调用方式：\n\n```typescript\n// 设置单个元素层级\nsetElementZIndex(id: ID, zIndex: number): Promise<void>;\n\n// 批量设置元素层级\nsetElementZIndex(zIndex: Record<ID, number>): Promise<void>;\n```\n\n**参数**:\n\n**单个元素层级设置**\n\n| 参数   | 描述    | 类型   | 默认值 | 必选 |\n| ------ | ------- | ------ | ------ | ---- |\n| id     | 元素 ID | string | -      | ✓    |\n| zIndex | 层级    | number | -      | ✓    |\n\n**批量元素层级设置**\n\n| 参数   | 描述               | 类型               | 默认值 | 必选 |\n| ------ | ------------------ | ------------------ | ------ | ---- |\n| zIndex | 元素ID到层级的映射 | Record<ID, number> | -      | ✓    |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，层级设置操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 设置单个元素层级\nawait graph.setElementZIndex('node1', 10);\n\n// 设置多个元素层级\nawait graph.setElementZIndex({\n  node1: 10,\n  node2: 20,\n  node3: 30,\n});\n```\n\n### Graph.setNode(node)\n\n设置节点样式映射。即 `options.node` 的值。\n\n```typescript\nsetNode(node: NodeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述     | 类型                                         | 默认值 | 必选 |\n| ---- | -------- | -------------------------------------------- | ------ | ---- |\n| node | 节点配置 | [NodeOptions](/manual/element/node/overview) | -      | ✓    |\n\n**示例**:\n\n```typescript\n// 设置所有的节点填充色为红色\ngraph.setNode({\n  style: {\n    fill: 'red',\n  },\n});\n```\n\n### Graph.setEdge(edge)\n\n设置边样式映射。即 `options.edge` 的值。\n\n```typescript\nsetEdge(edge: EdgeOptions): void;\n```\n\n**参数**:\n\n| 参数 | 描述   | 类型                                         | 默认值 | 必选 |\n| ---- | ------ | -------------------------------------------- | ------ | ---- |\n| edge | 边配置 | [EdgeOptions](/manual/element/edge/overview) | -      | ✓    |\n\n### Graph.setCombo(combo)\n\n设置组合样式映射。即 `options.combo` 的值。\n\n```typescript\nsetCombo(combo: ComboOptions): void;\n```\n\n**参数**:\n\n| 参数  | 描述     | 类型                                           | 默认值 | 必选 |\n| ----- | -------- | ---------------------------------------------- | ------ | ---- |\n| combo | 组合配置 | [ComboOptions](/manual/element/combo/overview) | -      | ✓    |\n\n### Graph.collapseElement(id, options)\n\n收起指定元素，通常用于折叠组合(Combo)或具有子元素的节点。\n\n```typescript\ncollapseElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要收起的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或收起节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，收起操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单收起，使用默认配置\nawait graph.collapseElement('combo1');\n\n// 收起并启用动画\nawait graph.collapseElement('combo1', true);\n\n// 收起并保证展开/收起的节点位置不变\nawait graph.collapseElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.expandElement(id, options)\n\n展开指定元素，通常用于展开先前收起的组合(Combo)或节点。\n\n```typescript\nexpandElement(id: ID, options?: boolean | CollapseExpandNodeOptions): Promise<void>;\n```\n\n**参数**:\n\n| 参数    | 描述                               | 类型                                                               | 默认值 | 必选 |\n| ------- | ---------------------------------- | ------------------------------------------------------------------ | ------ | ---- |\n| id      | 要展开的元素 ID                    | string                                                             | -      | ✓    |\n| options | 是否启用动画或展开节点的详细配置项 | boolean \\| [CollapseExpandNodeOptions](#collapseexpandnodeoptions) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，展开操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 简单展开，使用默认配置\nawait graph.expandElement('combo1');\n\n// 展开并启用动画\nawait graph.expandElement('combo1', true);\n\n// 展开并保证展开/收起的节点位置不变\nawait graph.expandElement('combo1', {\n  align: true,\n});\n```\n\n### Graph.frontElement(id)\n\n将指定元素置于最顶层，使其显示在其他重叠元素之上。\n\n```typescript\nfrontElement(id: ID | ID[]): void;\n```\n\n**参数**:\n\n| 参数 | 描述    | 类型               | 默认值 | 必选 |\n| ---- | ------- | ------------------ | ------ | ---- |\n| id   | 元素 ID | string \\| string[] | -      | ✓    |\n\n**返回值**:\n\n- **类型**: void\n\n**示例**:\n\n```typescript\n// 将节点置于最顶层\ngraph.frontElement('node1');\n\n// 对于选中的多个节点，都置于最顶层\ngraph.frontElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.showElement(id, animation)\n\n显示指定元素。\n\n```typescript\nshowElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，显示操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 显示单个元素\nawait graph.showElement('node1');\n\n// 带动画显示元素\nawait graph.showElement('node1', true);\n\n// 显示多个元素\nawait graph.showElement(['node1', 'node2', 'node3']);\n```\n\n### Graph.hideElement(id, animation)\n\n隐藏指定元素。\n\n```typescript\nhideElement(id: ID | ID[], animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述         | 类型               | 默认值 | 必选 |\n| --------- | ------------ | ------------------ | ------ | ---- |\n| id        | 元素 ID      | string \\| string[] | -      | ✓    |\n| animation | 是否启用动画 | boolean            | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，隐藏操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 无动画隐藏元素\nawait graph.hideElement('node1');\n\n// 带动画隐藏元素\nawait graph.hideElement('node1', true);\n\n// 隐藏多个元素\nawait graph.hideElement(['node1', 'node2', 'node3'], true);\n```\n\n### Graph.translateElementBy(id, offset, animation)\n\n相对平移元素指定距离，支持两种调用方式：\n\n```typescript\n// 将元素平移指定距离（相对平移）\ntranslateElement(id: ID, offset: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素平移指定距离（相对平移）\ntranslateElement(offsets: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素平移**\n\n| 参数      | 描述                    | 类型             | 默认值 | 必选 |\n| --------- | ----------------------- | ---------------- | ------ | ---- |\n| id        | 要平移的元素 ID         | string           | -      | ✓    |\n| offset    | 平移的相对距离 [dx, dy] | [number, number] | -      | ✓    |\n| animation | 是否启用动画            | boolean          | -      |      |\n\n**批量元素平移**\n\n| 参数      | 描述                   | 类型                         | 默认值 | 必选 |\n| --------- | ---------------------- | ---------------------------- | ------ | ---- |\n| offsets   | 元素ID到平移距离的映射 | Record<ID, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                      | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，平移操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 向右平移100像素，向下平移50像素\nawait graph.translateElementBy('node1', [100, 50]);\n\n// 带动画平移\nawait graph.translateElementBy('node1', [100, 50], true);\n\n// 对多个节点应用相同的平移\nawait graph.translateElementBy(\n  {\n    node1: [50, 50],\n    node2: [100, 100],\n    node3: [150, 150],\n  },\n  true,\n);\n```\n\n### Graph.translateElementTo(id, position, animation)\n\n将元素移动到指定位置，支持两种调用方式：\n\n```typescript\n// 将元素移动到指定位置（绝对位置）\ntranslateElementTo(id: ID, position: Point, animation?: boolean): Promise<void>;\n\n// 批量将元素移动到指定位置（绝对位置）\ntranslateElementTo(positions: Record<ID, Point>, animation?: boolean): Promise<void>;\n```\n\n**参数**:\n\n**单个元素移动**\n\n| 参数      | 描述                | 类型             | 默认值 | 必选 |\n| --------- | ------------------- | ---------------- | ------ | ---- |\n| id        | 要移动的元素 ID     | string           | -      | ✓    |\n| position  | 目标绝对位置 [x, y] | [number, number] | -      | ✓    |\n| animation | 是否启用动画        | boolean          | -      |      |\n\n**批量元素移动**\n\n| 参数      | 描述                   | 类型                             | 默认值 | 必选 |\n| --------- | ---------------------- | -------------------------------- | ------ | ---- |\n| positions | 元素ID到目标位置的映射 | Record<string, [number, number]> | -      | ✓    |\n| animation | 是否启用动画           | boolean                          | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，移动操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 将节点移动到画布的 (200, 300) 位置\nawait graph.translateElementTo('node1', [200, 300]);\n\n// 带动画移动\nawait graph.translateElementTo('node1', [200, 300], true);\n\n// 将一组节点整齐排列\nawait graph.translateElementTo(\n  {\n    node1: [100, 100],\n    node2: [200, 200],\n    node3: [300, 100],\n  },\n  true,\n);\n```\n\n### Graph.focusElement(id, animation)\n\n聚焦到指定元素，使元素居中于视口。\n\n```typescript\nfocusElement(id: ID | ID[], animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**:\n\n| 参数      | 描述                      | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| id        | 要聚焦的一个或多个元素 ID | string \\| string[]                                              | -      | ✓    |\n| animation | 视口动画配置              | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**返回值**:\n\n- **类型**: Promise\\<void\\>\n- **描述**: 返回一个 Promise，聚焦操作完成后 resolve\n\n**示例**:\n\n```typescript\n// 聚焦到单个节点\nawait graph.focusElement('node1');\n\n// 使用自定义动画配置\nawait graph.focusElement('node1', {\n  duration: 800,\n  easing: 'ease-in-out',\n});\n\n// 聚焦到多个节点\nawait graph.focusElement(['node1', 'node2', 'node3']);\n```\n\n## 类型定义\n\n### CollapseExpandNodeOptions\n\n收起或展开元素的配置选项。\n\n```typescript\ninterface CollapseExpandNodeOptions {\n  /**\n   * 是否使用动画\n   */\n  animation?: boolean;\n  /**\n   * 保证展开/收起的节点位置不变\n   */\n  align?: boolean;\n}\n```\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### AABB\n\nAABB (Axis-Aligned Bounding Box) 是\"轴对齐包围盒\"的缩写，是计算机图形学中的一个基础概念。\n\n```typescript\ninterface AABB {\n  x: number; // 矩形左上角的 x 坐标\n  y: number; // 矩形左上角的 y 坐标\n  width: number; // 矩形宽度\n  height: number; // 矩形高度\n}\n```\n\n### State\n\n元素状态类型。\n\n```typescript\ntype State = 'selected' | 'hover' | 'active' | 'inactive' | 'disabled' | string;\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/event.en.md) -->\n---\ntitle: Event Listening\norder: 11\n---\n\n## Overview of the Event System\n\nG6 provides a powerful event mechanism that allows you to respond to various interactive behaviors occurring in the chart, such as node clicks, edge hovers, canvas drags, etc. Through the event system, you can implement complex interactive logic to enhance user experience.\n\n### Event Categories\n\nEvents in G6 can be broadly categorized into the following types:\n\n1. **Element Events**: Events related to nodes, edges, and Combos, such as `node:click`, `edge:mouseenter`\n2. **Canvas Events**: Events related to the entire canvas, such as `canvas:drag`, `canvas:wheel`\n3. **Lifecycle Events**: Events related to the chart lifecycle, such as `beforerender`, `afterrender`\n\n### Event Naming Convention\n\nG6 events follow the `[object]:[event]` format, for example:\n\n- `node:click` - Node click event\n- `edge:mouseenter` - Mouse enters edge event\n- `canvas:drag` - Canvas drag event\n\n## Best Practice: Using Constant Enums\n\nG6 provides a complete set of event constant enums, and it is **strongly recommended** to use these constants instead of directly using string event names:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// Use constant enums to listen to events\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**Advantages**:\n\n- Type safety, avoiding string spelling errors\n- Provides intelligent code hints and auto-completion\n\n## API Reference\n\n### Graph.on(eventName, callback, once)\n\nListen to a specified event and execute a callback function when the event is triggered.\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n| once      | Whether to listen only once                            | boolean            | -       |          |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Listen to node click event\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // Get the ID of the clicked node\n  console.log(`Node ${target.id} was clicked`);\n\n  // Get node data\n  const nodeData = graph.getNodeData(target.id);\n  console.log('Node data:', nodeData);\n\n  // Modify node state\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen to edge mouse enter event\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// Listen to canvas drag event\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('Canvas is being dragged');\n});\n```\n\n### Graph.once(eventName, callback)\n\nListen to an event once, and automatically remove the listener after the event is triggered once.\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                                            | Type               | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------ | ------- | -------- |\n| eventName | Name of the event to listen to                         | string             | -       | ✓        |\n| callback  | Callback function executed when the event is triggered | (event: T) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// Listen to the chart's first load completion event, executed only once\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('Chart rendered for the first time');\n  // Execute one-time initialization operations\n  highlightImportantNodes();\n});\n\n// Wait for the user to click a node for the first time and then perform operations\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('User clicked a node for the first time:', evt.target.id);\n  showTutorialTip('You can drag nodes to change their position');\n});\n```\n\n### Graph.off()\n\nRemove all event listeners.\n\n```typescript\noff(): this;\n```\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\n// Remove all event listeners\ngraph.off();\nconsole.log('All event listeners have been removed');\n```\n\n### Graph.off(eventName)\n\nRemove all listeners of a specified event type.\n\n```typescript\noff(eventName: string): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type   | Default | Required |\n| --------- | --------------------------- | ------ | ------- | -------- |\n| eventName | Name of the event to remove | string | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Remove all node click event listeners\ngraph.off(NodeEvent.CLICK);\nconsole.log('All node click event listeners have been removed');\n\n// Remove related temporary event listeners after a certain operation mode ends\nfunction exitEditMode() {\n  // Remove all listeners in edit mode\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('Exited edit mode');\n}\n```\n\n### Graph.off(eventName, callback)\n\nRemove a specific callback function for a specific event.\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### Parameters\n\n| Parameter | Description                 | Type                     | Default | Required |\n| --------- | --------------------------- | ------------------------ | ------- | -------- |\n| eventName | Name of the event to remove | string                   | -       | ✓        |\n| callback  | Callback function to remove | (...args: any[]) => void | -       | ✓        |\n\n#### Return Value\n\n- **Type:** this (Graph instance)\n- **Description:** Returns the graph instance itself, supporting chain calls\n\n#### Example\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// Define callback function\nconst handleNodeClick = (evt) => {\n  console.log('Node clicked:', evt.target.id);\n};\n\n// Add listener\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// Later, remove this specific listener at a certain point\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('Specific node click event listener has been removed');\n```\n\n## Event Constant Enums\n\nG6 provides various event constant enums to facilitate developers in using standardized event names. Below is a detailed description of all event constants:\n\n### Node Events (NodeEvent)\n\n| Constant Name | Event Name          | Description                                                                   |\n| ------------- | ------------------- | ----------------------------------------------------------------------------- |\n| CLICK         | `node:click`        | Triggered when a node is clicked                                              |\n| DBLCLICK      | `node:dblclick`     | Triggered when a node is double-clicked                                       |\n| POINTER_OVER  | `node:pointerover`  | Triggered when the pointer enters a node                                      |\n| POINTER_LEAVE | `node:pointerleave` | Triggered when the pointer leaves a node                                      |\n| POINTER_ENTER | `node:pointerenter` | Triggered when the pointer enters a node or its child elements (non-bubbling) |\n| POINTER_MOVE  | `node:pointermove`  | Triggered when the pointer moves over a node                                  |\n| POINTER_OUT   | `node:pointerout`   | Triggered when the pointer leaves a node                                      |\n| POINTER_DOWN  | `node:pointerdown`  | Triggered when the pointer is pressed down on a node                          |\n| POINTER_UP    | `node:pointerup`    | Triggered when the pointer is released on a node                              |\n| CONTEXT_MENU  | `node:contextmenu`  | Triggered when the context menu is opened on a node                           |\n| DRAG_START    | `node:dragstart`    | Triggered when dragging a node starts                                         |\n| DRAG          | `node:drag`         | Triggered during node dragging                                                |\n| DRAG_END      | `node:dragend`      | Triggered when node dragging ends                                             |\n| DRAG_ENTER    | `node:dragenter`    | Triggered when a draggable item enters a node                                 |\n| DRAG_OVER     | `node:dragover`     | Triggered when a draggable item is over a node                                |\n| DRAG_LEAVE    | `node:dragleave`    | Triggered when a draggable item leaves a node                                 |\n| DROP          | `node:drop`         | Triggered when a draggable item is dropped on a node                          |\n\n### Edge Events (EdgeEvent)\n\n| Constant Name | Event Name          | Description                                                                    |\n| ------------- | ------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `edge:click`        | Triggered when an edge is clicked                                              |\n| DBLCLICK      | `edge:dblclick`     | Triggered when an edge is double-clicked                                       |\n| POINTER_OVER  | `edge:pointerover`  | Triggered when the pointer enters an edge                                      |\n| POINTER_LEAVE | `edge:pointerleave` | Triggered when the pointer leaves an edge                                      |\n| POINTER_ENTER | `edge:pointerenter` | Triggered when the pointer enters an edge or its child elements (non-bubbling) |\n| POINTER_MOVE  | `edge:pointermove`  | Triggered when the pointer moves over an edge                                  |\n| POINTER_OUT   | `edge:pointerout`   | Triggered when the pointer leaves an edge                                      |\n| POINTER_DOWN  | `edge:pointerdown`  | Triggered when the pointer is pressed down on an edge                          |\n| POINTER_UP    | `edge:pointerup`    | Triggered when the pointer is released on an edge                              |\n| CONTEXT_MENU  | `edge:contextmenu`  | Triggered when the context menu is opened on an edge                           |\n| DRAG_ENTER    | `edge:dragenter`    | Triggered when a draggable item enters an edge                                 |\n| DRAG_OVER     | `edge:dragover`     | Triggered when a draggable item is over an edge                                |\n| DRAG_LEAVE    | `edge:dragleave`    | Triggered when a draggable item leaves an edge                                 |\n| DROP          | `edge:drop`         | Triggered when a draggable item is dropped on an edge                          |\n\n### Combo Events (ComboEvent)\n\n| Constant Name | Event Name           | Description                                                                    |\n| ------------- | -------------------- | ------------------------------------------------------------------------------ |\n| CLICK         | `combo:click`        | Triggered when a Combo is clicked                                              |\n| DBLCLICK      | `combo:dblclick`     | Triggered when a Combo is double-clicked                                       |\n| POINTER_OVER  | `combo:pointerover`  | Triggered when the pointer enters a Combo                                      |\n| POINTER_LEAVE | `combo:pointerleave` | Triggered when the pointer leaves a Combo                                      |\n| POINTER_ENTER | `combo:pointerenter` | Triggered when the pointer enters a Combo or its child elements (non-bubbling) |\n| POINTER_MOVE  | `combo:pointermove`  | Triggered when the pointer moves over a Combo                                  |\n| POINTER_OUT   | `combo:pointerout`   | Triggered when the pointer leaves a Combo                                      |\n| POINTER_DOWN  | `combo:pointerdown`  | Triggered when the pointer is pressed down on a Combo                          |\n| POINTER_UP    | `combo:pointerup`    | Triggered when the pointer is released on a Combo                              |\n| CONTEXT_MENU  | `combo:contextmenu`  | Triggered when the context menu is opened on a Combo                           |\n| DRAG_START    | `combo:dragstart`    | Triggered when dragging a Combo starts                                         |\n| DRAG          | `combo:drag`         | Triggered during Combo dragging                                                |\n| DRAG_END      | `combo:dragend`      | Triggered when Combo dragging ends                                             |\n| DRAG_ENTER    | `combo:dragenter`    | Triggered when a draggable item enters a Combo                                 |\n| DRAG_OVER     | `combo:dragover`     | Triggered when a draggable item is over a Combo                                |\n| DRAG_LEAVE    | `combo:dragleave`    | Triggered when a draggable item leaves a Combo                                 |\n| DROP          | `combo:drop`         | Triggered when a draggable item is dropped on a Combo                          |\n\n### Canvas Events (CanvasEvent)\n\n| Constant Name | Event Name            | Description                                                                       |\n| ------------- | --------------------- | --------------------------------------------------------------------------------- |\n| CLICK         | `canvas:click`        | Triggered when clicking on the canvas blank area                                  |\n| DBLCLICK      | `canvas:dblclick`     | Triggered when double-clicking on the canvas blank area                           |\n| POINTER_OVER  | `canvas:pointerover`  | Triggered when the pointer enters the canvas                                      |\n| POINTER_LEAVE | `canvas:pointerleave` | Triggered when the pointer leaves the canvas                                      |\n| POINTER_ENTER | `canvas:pointerenter` | Triggered when the pointer enters the canvas or its child elements (non-bubbling) |\n| POINTER_MOVE  | `canvas:pointermove`  | Triggered when the pointer moves over the canvas                                  |\n| POINTER_OUT   | `canvas:pointerout`   | Triggered when the pointer leaves the canvas                                      |\n| POINTER_DOWN  | `canvas:pointerdown`  | Triggered when the pointer is pressed down on the canvas                          |\n| POINTER_UP    | `canvas:pointerup`    | Triggered when the pointer is released on the canvas                              |\n| CONTEXT_MENU  | `canvas:contextmenu`  | Triggered when the context menu is opened on the canvas                           |\n| DRAG_START    | `canvas:dragstart`    | Triggered when dragging the canvas starts                                         |\n| DRAG          | `canvas:drag`         | Triggered during canvas dragging                                                  |\n| DRAG_END      | `canvas:dragend`      | Triggered when canvas dragging ends                                               |\n| DRAG_ENTER    | `canvas:dragenter`    | Triggered when a draggable item enters the canvas                                 |\n| DRAG_OVER     | `canvas:dragover`     | Triggered when a draggable item is over the canvas                                |\n| DRAG_LEAVE    | `canvas:dragleave`    | Triggered when a draggable item leaves the canvas                                 |\n| DROP          | `canvas:drop`         | Triggered when a draggable item is dropped on the canvas                          |\n| WHEEL         | `canvas:wheel`        | Triggered when scrolling the mouse wheel on the canvas                            |\n\n### Graph Lifecycle Events (GraphEvent)\n\n| Constant Name            | Event Name               | Description                                    |\n| ------------------------ | ------------------------ | ---------------------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | Triggered before canvas initialization         |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | Triggered after canvas initialization          |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | Triggered before viewport size change          |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | Triggered after viewport size change           |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | Triggered before element creation              |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | Triggered after element creation               |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | Triggered before element update                |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | Triggered after element update                 |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | Triggered before element destruction           |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | Triggered after element destruction            |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | Triggered before element translation           |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | Triggered after element translation            |\n| BEFORE_DRAW              | `beforedraw`             | Triggered before drawing starts                |\n| AFTER_DRAW               | `afterdraw`              | Triggered after drawing ends                   |\n| BEFORE_RENDER            | `beforerender`           | Triggered before rendering starts              |\n| AFTER_RENDER             | `afterrender`            | Triggered after rendering completes            |\n| BEFORE_ANIMATE           | `beforeanimate`          | Triggered before animation starts              |\n| AFTER_ANIMATE            | `afteranimate`           | Triggered after animation ends                 |\n| BEFORE_LAYOUT            | `beforelayout`           | Triggered before layout starts                 |\n| AFTER_LAYOUT             | `afterlayout`            | Triggered after layout ends                    |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | Triggered before each stage in pipeline layout |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | Triggered after each stage in pipeline layout  |\n| BEFORE_TRANSFORM         | `beforetransform`        | Triggered before viewport transformation       |\n| AFTER_TRANSFORM          | `aftertransform`         | Triggered after viewport transformation        |\n| BATCH_START              | `batchstart`             | Triggered when batch operation starts          |\n| BATCH_END                | `batchend`               | Triggered when batch operation ends            |\n| BEFORE_DESTROY           | `beforedestroy`          | Triggered before chart destruction             |\n| AFTER_DESTROY            | `afterdestroy`           | Triggered after chart destruction              |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | Triggered before renderer change               |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | Triggered after renderer change                |\n\n### Container Events (ContainerEvent)\n\n| Constant Name | Event Name | Description                                   |\n| ------------- | ---------- | --------------------------------------------- |\n| KEY_DOWN      | `keydown`  | Triggered when a keyboard key is pressed down |\n| KEY_UP        | `keyup`    | Triggered when a keyboard key is released     |\n\n### Common Events (CommonEvent)\n\nThese are events without prefixes and can be used to listen to global events:\n\n| Constant Name | Event Name     | Description                                                                        |\n| ------------- | -------------- | ---------------------------------------------------------------------------------- |\n| CLICK         | `click`        | Triggered when any element is clicked                                              |\n| DBLCLICK      | `dblclick`     | Triggered when any element is double-clicked                                       |\n| POINTER_OVER  | `pointerover`  | Triggered when the pointer enters any element                                      |\n| POINTER_LEAVE | `pointerleave` | Triggered when the pointer leaves any element                                      |\n| POINTER_ENTER | `pointerenter` | Triggered when the pointer enters any element or its child elements (non-bubbling) |\n| POINTER_MOVE  | `pointermove`  | Triggered when the pointer moves over any element                                  |\n| POINTER_OUT   | `pointerout`   | Triggered when the pointer leaves any element                                      |\n| POINTER_DOWN  | `pointerdown`  | Triggered when the pointer is pressed down on any element                          |\n| POINTER_UP    | `pointerup`    | Triggered when the pointer is released on any element                              |\n| CONTEXT_MENU  | `contextmenu`  | Triggered when the context menu is opened on any element                           |\n| DRAG_START    | `dragstart`    | Triggered when dragging any element starts                                         |\n| DRAG          | `drag`         | Triggered during any element dragging                                              |\n| DRAG_END      | `dragend`      | Triggered when any element dragging ends                                           |\n| DRAG_ENTER    | `dragenter`    | Triggered when a draggable item enters any element                                 |\n| DRAG_OVER     | `dragover`     | Triggered when a draggable item is over any element                                |\n| DRAG_LEAVE    | `dragleave`    | Triggered when a draggable item leaves any element                                 |\n| DROP          | `drop`         | Triggered when a draggable item is dropped on any element                          |\n| KEY_DOWN      | `keydown`      | Triggered when a keyboard key is pressed down                                      |\n| KEY_UP        | `keyup`        | Triggered when a keyboard key is released                                          |\n| WHEEL         | `wheel`        | Triggered when scrolling the mouse wheel                                           |\n| PINCH         | `pinch`        | Triggered when pinching or spreading fingers on a multi-touch screen               |\n\n## Tips for Use\n\n### Chain Calls\n\nG6's event API supports chain calls, allowing you to register multiple events consecutively:\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// Use constant enums + chain calls\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### Event Delegation\n\nYou can use the event bubbling mechanism to listen to all child element events on the parent element:\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// Handle all element click events uniformly\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('Clicked on node:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('Clicked on edge:', target.id);\n  } else {\n    console.log('Clicked on canvas blank area');\n  }\n});\n```\n\n### Event Object Properties\n\nMost event callback functions receive an event object containing the following common properties:\n\n- `target` - The element that triggered the event\n- `targetType` - The type of the element that triggered the event (node/edge/combo/canvas)\n- `originalTarget` - The original graphic that triggered the event\n- `currentTarget` - The current object that triggered the event\n- `originalEvent` - The original browser event object\n\nWith these properties, you can precisely control interactive behavior.\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/event.zh.md) -->\n---\ntitle: 事件监听\norder: 11\n---\n\n## 事件系统概述\n\nG6 提供了强大的事件机制，允许你响应图表中发生的各种交互行为。例如节点点击、边悬停、画布拖拽等。通过事件系统，你可以实现复杂的交互逻辑，提升用户体验。\n\n### 事件分类\n\nG6 中的事件大致可分为以下几类：\n\n1. **元素事件**：与节点、边、Combo 相关的事件，如 `node:click`, `edge:mouseenter`\n2. **画布事件**：与整个画布相关的事件，如 `canvas:drag`, `canvas:wheel`\n3. **生命周期事件**：与图表生命周期相关的事件，如 `beforerender`, `afterrender`\n\n### 事件命名规则\n\nG6 的事件命名遵循 `[对象]:[事件]` 的格式，例如：\n\n- `node:click` - 节点点击事件\n- `edge:mouseenter` - 鼠标进入边的事件\n- `canvas:drag` - 画布拖拽事件\n\n## 最佳实践：使用常量枚举\n\nG6 提供了完整的事件常量枚举，**强烈建议**使用这些常量而非直接使用字符串事件名：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent, GraphEvent } from '@antv/g6';\n\n// 使用常量枚举监听事件\ngraph.on(NodeEvent.CLICK, handleNodeClick);\ngraph.on(EdgeEvent.POINTER_OVER, handleEdgeHover);\ngraph.on(CanvasEvent.DRAG, handleCanvasDrag);\ngraph.on(GraphEvent.AFTER_RENDER, handleAfterRender);\n```\n\n**优势**：\n\n- 类型安全，避免字符串拼写错误\n- 提供智能代码提示和自动完成\n\n## API 参考\n\n### Graph.on(eventName, callback, once)\n\n监听指定的事件，当事件触发时执行回调函数。\n\n```typescript\non<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void, once?: boolean): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n| once      | 是否只监听一次           | boolean            | -      |      |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 监听节点点击事件\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt; // 获取被点击节点的 ID\n  console.log(`节点 ${target.id} 被点击了`);\n\n  // 获取节点数据\n  const nodeData = graph.getNodeData(target.id);\n  console.log('节点数据:', nodeData);\n\n  // 修改节点状态\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边的鼠标进入事件\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n\n// 监听画布拖拽事件\ngraph.on(CanvasEvent.DRAG, (evt) => {\n  console.log('画布正在被拖拽');\n});\n```\n\n### Graph.once(eventName, callback)\n\n一次性监听事件，事件触发一次后自动移除监听器。\n\n```typescript\nonce<T extends IEvent = IEvent>(eventName: string, callback: (event: T) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述                     | 类型               | 默认值 | 必选 |\n| --------- | ------------------------ | ------------------ | ------ | ---- |\n| eventName | 要监听的事件名称         | string             | -      | ✓    |\n| callback  | 事件触发时执行的回调函数 | (event: T) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { GraphEvent, NodeEvent } from '@antv/g6';\n\n// 监听图表首次加载完成事件，仅执行一次\ngraph.once(GraphEvent.AFTER_RENDER, () => {\n  console.log('图表首次渲染完成');\n  // 执行一次性的初始化操作\n  highlightImportantNodes();\n});\n\n// 等待用户第一次点击某个节点后执行操作\ngraph.once(NodeEvent.CLICK, (evt) => {\n  console.log('用户首次点击了节点:', evt.target.id);\n  showTutorialTip('您可以拖拽节点改变位置');\n});\n```\n\n### Graph.off()\n\n移除全部事件监听器。\n\n```typescript\noff(): this;\n```\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\n// 移除所有事件监听器\ngraph.off();\nconsole.log('已移除所有事件监听器');\n```\n\n### Graph.off(eventName)\n\n移除指定事件类型的所有监听器。\n\n```typescript\noff(eventName: string): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型   | 默认值 | 必选 |\n| --------- | ---------------- | ------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 移除所有节点点击事件的监听器\ngraph.off(NodeEvent.CLICK);\nconsole.log('已移除所有节点点击事件监听器');\n\n// 在某个操作模式结束后，移除相关的临时事件监听\nfunction exitEditMode() {\n  // 移除编辑模式下的所有监听器\n  graph.off(NodeEvent.DRAG_END);\n  graph.off(NodeEvent.DROP);\n  console.log('已退出编辑模式');\n}\n```\n\n### Graph.off(eventName, callback)\n\n移除特定事件的特定回调函数。\n\n```typescript\noff(eventName: string, callback: (...args: any[]) => void): this;\n```\n\n#### 参数\n\n| 参数      | 描述             | 类型                     | 默认值 | 必选 |\n| --------- | ---------------- | ------------------------ | ------ | ---- |\n| eventName | 要移除的事件名称 | string                   | -      | ✓    |\n| callback  | 要移除的回调函数 | (...args: any[]) => void | -      | ✓    |\n\n#### 返回值\n\n- **类型：** this（Graph 实例）\n- **描述：** 返回图实例本身，支持链式调用\n\n#### 示例\n\n```typescript\nimport { NodeEvent } from '@antv/g6';\n\n// 定义回调函数\nconst handleNodeClick = (evt) => {\n  console.log('节点被点击:', evt.target.id);\n};\n\n// 添加监听器\ngraph.on(NodeEvent.CLICK, handleNodeClick);\n\n// 之后在某个时机移除这个特定的监听器\ngraph.off(NodeEvent.CLICK, handleNodeClick);\nconsole.log('已移除特定的节点点击事件监听器');\n```\n\n## 事件常量枚举\n\nG6 提供了多种事件常量枚举，便于开发者使用规范的事件名称。以下是所有事件常量的详细说明：\n\n### 节点事件 (NodeEvent)\n\n| 常量名        | 事件名              | 描述                                 |\n| ------------- | ------------------- | ------------------------------------ |\n| CLICK         | `node:click`        | 点击节点时触发                       |\n| DBLCLICK      | `node:dblclick`     | 双击节点时触发                       |\n| POINTER_OVER  | `node:pointerover`  | 指针移入节点时触发                   |\n| POINTER_LEAVE | `node:pointerleave` | 指针离开节点时触发                   |\n| POINTER_ENTER | `node:pointerenter` | 指针进入节点或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `node:pointermove`  | 指针在节点上移动时触发               |\n| POINTER_OUT   | `node:pointerout`   | 指针离开节点时触发                   |\n| POINTER_DOWN  | `node:pointerdown`  | 指针在节点上按下时触发               |\n| POINTER_UP    | `node:pointerup`    | 指针在节点上抬起时触发               |\n| CONTEXT_MENU  | `node:contextmenu`  | 节点上打开上下文菜单时触发           |\n| DRAG_START    | `node:dragstart`    | 开始拖拽节点时触发                   |\n| DRAG          | `node:drag`         | 拖拽节点过程中触发                   |\n| DRAG_END      | `node:dragend`      | 拖拽节点结束时触发                   |\n| DRAG_ENTER    | `node:dragenter`    | 拖拽物进入节点时触发                 |\n| DRAG_OVER     | `node:dragover`     | 拖拽物在节点上方时触发               |\n| DRAG_LEAVE    | `node:dragleave`    | 拖拽物离开节点时触发                 |\n| DROP          | `node:drop`         | 在节点上放置拖拽物时触发             |\n\n### 边事件 (EdgeEvent)\n\n| 常量名        | 事件名              | 描述                               |\n| ------------- | ------------------- | ---------------------------------- |\n| CLICK         | `edge:click`        | 点击边时触发                       |\n| DBLCLICK      | `edge:dblclick`     | 双击边时触发                       |\n| POINTER_OVER  | `edge:pointerover`  | 指针移入边时触发                   |\n| POINTER_LEAVE | `edge:pointerleave` | 指针离开边时触发                   |\n| POINTER_ENTER | `edge:pointerenter` | 指针进入边或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `edge:pointermove`  | 指针在边上移动时触发               |\n| POINTER_OUT   | `edge:pointerout`   | 指针离开边时触发                   |\n| POINTER_DOWN  | `edge:pointerdown`  | 指针在边上按下时触发               |\n| POINTER_UP    | `edge:pointerup`    | 指针在边上抬起时触发               |\n| CONTEXT_MENU  | `edge:contextmenu`  | 边上打开上下文菜单时触发           |\n| DRAG_ENTER    | `edge:dragenter`    | 拖拽物进入边时触发                 |\n| DRAG_OVER     | `edge:dragover`     | 拖拽物在边上方时触发               |\n| DRAG_LEAVE    | `edge:dragleave`    | 拖拽物离开边时触发                 |\n| DROP          | `edge:drop`         | 在边上放置拖拽物时触发             |\n\n### Combo事件 (ComboEvent)\n\n| 常量名        | 事件名               | 描述                                  |\n| ------------- | -------------------- | ------------------------------------- |\n| CLICK         | `combo:click`        | 点击Combo时触发                       |\n| DBLCLICK      | `combo:dblclick`     | 双击Combo时触发                       |\n| POINTER_OVER  | `combo:pointerover`  | 指针移入Combo时触发                   |\n| POINTER_LEAVE | `combo:pointerleave` | 指针离开Combo时触发                   |\n| POINTER_ENTER | `combo:pointerenter` | 指针进入Combo或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `combo:pointermove`  | 指针在Combo上移动时触发               |\n| POINTER_OUT   | `combo:pointerout`   | 指针离开Combo时触发                   |\n| POINTER_DOWN  | `combo:pointerdown`  | 指针在Combo上按下时触发               |\n| POINTER_UP    | `combo:pointerup`    | 指针在Combo上抬起时触发               |\n| CONTEXT_MENU  | `combo:contextmenu`  | Combo上打开上下文菜单时触发           |\n| DRAG_START    | `combo:dragstart`    | 开始拖拽Combo时触发                   |\n| DRAG          | `combo:drag`         | 拖拽Combo过程中触发                   |\n| DRAG_END      | `combo:dragend`      | 拖拽Combo结束时触发                   |\n| DRAG_ENTER    | `combo:dragenter`    | 拖拽物进入Combo时触发                 |\n| DRAG_OVER     | `combo:dragover`     | 拖拽物在Combo上方时触发               |\n| DRAG_LEAVE    | `combo:dragleave`    | 拖拽物离开Combo时触发                 |\n| DROP          | `combo:drop`         | 在Combo上放置拖拽物时触发             |\n\n### 画布事件 (CanvasEvent)\n\n| 常量名        | 事件名                | 描述                                 |\n| ------------- | --------------------- | ------------------------------------ |\n| CLICK         | `canvas:click`        | 点击画布空白处时触发                 |\n| DBLCLICK      | `canvas:dblclick`     | 双击画布空白处时触发                 |\n| POINTER_OVER  | `canvas:pointerover`  | 指针移入画布时触发                   |\n| POINTER_LEAVE | `canvas:pointerleave` | 指针离开画布时触发                   |\n| POINTER_ENTER | `canvas:pointerenter` | 指针进入画布或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `canvas:pointermove`  | 指针在画布上移动时触发               |\n| POINTER_OUT   | `canvas:pointerout`   | 指针离开画布时触发                   |\n| POINTER_DOWN  | `canvas:pointerdown`  | 指针在画布上按下时触发               |\n| POINTER_UP    | `canvas:pointerup`    | 指针在画布上抬起时触发               |\n| CONTEXT_MENU  | `canvas:contextmenu`  | 画布上打开上下文菜单时触发           |\n| DRAG_START    | `canvas:dragstart`    | 开始拖拽画布时触发                   |\n| DRAG          | `canvas:drag`         | 拖拽画布过程中触发                   |\n| DRAG_END      | `canvas:dragend`      | 拖拽画布结束时触发                   |\n| DRAG_ENTER    | `canvas:dragenter`    | 拖拽物进入画布时触发                 |\n| DRAG_OVER     | `canvas:dragover`     | 拖拽物在画布上方时触发               |\n| DRAG_LEAVE    | `canvas:dragleave`    | 拖拽物离开画布时触发                 |\n| DROP          | `canvas:drop`         | 在画布上放置拖拽物时触发             |\n| WHEEL         | `canvas:wheel`        | 在画布上滚动鼠标滚轮时触发           |\n\n### 图表生命周期事件 (GraphEvent)\n\n| 常量名                   | 事件名                   | 描述                               |\n| ------------------------ | ------------------------ | ---------------------------------- |\n| BEFORE_CANVAS_INIT       | `beforecanvasinit`       | 画布初始化之前触发                 |\n| AFTER_CANVAS_INIT        | `aftercanvasinit`        | 画布初始化之后触发                 |\n| BEFORE_SIZE_CHANGE       | `beforesizechange`       | 视口尺寸变更之前触发               |\n| AFTER_SIZE_CHANGE        | `aftersizechange`        | 视口尺寸变更之后触发               |\n| BEFORE_ELEMENT_CREATE    | `beforeelementcreate`    | 元素创建之前触发                   |\n| AFTER_ELEMENT_CREATE     | `afterelementcreate`     | 元素创建之后触发                   |\n| BEFORE_ELEMENT_UPDATE    | `beforeelementupdate`    | 元素更新之前触发                   |\n| AFTER_ELEMENT_UPDATE     | `afterelementupdate`     | 元素更新之后触发                   |\n| BEFORE_ELEMENT_DESTROY   | `beforeelementdestroy`   | 元素销毁之前触发                   |\n| AFTER_ELEMENT_DESTROY    | `afterelementdestroy`    | 元素销毁之后触发                   |\n| BEFORE_ELEMENT_TRANSLATE | `beforeelementtranslate` | 元素平移之前触发                   |\n| AFTER_ELEMENT_TRANSLATE  | `afterelementtranslate`  | 元素平移之后触发                   |\n| BEFORE_DRAW              | `beforedraw`             | 绘制开始之前触发                   |\n| AFTER_DRAW               | `afterdraw`              | 绘制结束之后触发                   |\n| BEFORE_RENDER            | `beforerender`           | 渲染开始之前触发                   |\n| AFTER_RENDER             | `afterrender`            | 渲染完成之后触发                   |\n| BEFORE_ANIMATE           | `beforeanimate`          | 动画开始之前触发                   |\n| AFTER_ANIMATE            | `afteranimate`           | 动画结束之后触发                   |\n| BEFORE_LAYOUT            | `beforelayout`           | 布局开始之前触发                   |\n| AFTER_LAYOUT             | `afterlayout`            | 布局结束之后触发                   |\n| BEFORE_STAGE_LAYOUT      | `beforestagelayout`      | 流水线布局过程中每个阶段开始前触发 |\n| AFTER_STAGE_LAYOUT       | `afterstagelayout`       | 流水线布局过程中每个阶段结束后触发 |\n| BEFORE_TRANSFORM         | `beforetransform`        | 可视区域变化之前触发               |\n| AFTER_TRANSFORM          | `aftertransform`         | 可视区域变化之后触发               |\n| BATCH_START              | `batchstart`             | 批处理操作开始时触发               |\n| BATCH_END                | `batchend`               | 批处理操作结束时触发               |\n| BEFORE_DESTROY           | `beforedestroy`          | 图表销毁前触发                     |\n| AFTER_DESTROY            | `afterdestroy`           | 图表销毁后触发                     |\n| BEFORE_RENDERER_CHANGE   | `beforerendererchange`   | 渲染器变更之前触发                 |\n| AFTER_RENDERER_CHANGE    | `afterrendererchange`    | 渲染器变更之后触发                 |\n\n### 容器事件 (ContainerEvent)\n\n| 常量名   | 事件名    | 描述               |\n| -------- | --------- | ------------------ |\n| KEY_DOWN | `keydown` | 键盘按键按下时触发 |\n| KEY_UP   | `keyup`   | 键盘按键抬起时触发 |\n\n### 通用事件 (CommonEvent)\n\n这些是不带前缀的事件，可用于监听全局事件：\n\n| 常量名        | 事件名         | 描述                                     |\n| ------------- | -------------- | ---------------------------------------- |\n| CLICK         | `click`        | 点击任何元素时触发                       |\n| DBLCLICK      | `dblclick`     | 双击任何元素时触发                       |\n| POINTER_OVER  | `pointerover`  | 指针移入任何元素时触发                   |\n| POINTER_LEAVE | `pointerleave` | 指针离开任何元素时触发                   |\n| POINTER_ENTER | `pointerenter` | 指针进入任何元素或其子元素时触发(不冒泡) |\n| POINTER_MOVE  | `pointermove`  | 指针在任何元素上移动时触发               |\n| POINTER_OUT   | `pointerout`   | 指针离开任何元素时触发                   |\n| POINTER_DOWN  | `pointerdown`  | 指针在任何元素上按下时触发               |\n| POINTER_UP    | `pointerup`    | 指针在任何元素上抬起时触发               |\n| CONTEXT_MENU  | `contextmenu`  | 任何元素上打开上下文菜单时触发           |\n| DRAG_START    | `dragstart`    | 开始拖拽任何元素时触发                   |\n| DRAG          | `drag`         | 拖拽任何元素过程中触发                   |\n| DRAG_END      | `dragend`      | 拖拽任何元素结束时触发                   |\n| DRAG_ENTER    | `dragenter`    | 拖拽物进入任何元素时触发                 |\n| DRAG_OVER     | `dragover`     | 拖拽物在任何元素上方时触发               |\n| DRAG_LEAVE    | `dragleave`    | 拖拽物离开任何元素时触发                 |\n| DROP          | `drop`         | 在任何元素上放置拖拽物时触发             |\n| KEY_DOWN      | `keydown`      | 键盘按键按下时触发                       |\n| KEY_UP        | `keyup`        | 键盘按键抬起时触发                       |\n| WHEEL         | `wheel`        | 滚动鼠标滚轮时触发                       |\n| PINCH         | `pinch`        | 多点触控屏幕上双指捏合或张开时触发       |\n\n## 使用技巧\n\n### 链式调用\n\nG6 的事件 API 支持链式调用，可以连续注册多个事件：\n\n```typescript\nimport { NodeEvent, EdgeEvent, CanvasEvent } from '@antv/g6';\n\n// 使用常量枚举+链式调用\ngraph.on(NodeEvent.CLICK, handleNodeClick).on(EdgeEvent.CLICK, handleEdgeClick).on(CanvasEvent.WHEEL, handleCanvasZoom);\n```\n\n### 事件代理\n\n你可以利用事件冒泡机制，在父元素上监听所有子元素的事件：\n\n```typescript\nimport { CommonEvent } from '@antv/g6';\n\n// 统一处理所有元素的点击事件\ngraph.on(CommonEvent.CLICK, (evt) => {\n  const { targetType, target } = evt;\n  if (targetType === 'node') {\n    console.log('点击了节点:', target.id);\n  } else if (targetType === 'edge') {\n    console.log('点击了边:', target.id);\n  } else {\n    console.log('点击了画布空白处');\n  }\n});\n```\n\n### 事件对象属性\n\n大多数事件的回调函数会接收一个事件对象，包含以下常用属性：\n\n- `target` - 触发事件的元素\n- `targetType` - 触发事件的元素类型（node/edge/combo/canvas）\n- `originalTarget` - 原始的触发事件的图形\n- `currentTarget` - 当前触发事件的对象\n- `originalEvent` - 原始的浏览器事件对象\n\n通过这些属性，你可以精确地控制交互行为。\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/export-image.en.md) -->\n---\ntitle: Export Image\norder: 12\n---\n\n## Overview of Image Export\n\nG6 provides the functionality to export the graph as an image, allowing you to export the current canvas content as a DataURL format. This is convenient for saving, sharing, or further processing. The exported image will retain all visible elements on the canvas, including nodes, edges, combos, and other custom graphics.\n\n## API Reference\n\n### Graph.toDataURL(options)\n\nExport the current canvas as an image in DataURL format.\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**Parameters**\n\n| Parameter | Description                | Type                      | Default | Required |\n| --------- | -------------------------- | ------------------------- | ------- | -------- |\n| options   | Export image configuration | Partial\\<DataURLOptions\\> | -       |          |\n\n**Return Value**\n\nReturns a Promise that resolves to a DataURL string representing the image.\n\n**DataURLOptions Type Definition**\n\n| Parameter      | Type                                        | Required | Description                                                                                              |\n| -------------- | ------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |\n| mode           | 'viewport' \\| 'overall'                     | No       | Export mode <br/> - viewport: Export viewport content <br/> - overall: Export entire canvas              |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | No       | Image type <br/> - image/png: PNG format <br/> - image/jpeg: JPEG format <br/> - image/webp: WebP format |\n| encoderOptions | number                                      | No       | Image quality, only effective for image/jpeg and image/webp, range 0 ~ 1                                 |\n\n## Download Image\n\nG6 5.0 only provides an API to export the canvas as a Base64 image ([toDataURL](#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=Note}\nThe exported image content may not include the complete canvas content. The export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., which will not appear in the exported image.\n:::\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/export-image.zh.md) -->\n---\ntitle: 导出图片\norder: 12\n---\n\n## 图片导出概述\n\nG6 提供了将图导出为图片的功能，可以将当前画布内容导出为 DataURL 格式，方便保存、分享或进一步处理。导出的图片会保留画布上的所有可见元素，包括节点、边、组合以及其他自定义图形。\n\n## API 参考\n\n### Graph.toDataURL(options)\n\n将当前画布导出为 DataURL 格式的图片。\n\n```typescript\ntoDataURL(options?: Partial<DataURLOptions>): Promise<string>;\n```\n\n**参数**\n\n| 参数    | 描述         | 类型                      | 默认值 | 必选 |\n| ------- | ------------ | ------------------------- | ------ | ---- |\n| options | 导出图片配置 | Partial\\<DataURLOptions\\> | -      |      |\n\n**返回值**\n\n返回一个 Promise，解析为表示图片的 DataURL 字符串。\n\n**DataURLOptions 类型定义**\n\n| 参数           | 类型                                        | 必选 | 描述                                                                                             |\n| -------------- | ------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------ |\n| mode           | 'viewport' \\| 'overall'                     | 否   | 导出模式 <br/> - viewport: 导出视口内容 <br/> - overall: 导出整个画布                            |\n| type           | 'image/png' \\| 'image/jpeg' \\| 'image/webp' | 否   | 图片类型 <br/> - image/png: PNG 格式 <br/> - image/jpeg: JPEG 格式 <br/> - image/webp: WebP 格式 |\n| encoderOptions | number                                      | 否   | 图片质量，仅对 image/jpeg 和 image/webp 有效，取值范围 0 ~ 1                                     |\n\n## 下载图片\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<br />\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/graph.en.md) -->\n---\ntitle: Graph Instance\norder: 2\n---\n\n## API Reference\n\n### Graph.destroy()\n\nDestroy the current graph instance and release all resources related to it.\n\n⚠️ **Note**: After destruction, no operations can be performed. If you need to use it again, you must create a new graph instance.\n\n```typescript\ndestroy(): void;\n```\n\n**Usage Scenarios**:\n\n- When the user closes the chart or switches to another view, this method can be called to release resources.\n- When needing to recreate a graph instance, ensure the old instance is destroyed first to avoid memory leaks.\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/graph.zh.md) -->\n---\ntitle: 图实例\norder: 2\n---\n\n## API 参考\n\n### Graph.destroy()\n\n销毁当前图实例，释放与图实例相关的所有资源。\n\n⚠️ **注意**: 销毁后无法进行任何操作，如果需要重新使用，需要重新创建一个新的图实例。\n\n```typescript\ndestroy(): void;\n```\n\n**使用场景**:\n\n- 当用户关闭图表或切换到其他视图时，可以调用此方法来释放资源。\n- 在需要重新创建图实例时，确保先销毁旧的实例，以避免内存泄漏。\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/layout.en.md) -->\n---\ntitle: Layout\norder: 6\n---\n\n## Overview of Layout\n\n[Layout](/en/manual/layout/overview) is a crucial part of graph visualization, determining the positioning of nodes on the canvas. G6 offers a variety of layout algorithms to meet different data structures and visualization needs. Through the layout API, you can:\n\n- Set and update the graph's layout configuration\n- Execute or stop layout calculations\n- Combine multiple layout strategies\n- Customize layout algorithms\n\nA suitable layout can clearly display the relationship patterns between nodes, enhancing the graph's readability and aesthetics.\n\n## API Reference\n\n### Graph.setLayout(layout)\n\nSet the graph's layout algorithm and configuration.\n\n⚠️ **Note**: Calling this function won't automatically re-layout, so there's need to call `graph.layout()` separately.\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                        | Type                                                                        | Default | Required |\n| --------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layout    | Layout configuration object, or a function returning a new configuration based on the previous one | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       | ✓        |\n\n**Example 1**: Set a force-directed layout\n\n```typescript\n// Set a simple force-directed layout\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // Prevent node overlap\n  nodeStrength: -50, // Repulsion between nodes, negative value for repulsion\n  edgeStrength: 0.5, // Edge strength, affects edge length\n});\n```\n\n**Example 2**: Update layout using a function\n\n```typescript\n// Update based on the current layout configuration\ngraph.setLayout((prevLayout) => {\n  // If the previous layout was force-directed, adjust its parameters\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // Increase repulsion\n      alphaDecay: 0.01, // Lower decay rate for more iteration time\n    };\n  }\n\n  // Otherwise, switch to radial layout\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**Example 3**: Set a combined layout\n\n```typescript\n// Set a combined layout - different nodes use different layout algorithms\ngraph.setLayout([\n  {\n    type: 'grid',\n    // Filter function: only nodes with type 'main' participate in the layout\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\nGet the current layout configuration.\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**Return Value**\n\n- **Type**: [LayoutOptions](#layoutoptions)\n- **Description**: The current layout configuration object\n\n**Example**\n\n```typescript\n// Get the current layout configuration\nconst currentLayout = graph.getLayout();\nconsole.log('Current layout type:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\nExecute layout calculations. When graph data changes, call this method to trigger the layout algorithm to recalculate node positions.\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter     | Description                 | Type                                                                        | Default | Required |\n| ------------- | --------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| layoutOptions | Layout configuration object | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -       |          |\n\nIf `layoutOptions` is provided, it takes precedence over the graph's current layout configuration.\n\n**Note**\n\nLayout calculation is an asynchronous process, especially for complex layout algorithms like force-directed layout. This method returns a Promise, which can be used to perform subsequent operations after the layout is complete.\n\n**Example 1**: Basic usage\n\n```typescript\n// Execute layout\nawait graph.layout();\nconsole.log('Layout calculation complete');\n```\n\n**Example 2**: Re-layout after adding data\n\n```typescript\n// Add new nodes and edges\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// Draw new nodes and edges\nawait graph.draw();\n\n// Recalculate layout\nawait graph.layout();\n```\n\n**Example 3**: Listen to layout events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before layout starts\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('Layout calculation starting...');\n});\n\n// After layout completes\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('Layout calculation complete');\n});\n\n// Execute layout\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\nStop an ongoing layout calculation. Mainly used to stop iterative layout algorithms like force-directed layout.\n\n```typescript\nstopLayout(): void;\n```\n\n**Note**\n\nApplicable to layouts with iterative animations, currently `force` belongs to this category. If the layout calculation takes too long, you can manually stop the iteration.\n\n**Example 1**: Basic usage\n\n```typescript\n// Stop layout after 5 seconds\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('Layout manually stopped');\n}, 5000);\n```\n\n**Example 2**: Stop layout with user interaction\n\n```typescript\n// Stop layout when the user clicks the canvas\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('User clicked canvas, layout stopped');\n});\n```\n\n## Type Definitions\n\n### LayoutOptions\n\nLayout configuration type, can be a single layout configuration or an array of layout configurations.\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\nSingle layout configuration, can be a built-in layout configuration or a custom base layout configuration.\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\nBasic configuration items common to all layout types.\n\n```typescript\ninterface BaseLayoutOptions {\n  // Layout type\n  type: string;\n\n  // Node filter function for participating in the layout\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // Whether to calculate the layout before initializing elements\n  preLayout?: boolean;\n\n  // Whether invisible nodes participate in the layout (effective when preLayout is true)\n  isLayoutInvisibleNodes?: boolean;\n\n  // Enable layout animation, for iterative layouts, animation transitions occur between iterations\n  animation?: boolean;\n\n  // Whether to run the layout in a WebWorker\n  enableWorker?: boolean;\n\n  // Number of iterations for iterative layouts\n  iterations?: number;\n\n  // Other specific layout configuration items\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nConfiguration for G6's built-in layout types, see [API - Built-in Layouts](/en/manual/layout/antv-dagre-layout) for details.\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/layout.zh.md) -->\n---\ntitle: 布局\norder: 6\n---\n\n## 布局概述\n\n[布局](/manual/layout/overview) 是图可视化中至关重要的一环，它决定了节点在画布上的位置排布。G6 提供了多种布局算法，以满足不同数据结构和可视化需求。通过布局 API，你可以：\n\n- 设置和更新图的布局配置\n- 执行或停止布局计算\n- 组合多种布局策略\n- 自定义布局算法\n\n合适的布局可以清晰地展示节点间的关系模式，提高图的可读性和美观度。\n\n## API 参考\n\n### Graph.setLayout(layout)\n\n设置图的布局算法及配置。\n\n⚠️ **注意**: 调用此函数不会自动重新布局，需要单独调用 `graph.layout()`。\n\n```typescript\nsetLayout(layout: LayoutOptions | ((prev: LayoutOptions) => LayoutOptions)): void;\n```\n\n**参数**\n\n| 参数   | 描述                                               | 类型                                                                        | 默认值 | 必选 |\n| ------ | -------------------------------------------------- | --------------------------------------------------------------------------- | ------ | ---- |\n| layout | 布局配置对象，或者一个基于之前配置返回新配置的函数 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      | ✓    |\n\n**示例 1**: 设置力导向布局\n\n```typescript\n// 设置简单的力导向布局\ngraph.setLayout({\n  type: 'force',\n  preventOverlap: true, // 防止节点重叠\n  nodeStrength: -50, // 节点间斥力，负值为斥力\n  edgeStrength: 0.5, // 边的强度，会影响边的长度\n});\n```\n\n**示例 2**: 使用函数式更新布局\n\n```typescript\n// 基于当前布局配置进行更新\ngraph.setLayout((prevLayout) => {\n  // 如果之前是力导向布局，调整其参数\n  if (prevLayout.type === 'force') {\n    return {\n      ...prevLayout,\n      preventOverlap: true,\n      nodeStrength: -100, // 增加斥力\n      alphaDecay: 0.01, // 降低衰减率，让布局有更多迭代时间\n    };\n  }\n\n  // 否则切换到放射状布局\n  return {\n    type: 'radial',\n    unitRadius: 100,\n    preventOverlap: true,\n  };\n});\n```\n\n**示例 3**: 设置组合布局\n\n```typescript\n// 设置组合布局 - 不同的节点使用不同的布局算法\ngraph.setLayout([\n  {\n    type: 'grid',\n    // 过滤函数：只有type为'main'的节点参与布局\n    nodeFilter: (node) => node.data.type === 'main',\n    rows: 1,\n  },\n  {\n    type: 'circle',\n    nodeFilter: (node) => node.data.type === 'sub',\n    radius: 100,\n  },\n]);\n```\n\n### Graph.getLayout()\n\n获取当前的布局配置。\n\n```typescript\ngetLayout(): LayoutOptions;\n```\n\n**返回值**\n\n- **类型**: [LayoutOptions](#layoutoptions)\n- **描述**: 当前的布局配置对象\n\n**示例**\n\n```typescript\n// 获取当前布局配置\nconst currentLayout = graph.getLayout();\nconsole.log('当前布局类型:', currentLayout.type);\n```\n\n### Graph.layout(layoutOptions)\n\n执行布局计算。当图数据发生变化后，调用此方法可触发布局算法重新计算节点位置。\n\n```typescript\nlayout(layoutOptions?: LayoutOptions): Promise<void>;\n```\n\n**参数**\n\n| 参数          | 描述         | 类型                                                                        | 默认值 | 必选 |\n| ------------- | ------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| layoutOptions | 布局配置对象 | [LayoutOptions](#layoutoptions) \\| ((prev: LayoutOptions) => LayoutOptions) | -      |      |\n\n如果传入 `layoutOptions`，则优先考虑传入的布局配置，否则使用图的当前布局配置进行布局。\n\n**说明**\n\n布局计算是一个异步过程，特别是对于复杂的布局算法（如力导向布局）。此方法返回一个 Promise，可以用于在布局完成后执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 执行布局\nawait graph.layout();\nconsole.log('布局计算完成');\n```\n\n**示例 2**: 添加数据后重新布局\n\n```typescript\n// 添加新节点和边\ngraph.addData({\n  nodes: [{ id: 'newNode1' }, { id: 'newNode2' }],\n  edges: [{ id: 'newEdge', source: 'existingNode', target: 'newNode1' }],\n});\n\n// 绘制新节点和边\nawait graph.draw();\n\n// 重新计算布局\nawait graph.layout();\n```\n\n**示例 3**: 监听布局事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 布局开始前\ngraph.on(GraphEvent.BEFORE_LAYOUT, () => {\n  console.log('布局计算开始...');\n});\n\n// 布局完成后\ngraph.on(GraphEvent.AFTER_LAYOUT, () => {\n  console.log('布局计算完成');\n});\n\n// 执行布局\ngraph.layout();\n```\n\n### Graph.stopLayout()\n\n停止正在进行中的布局计算。主要用于停止迭代类型的布局算法，如力导向布局。\n\n```typescript\nstopLayout(): void;\n```\n\n**说明**\n\n适用于带有迭代动画的布局，目前有 `force` 属于此类布局。当布局计算时间过长时，可以手动停止迭代。\n\n**示例 1**: 基本使用\n\n```typescript\n// 5秒后停止布局\nsetTimeout(() => {\n  graph.stopLayout();\n  console.log('布局已手动停止');\n}, 5000);\n```\n\n**示例 2**: 结合用户交互停止布局\n\n```typescript\n// 当用户点击画布时停止布局\nimport { CanvasEvent } from '@antv/g6';\n\ngraph.on(CanvasEvent.CLICK, () => {\n  graph.stopLayout();\n  console.log('用户点击画布，布局已停止');\n});\n```\n\n## 类型定义\n\n### LayoutOptions\n\n布局配置类型，可以是单一布局配置或布局配置数组。\n\n```typescript\ntype LayoutOptions = SingleLayoutOptions | SingleLayoutOptions[];\n```\n\n### SingleLayoutOptions\n\n单一布局配置，可以是内置布局配置或自定义基础布局配置。\n\n```typescript\ntype SingleLayoutOptions = BuiltInLayoutOptions | BaseLayoutOptions;\n```\n\n### BaseLayoutOptions\n\n所有布局类型共有的基础配置项。\n\n```typescript\ninterface BaseLayoutOptions {\n  // 布局类型\n  type: string;\n\n  // 参与该布局的节点过滤函数\n  nodeFilter?: (node: NodeData) => boolean;\n\n  // 是否在初始化元素前计算布局\n  preLayout?: boolean;\n\n  // 不可见节点是否参与布局（当 preLayout 为 true 时生效）\n  isLayoutInvisibleNodes?: boolean;\n\n  // 启用布局动画，对于迭代布局，会在两次迭代之间进行动画过渡\n  animation?: boolean;\n\n  // 是否在 WebWorker 中运行布局\n  enableWorker?: boolean;\n\n  // 迭代布局的迭代次数\n  iterations?: number;\n\n  // 其他特定布局的配置项\n  [key: string]: any;\n}\n```\n\n### BuiltInLayoutOptions\n\nG6 内置的布局类型配置，具体请查看 [API - 内置布局](/manual/layout/antv-dagre-layout)。\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/option.en.md) -->\n---\ntitle: Graph Options\norder: 7\n---\n\n## Overview of Graph Options\n\nThe [options](/en/manual/graph/option) of a G6 graph instance control various aspects of the graph, including canvas settings, viewport properties, data, layout, styles, interaction behaviors, plugins, and more. By configuring these options appropriately, you can flexibly customize the appearance and behavior of the graph.\n\nOptions can be specified when creating a graph instance or dynamically modified at runtime through the API. Some basic configurations (such as devicePixelRatio, container) require destroying and recreating the graph instance to take effect after modification.\n\n## API Reference\n\n### Graph.getOptions()\n\nRetrieve all configuration options of the current graph.\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**Return Value**\n\n- **Type**: [GraphOptions](/en/manual/graph/option)\n- **Description**: Complete configuration options of the current graph\n\n**Example**\n\n```typescript\n// Retrieve the current graph's options\nconst options = graph.getOptions();\nconsole.log('Current graph options:', options);\n\n// Retrieve specific options\nconsole.log('Current canvas width:', options.width);\nconsole.log('Current layout options:', options.layout);\n```\n\n### Graph.setOptions(options)\n\nUpdate the graph's configuration options.\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**Parameters**\n\n| Parameter | Description               | Type                                    | Default | Required |\n| --------- | ------------------------- | --------------------------------------- | ------- | -------- |\n| options   | New configuration options | [GraphOptions](/en/manual/graph/option) | -       | ✓        |\n\n**Note**\n\n⚠️ **Attention**: To update basic properties like devicePixelRatio, container, etc., you need to destroy the current graph instance and recreate it. Most other configurations can be dynamically updated.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Update graph configuration\ngraph.setOptions({\n  width: 1000, // Update width\n  height: 800, // Update height\n  autoFit: 'view', // Enable auto-fit\n  animation: true, // Enable animation\n});\n```\n\n**Example 2**: Update Theme\n\n```typescript\n// Update graph theme configuration\ngraph.setOptions({\n  theme: {\n    type: 'dark', // Switch to dark theme\n    // Custom theme configuration\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**Example 3**: Update Layout Configuration\n\n```typescript\n// Update layout configuration\ngraph.setOptions({\n  layout: {\n    type: 'force', // Switch to force-directed layout\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**Example 4**: Update Default Node and Edge Configuration\n\n```typescript\n// Update default style configuration for nodes and edges\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n\n## Type Definitions\n\n### GraphOptions\n\n```typescript\ntype GraphOptions = {\n  // Whether to enable zooming\n  enableZoom?: boolean;\n\n  // Whether to enable dragging\n  enableDrag?: boolean;\n\n  // Default style for nodes\n  defaultNodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Additional configuration options for the graph\n  [configKey: string]: any;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/option.zh.md) -->\n---\ntitle: 图配置项\norder: 7\n---\n\n## 图配置项概述\n\nG6 图实例的 [配置项](/manual/graph/option) 控制着图的各个方面，包括画布设置、视口属性、数据、布局、样式、交互行为、插件等。通过合理配置这些选项，可以灵活定制图的外观和行为。\n\n配置项可以在图实例创建时指定，也可以通过 API 在运行时动态修改。某些基础配置（如 devicePixelRatio、container）修改后需要销毁并重新创建图实例才能生效。\n\n## API 参考\n\n### Graph.getOptions()\n\n获取当前图表的所有配置项。\n\n```typescript\ngetOptions(): GraphOptions;\n```\n\n**返回值**\n\n- **类型**: [GraphOptions](/manual/graph/option)\n- **描述**: 当前图表的完整配置项\n\n**示例**\n\n```typescript\n// 获取当前图表的配置项\nconst options = graph.getOptions();\nconsole.log('当前图表配置:', options);\n\n// 获取特定配置\nconsole.log('当前画布宽度:', options.width);\nconsole.log('当前布局配置:', options.layout);\n```\n\n### Graph.setOptions(options)\n\n更新图表的配置项。\n\n```typescript\nsetOptions(options: GraphOptions): void;\n```\n\n**参数**\n\n| 参数    | 描述       | 类型                                 | 默认值 | 必选 |\n| ------- | ---------- | ------------------------------------ | ------ | ---- |\n| options | 新的配置项 | [GraphOptions](/manual/graph/option) | -      | ✓    |\n\n**说明**\n\n⚠️ **注意**: 要更新 devicePixelRatio、container 等基础属性，需要销毁当前图实例后重新创建。其他大部分配置可以动态更新。\n\n**示例 1**: 基本用法\n\n```typescript\n// 更新图表配置\ngraph.setOptions({\n  width: 1000, // 更新宽度\n  height: 800, // 更新高度\n  autoFit: 'view', // 开启自适应\n  animation: true, // 启用动画\n});\n```\n\n**示例 2**: 更新主题\n\n```typescript\n// 更新图表主题配置\ngraph.setOptions({\n  theme: {\n    type: 'dark', // 切换到暗色主题\n    // 自定义主题配置\n    node: {\n      palette: ['#1AAF8B', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n    edge: {\n      palette: ['#F5A623', '#F8E71C', '#8B572A', '#7ED321'],\n    },\n  },\n});\n```\n\n**示例 3**: 更新布局配置\n\n```typescript\n// 更新布局配置\ngraph.setOptions({\n  layout: {\n    type: 'force', // 切换到力导向布局\n    preventOverlap: true,\n    nodeStrength: -50,\n    edgeStrength: 0.7,\n  },\n});\n```\n\n**示例 4**: 更新节点和边的默认配置\n\n```typescript\n// 更新节点和边的默认样式配置\ngraph.setOptions({\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#40a9ff',\n      lineWidth: 1,\n      radius: 10,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 2,\n      endArrow: true,\n    },\n  },\n});\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/plugin.en.md) -->\n---\ntitle: Plugin\norder: 8\n---\n\n## Overview of Plugins\n\n[Plugins](/en/manual/plugin/overview) are an important mechanism in G6 for extending functionality and enhancing the interactive experience of graphs. Plugins typically provide independent functional modules, such as thumbnails, toolbars, context menus, etc. They integrate well with the main graph while maintaining modular and maintainable code.\n\nThe plugin system is designed to follow the \"plug and play\" principle, allowing dynamic addition or removal as needed.\n\n## API Reference\n\n### Graph.getPluginInstance(key)\n\nRetrieve the plugin instance specified by the key, used to access and operate the methods provided by the plugin.\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**Parameters**\n\n| Parameter | Description                     | Type   | Default | Required |\n| --------- | ------------------------------- | ------ | ------- | -------- |\n| key       | Unique identifier of the plugin | string | -       | ✓        |\n\n**Return Value**\n\n- **Type**: Plugin instance\n- **Description**: The plugin instance corresponding to the specified key\n\n**Note**\n\nMany plugins provide specific API methods, which can be directly called by obtaining the plugin instance. For example, the fullscreen plugin provides `request()` and `exit()` methods to control fullscreen status.\n\n**Example**: Operate the fullscreen plugin\n\n```typescript\n// Get the fullscreen plugin instance\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// Request to enter fullscreen\nfullscreen.request();\n\n// Exit fullscreen later\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\nRetrieve all configured plugins in the current graph.\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**Return Value**\n\n- **Type**: [PluginOptions](#pluginoptions)\n- **Description**: All configured plugins in the current graph\n\n**Example**\n\n```typescript\n// Get all plugin configurations\nconst plugins = graph.getPlugins();\n\n// View currently active plugins\nconsole.log('Current graph plugin configurations:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\nSet the graph's plugins, replacing all existing plugin configurations.\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                                                                     | Type                                                                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------- | -------- |\n| plugins   | New plugin configurations, or a function returning new configurations based on the current ones | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -       | ✓        |\n\n**Note**\n\nThe set plugins will completely replace the original plugin configurations. To add new plugins based on existing ones, you can use functional updates:\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**Example 1**: Set basic plugins\n\n```typescript\n// Set multiple basic plugins\ngraph.setPlugins([\n  // String form (using default configuration)\n  'minimap',\n\n  // Object form (custom configuration)\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**Example 2**: Use functional updates\n\n```typescript\n// Add new plugins to existing configurations\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// Replace specific plugins\ngraph.setPlugins((currentPlugins) => {\n  // Filter out existing grid plugins\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // Add new grid plugin configuration\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\nUpdate the configuration of a specified plugin, identified by the `key` of the plugin to be updated.\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                               | Type                                      | Default | Required |\n| --------- | ----------------------------------------- | ----------------------------------------- | ------- | -------- |\n| plugin    | Configuration of the plugin to be updated | [UpdatePluginOption](#updatepluginoption) | -       | ✓        |\n\n**Note**\n\nTo update a plugin, the `key` field must be specified in the original plugin configuration to accurately locate and update the plugin.\n\n**Example 1**: Update plugin configuration\n\n```typescript\n// Specify key when initially setting plugins\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// Update grid plugin configuration\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## Type Definitions\n\n### PluginOptions\n\nPlugin configuration type, representing an array of plugin configurations.\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\nCustom plugin configuration interface, used to configure plugin parameters.\n\n```typescript\ntype CustomPluginOption = {\n  // Plugin type\n  type: string;\n\n  // Plugin key, i.e., unique identifier\n  // Used to identify the plugin for further operations\n  key?: string;\n\n  // Other configuration items for different types of plugins\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\nConfiguration interface for updating plugins, used to dynamically modify plugin parameters.\n\n```typescript\ntype UpdatePluginOption = {\n  // Unique identifier of the plugin to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/plugin.zh.md) -->\n---\ntitle: 插件\norder: 8\n---\n\n## 插件概述\n\n[插件](/manual/plugin/overview)（Plugin）是 G6 中扩展功能的重要机制，用于增强图表的功能和交互体验。插件通常提供一些独立的功能模块，如缩略图、工具栏、上下文菜单等，它们可以与图表主体良好集成，同时又保持代码的模块化和可维护性。\n\n插件系统设计遵循\"即插即用\"的原则，可以根据需要动态添加或移除。\n\n## API 参考\n\n### Graph.getPluginInstance(key)\n\n获取指定 key 的插件实例，用于访问和操作插件提供的方法。\n\n```typescript\ngetPluginInstance<T extends Plugin>(key: string): T;\n```\n\n**参数**\n\n| 参数 | 描述             | 类型   | 默认值 | 必选 |\n| ---- | ---------------- | ------ | ------ | ---- |\n| key  | 插件的唯一标识符 | string | -      | ✓    |\n\n**返回值**\n\n- **类型**: 插件实例\n- **描述**: 指定 key 对应的插件实例\n\n**说明**\n\n许多插件提供了特定的API方法，通过获取插件实例可以直接调用这些方法。例如，全屏插件提供了 `request()` 和 `exit()` 方法来控制全屏状态。\n\n**示例**: 操作全屏插件\n\n```typescript\n// 获取全屏插件实例\nconst fullscreen = graph.getPluginInstance('fullscreen');\n\n// 请求进入全屏\nfullscreen.request();\n\n// 稍后退出全屏\nsetTimeout(() => {\n  fullscreen.exit();\n}, 5000);\n```\n\n### Graph.getPlugins()\n\n获取当前图表中所有已配置的插件。\n\n```typescript\ngetPlugins(): PluginOptions;\n```\n\n**返回值**\n\n- **类型**: [PluginOptions](#pluginoptions)\n- **描述**: 当前图表中已配置的所有插件\n\n**示例**\n\n```typescript\n// 获取所有插件配置\nconst plugins = graph.getPlugins();\n\n// 查看当前激活的插件\nconsole.log('当前图表的插件配置:', plugins);\n```\n\n### Graph.setPlugins(plugins)\n\n设置图表的插件，将替换所有现有的插件配置。\n\n```typescript\nsetPlugins(plugins: PluginOptions | ((prev: PluginOptions) => PluginOptions)): void;\n```\n\n**参数**\n\n| 参数    | 描述                                             | 类型                                                                        | 默认值 | 必选 |\n| ------- | ------------------------------------------------ | --------------------------------------------------------------------------- | ------ | ---- |\n| plugins | 新的插件配置，或一个基于当前配置返回新配置的函数 | [PluginOptions](#pluginoptions) \\| ((prev: PluginOptions) => PluginOptions) | -      | ✓    |\n\n**说明**\n\n设置的插件会全量替换原有的插件配置。如果需要在现有插件基础上添加新插件，可以使用函数式更新方式：\n\n```typescript\ngraph.setPlugins((plugins) => [...plugins, { type: 'grid', key: 'grid-line' }]);\n```\n\n**示例 1**: 设置基本插件\n\n```typescript\n// 设置多个基本插件\ngraph.setPlugins([\n  // 字符串形式（使用默认配置）\n  'minimap',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n  {\n    type: 'toolbar',\n    key: 'graph-toolbar',\n    position: 'top-right',\n  },\n]);\n```\n\n**示例 2**: 使用函数式更新\n\n```typescript\n// 添加新插件到现有配置\ngraph.setPlugins((currentPlugins) => [\n  ...currentPlugins,\n  {\n    type: 'grid',\n    key: 'grid-line',\n  },\n]);\n\n// 替换特定插件\ngraph.setPlugins((currentPlugins) => {\n  // 过滤掉现有的网格插件\n  const filteredPlugins = currentPlugins.filter((plugin) => {\n    if (typeof plugin === 'string') return plugin !== 'grid';\n    if (typeof plugin === 'function') return true;\n    return plugin.type !== 'grid';\n  });\n\n  // 添加新的网格插件配置\n  return [\n    ...filteredPlugins,\n    {\n      type: 'grid',\n      key: 'new-grid',\n      follow: true,\n    },\n  ];\n});\n```\n\n### Graph.updatePlugin(plugin)\n\n更新指定的插件配置，需要通过 `key` 标识要更新的插件。\n\n```typescript\nupdatePlugin(plugin: UpdatePluginOption): void;\n```\n\n**参数**\n\n| 参数   | 描述           | 类型                                      | 默认值 | 必选 |\n| ------ | -------------- | ----------------------------------------- | ------ | ---- |\n| plugin | 更新的插件配置 | [UpdatePluginOption](#updatepluginoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个插件，必须在原始插件配置中指定 `key` 字段，以便能够准确找到并更新该插件。\n\n**示例 1**: 更新插件配置\n\n```typescript\n// 初始设置插件时指定 key\ngraph.setPlugins([\n  {\n    type: 'grid',\n    key: 'main-grid',\n    follow: true,\n  },\n]);\n\n// 更新网格插件配置\ngraph.updatePlugin({\n  key: 'main-grid',\n  follow: false,\n});\n```\n\n## 类型定义\n\n### PluginOptions\n\n插件配置类型，表示一组插件配置的数组。\n\n```typescript\ntype PluginOptions = (string | CustomPluginOption | ((this: Graph) => CustomPluginOption))[];\n```\n\n### CustomPluginOption\n\n自定义插件配置接口，用于配置插件参数。\n\n```typescript\ntype CustomPluginOption = {\n  // 插件类型\n  type: string;\n\n  // 插件 key，即唯一标识\n  // 用于标识插件，从而进一步操作此插件\n  key?: string;\n\n  // 针对不同类型的插件，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdatePluginOption\n\n更新插件的配置接口，用于动态修改插件参数。\n\n```typescript\ntype UpdatePluginOption = {\n  // 要更新的插件的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/render.en.md) -->\n---\ntitle: Drawing and Rendering\norder: 3\n---\n\n## Overview of Drawing and Rendering\n\nG6 provides a series of drawing and rendering-related APIs to control the display process of graphical elements. In G6, drawing and rendering are two different concepts:\n\n- **Drawing (draw)**: Responsible only for drawing graphical elements onto the canvas, without involving layout calculations.\n- **Rendering (render)**: A complete rendering process, including data processing, layout calculations, and final drawing.\n\nUnderstanding the differences between these APIs is crucial for optimizing performance and achieving specific effects.\n\n## API Reference\n\n### Graph.draw()\n\nDraw elements without performing layout calculations.\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**Note**\n\nThe `draw` method only executes the drawing process of elements and does not recalculate the layout.\n\n⚠️ **Attention**: `draw` is an asynchronous method, requiring the use of `await` or Promise chaining to ensure subsequent operations are executed after drawing is complete.\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.draw();\n```\n\n**Example 2**: Redraw after modifying node styles\n\n```javascript\n// Redraw after modifying node styles\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// Only draw the updated styles without re-layout\nawait graph.draw();\n```\n\n**Example 3**: Batch update multiple elements and draw once\n\n```javascript\n// Update multiple nodes\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// Update edges\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// Draw after batch operations\nawait graph.draw();\n```\n\n**Example 4**: Use event listener to detect drawing completion\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('Drawing complete');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\nExecute the complete rendering process, including data processing, layout calculations, and drawing.\n\n```typescript\nrender(): Promise<void>;\n```\n\n**Note**\n\nThe `render` method executes the complete rendering process:\n\n1. Process data updates\n2. Draw elements onto the canvas\n3. Execute layout algorithms\n\n**Example 1**: Basic Usage\n\n```typescript\n// Basic usage\nawait graph.render();\n```\n\n**Example 2**: Render after adding new data\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**Example 3**: Listen to rendering events\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// Before rendering starts\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('Rendering starts...');\n  // Show loading indicator\n  showLoadingIndicator();\n});\n\n// After rendering completes\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('Rendering complete');\n  // Hide loading indicator\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\nClear all elements on the canvas, including nodes, edges, and other graphical elements.\n\n```typescript\nclear(): Promise<void>;\n```\n\n**Note**\n\nThis method deletes all elements in the graph but retains the canvas configuration and styles. It is an asynchronous method that returns a Promise.\n\n**Example**\n\n```typescript\n// Basic usage\nawait graph.clear();\n```\n\n## Usage Tips\n\n### Choosing between draw and render\n\n- Use `draw()` when:\n  - Only the styles or states of elements are modified, without needing to recalculate positions.\n  - Performance-sensitive, aiming to avoid unnecessary layout calculations.\n- Use `render()` when:\n  - Initializing the graph.\n  - Changing layout configurations.\n  - Adding or removing a large number of nodes/edges.\n  - Need to recalculate positions of all elements.\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/render.zh.md) -->\n---\ntitle: 绘制与渲染\norder: 3\n---\n\n## 绘制与渲染概述\n\nG6 提供了一系列绘制和渲染相关的 API，用于控制图形元素的显示过程。在 G6 中，绘制和渲染是两个不同的概念：\n\n- **绘制(draw)**: 仅负责将图形元素绘制到画布上，不涉及布局计算\n- **渲染(render)**: 完整的渲染流程，包括数据处理、布局计算和最终绘制\n\n理解这些 API 的区别对于优化性能和实现特定效果至关重要。\n\n## API 参考\n\n### Graph.draw()\n\n绘制元素，但不执行布局计算。\n\n```typescript\ndraw(): Promise<void>;\n```\n\n**说明**\n\n`draw` 方法仅执行元素的绘制过程，不会重新计算布局。\n\n⚠️ **注意**: `draw` 为异步方法，需要使用 `await` 或 Promise 链式调用来确保绘制完成后再执行后续操作。\n\n**示例 1**: 基础用法\n\n```typescript\n// 基本用法\nawait graph.draw();\n```\n\n**示例 2**: 修改节点样式后重新绘制\n\n```javascript\n// 修改节点样式后重新绘制\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    style: {\n      fill: 'red',\n      stroke: 'blue',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 仅绘制更新后的样式，不重新布局\nawait graph.draw();\n```\n\n**示例 3**: 批量更新多个元素后一次性绘制\n\n```javascript\n// 更新多个节点\ngraph.updateNodeData([{ id: 'node1', style: { fill: 'red' } }]);\ngraph.updateNodeData([{ id: 'node2', style: { fill: 'blue' } }]);\n\n// 更新边\ngraph.updateEdgeData([{ id: 'edge1', style: { stroke: 'green' } }]);\n\n// 批量操作完成后绘制\nawait graph.draw();\n```\n\n**示例 4**: 使用事件监听绘制完成\n\n```javascript\nimport { GraphEvent } from '@antv/g6';\n\ngraph.on(GraphEvent.AFTER_DRAW, () => {\n  console.log('绘制完成');\n});\n\nawait graph.draw();\n```\n\n### Graph.render()\n\n执行完整的渲染流程，包括数据处理、布局计算和绘制。\n\n```typescript\nrender(): Promise<void>;\n```\n\n**说明**\n\n`render` 方法会执行完整的渲染流程：\n\n1. 处理数据更新\n2. 绘制元素到画布上\n3. 执行布局算法\n\n**示例 1**: 基本用法\n\n```typescript\n// 基本用法\nawait graph.render();\n```\n\n**示例 2**: 添加新数据后渲染\n\n```typescript\ngraph.addData({\n  nodes: [{ id: 'node3' }, { id: 'node4' }],\n  edges: [{ id: 'edge2', source: 'node1', target: 'node3' }],\n});\nawait graph.render();\n```\n\n**示例 3**: 监听渲染事件\n\n```typescript\nimport { GraphEvent } from '@antv/g6';\n\n// 渲染开始前\ngraph.on(GraphEvent.BEFORE_RENDER, () => {\n  console.log('渲染开始...');\n  // 显示加载指示器\n  showLoadingIndicator();\n});\n\n// 渲染完成后\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  console.log('渲染完成');\n  // 隐藏加载指示器\n  hideLoadingIndicator();\n});\n\ngraph.render();\n```\n\n### Graph.clear()\n\n清空画布上的所有元素，包括节点、边和其他图形元素。\n\n```typescript\nclear(): Promise<void>;\n```\n\n**说明**\n\n此方法会删除图中的所有元素，但保留画布配置和样式。这是一个异步方法，返回一个 Promise。\n\n**示例**\n\n```typescript\n// 基本用法\nawait graph.clear();\n```\n\n## 使用技巧\n\n### draw 与 render 的选择\n\n- 使用 `draw()` 当:\n  - 仅修改了元素样式或状态，不需要重新计算位置\n  - 性能敏感，希望避免不必要的布局计算\n- 使用 `render()` 当:\n  - 初始化图表\n  - 更改了布局配置\n  - 添加或删除了大量节点/边\n  - 需要重新计算所有元素位置\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/theme.en.md) -->\n---\ntitle: Theme\norder: 9\n---\n\n## Overview of Theme\n\nG6 allows users to customize the appearance of graphs through themes. Themes can be used to define colors, shapes, and styles for nodes, edges, and other graph elements.\n\n## API Reference\n\n### Graph.getTheme()\n\nGet the theme\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>Related Parameters</summary>\n\n**Return Value**:\n\n- **Type:** false \\| 'light' \\| 'dark' \\| string\n\n- **Description:** Current theme\n\n</details>\n\n### Graph.setTheme(theme)\n\nSet the theme\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**Example**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>Related Parameters</summary>\n\n<table><thead><tr><th>\n\nParameter\n\n</th><th>\n\nType\n\n</th><th>\n\nDescription\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) => false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\nTheme name\n\n</td></tr>\n</tbody></table>\n\n**Return Value**:\n\n- **Type:** void\n\n</details>\n\n## Type Definitions\n\n### ThemeOptions\n\n```typescript\ntype ThemeOptions = {\n  // Colors used in the theme\n  colors: string[];\n\n  // Node style settings\n  nodeStyle?: {\n    fill: string;\n    stroke: string;\n  };\n\n  // Edge style settings\n  edgeStyle?: {\n    stroke: string;\n  };\n\n  // Additional configuration options for the theme\n  [configKey: string]: any;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/theme.zh.md) -->\n---\ntitle: 主题\norder: 9\n---\n\n## API 参考\n\n### Graph.getTheme()\n\n获取主题\n\n```typescript\ngetTheme(): ThemeOptions;\n```\n\n<details><summary>相关参数</summary>\n\n**返回值**：\n\n- **类型：** false \\| 'light' \\| 'dark' \\| string\n\n- **描述：** 当前主题\n\n</details>\n\n### Graph.setTheme(theme)\n\n设置主题\n\n```typescript\nsetTheme(theme: ThemeOptions | ((prev: ThemeOptions) => ThemeOptions)): void;\n```\n\n**示例**\n\n```ts\ngraph.setTheme('dark');\n```\n\n<details><summary>相关参数</summary>\n\n<table><thead><tr><th>\n\n参数\n\n</th><th>\n\n类型\n\n</th><th>\n\n描述\n\n</th></tr></thead>\n<tbody><tr><td>\n\ntheme\n\n</td><td>\n\nfalse \\| 'light' \\| 'dark' \\| string \\| ((prev: false \\| 'light' \\| 'dark' \\| string) =&gt; false \\| 'light' \\| 'dark' \\| string)\n\n</td><td>\n\n主题名\n\n</td></tr>\n</tbody></table>\n\n**返回值**：\n\n- **类型：** void\n\n</details>\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/transform.en.md) -->\n---\ntitle: Data Transformation\norder: 10\n---\n\n## Overview of Data Transformation\n\n[Data Transformation](/en/manual/transform/overview) is a powerful feature in G6 that allows for processing and transforming data during the graph rendering process. With data transformers, you can achieve various data processing needs, such as:\n\n- Data Filtering: Filter nodes and edges to be displayed based on conditions\n- Data Calculation: Generate new attributes based on original data, such as calculating node size based on the number of connections, without polluting the original data\n- Data Aggregation: Aggregate a large number of nodes into fewer nodes to improve the performance of large-scale graphs\n\nData transformation occurs at specific stages of the rendering process, allowing flexible changes to the final presentation without modifying the original data source.\n\n## API Reference\n\n### Graph.getTransforms()\n\nRetrieve all configured data transformers in the current graph.\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**Return Value**\n\n- **Type**: [TransformOptions](#transformoptions)\n- **Description**: All configured data transformers in the current graph\n\n**Example**\n\n```typescript\n// Retrieve all data transformers\nconst transforms = graph.getTransforms();\nconsole.log('Data transformers in the current graph:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\nSet the data transformers for the graph, replacing all existing transformers.\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**Parameters**\n\n| Parameter  | Description                                                                                               | Type                                                                                  | Default | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------- | -------- |\n| transforms | New data transformer configurations, or a function returning new configurations based on the current ones | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -       | ✓        |\n\n**Note**\n\nData transformers can process data at different stages of the graph rendering process. The set data transformations will completely replace the original ones. To add new data transformations based on existing ones, you can use functional updates.\n\n**Example 1**: Set basic data transformations\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**Example 2**: Set data transformations with configurations\n\n```typescript\ngraph.setTransforms([\n  // String form (using default configuration)\n  'process-parallel-edges',\n\n  // Object form (custom configuration)\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // Distance between parallel edges\n  },\n]);\n```\n\n**Example 3**: Use functional updates\n\n```typescript\n// Add new data transformations to existing configurations\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\nUpdate the configuration of a specified data transformer, identified by the `key` of the transformer to be updated.\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**Parameters**\n\n| Parameter | Description                                         | Type                                            | Default | Required |\n| --------- | --------------------------------------------------- | ----------------------------------------------- | ------- | -------- |\n| transform | Configuration of the data transformer to be updated | [UpdateTransformOption](#updatetransformoption) | -       | ✓        |\n\n**Note**\n\nTo update a data transformer, the `key` field must be specified in the original data transformer configuration to accurately locate and update the transformer.\n\n**Example**: Update data transformer configuration\n\n```typescript\n// Specify key when initially setting data transformers\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// Update distance between parallel edges\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## Type Definitions\n\n### TransformOptions\n\nData transformer configuration type, representing an array of data transformer configurations.\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\nCustom data transformer configuration interface, used to configure data processing parameters.\n\n```typescript\ntype CustomTransformOption = {\n  // Data processing type\n  type: string;\n\n  // Unique identifier for the data transformer\n  key?: string;\n\n  // Other configuration items for different types of data processing\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\nConfiguration interface for updating data transformers, used to dynamically modify data processing parameters.\n\n```typescript\ntype UpdateTransformOption = {\n  // Unique identifier of the data transformer to be updated\n  key: string;\n\n  // Other configuration items to be updated\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/transform.zh.md) -->\n---\ntitle: 数据处理\norder: 10\n---\n\n## 数据处理概述\n\n[数据处理](/manual/transform/overview)（Transform）是 G6 中一项强大的功能，允许在图渲染过程中对数据进行处理和转换。通过数据处理器，您可以实现各种数据处理需求，比如：\n\n- 数据过滤：根据条件筛选需要显示的节点和边\n- 数据计算：基于原始数据生成新的属性，如根据节点连接数计算节点大小，但不污染原始数据\n- 数据聚合：将大量节点聚合为少量节点，提高大规模图表的性能\n\n数据处理发生在渲染流程的特定阶段，可以灵活地改变最终呈现的结果，而无需修改原始数据源。\n\n## API 参考\n\n### Graph.getTransforms()\n\n获取当前图表中所有已配置的数据处理器。\n\n```typescript\ngetTransforms(): TransformOptions;\n```\n\n**返回值**\n\n- **类型**: [TransformOptions](#transformoptions)\n- **描述**: 当前图表中已配置的所有数据处理器\n\n**示例**\n\n```typescript\n// 获取当前所有数据处理器\nconst transforms = graph.getTransforms();\nconsole.log('当前图表的数据处理器:', transforms);\n```\n\n### Graph.setTransforms(transforms)\n\n设置图表的数据处理器，将替换所有现有的数据处理器。\n\n```typescript\nsetTransforms(transforms: TransformOptions | ((prev: TransformOptions) => TransformOptions)): void;\n```\n\n**参数**\n\n| 参数       | 描述                                                   | 类型                                                                                  | 默认值 | 必选 |\n| ---------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------ | ---- |\n| transforms | 新的数据处理器配置，或一个基于当前配置返回新配置的函数 | [TransformOptions](#transformoptions) \\| (prev: TransformOptions) => TransformOptions | -      | ✓    |\n\n**说明**\n\n数据处理器能够在图渲染过程的不同阶段对数据进行处理。设置的数据处理会全量替换原有的数据处理，如果需要在现有数据处理基础上添加新的数据处理，可以使用函数式更新方式。\n\n**示例 1**: 设置基本数据处理\n\n```typescript\ngraph.setTransforms(['process-parallel-edges', 'map-node-size']);\n```\n\n**示例 2**: 设置带配置的数据处理\n\n```typescript\ngraph.setTransforms([\n  // 字符串形式（使用默认配置）\n  'process-parallel-edges',\n\n  // 对象形式（自定义配置）\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20, // 平行边之间的距离\n  },\n]);\n```\n\n**示例 3**: 使用函数式更新\n\n```typescript\n// 添加新的数据处理到现有配置\ngraph.setTransforms((currentTransforms) => [\n  ...currentTransforms,\n  {\n    type: 'map-node-size',\n    key: 'my-map-node-size',\n    maxSize: 100,\n    minSize: 20,\n  },\n]);\n```\n\n### Graph.updateTransform(transform)\n\n更新指定的数据处理器配置，需要通过 `key` 标识要更新的数据处理。\n\n```typescript\nupdateTransform(transform: UpdateTransformOption): void;\n```\n\n**参数**\n\n| 参数      | 描述               | 类型                                            | 默认值 | 必选 |\n| --------- | ------------------ | ----------------------------------------------- | ------ | ---- |\n| transform | 更新的数据处理配置 | [UpdateTransformOption](#updatetransformoption) | -      | ✓    |\n\n**说明**\n\n如果要更新一个数据处理器，必须在原始数据处理配置中指定 `key` 字段，以便能够准确找到并更新该数据处理。\n\n**示例**: 更新数据处理配置\n\n```typescript\n// 初始设置数据处理时指定 key\ngraph.setTransforms([\n  {\n    type: 'process-parallel-edges',\n    key: 'my-process-parallel-edges',\n    distance: 20,\n  },\n]);\n\n// 更新平行边距离\ngraph.updateTransform({\n  key: 'my-process-parallel-edges',\n  distance: 30,\n});\n```\n\n## 类型定义\n\n### TransformOptions\n\n数据处理器配置类型，表示一组数据处理配置的数组。\n\n```typescript\ntype TransformOptions = (CustomTransformOption | ((this: Graph) => CustomTransformOption))[];\n```\n\n### CustomTransformOption\n\n自定义数据处理配置接口，用于配置数据处理参数。\n\n```typescript\ntype CustomTransformOption = {\n  // 数据处理类型\n  type: string;\n\n  // 数据处理唯一标识\n  key?: string;\n\n  // 针对不同类型的数据处理，还可能有其他配置项\n  [configKey: string]: any;\n};\n```\n\n### UpdateTransformOption\n\n更新数据处理的配置接口，用于动态修改数据处理参数。\n\n```typescript\ntype UpdateTransformOption = {\n  // 要更新的数据处理的唯一标识\n  key: string;\n\n  // 其他要更新的配置项\n  [configKey: string]: unknown;\n};\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/viewport.en.md) -->\n---\ntitle: Viewport Operations\norder: 4\n---\n\n## Overview of Viewport Operations\n\nG6 provides a series of viewport operation APIs to control the zooming, panning, and rotating of the canvas. These operations help users better view and interact with graphical content. Through viewport operations, you can achieve the following functions:\n\n- Zoom the canvas to view details or the global view\n- Pan the canvas to view different areas\n- Rotate the canvas to get different perspectives\n- Automatically fit content to the viewport\n\n### Categories of Viewport Operations\n\nViewport operations in G6 are mainly divided into the following categories:\n\n1. **Zoom Operations**: such as `zoomTo`, `zoomBy`\n2. **Pan Operations**: such as `translateTo`, `translateBy`\n3. **Rotate Operations**: such as `rotateTo`, `rotateBy`\n4. **Fit Operations**: such as `fitView`, `fitCenter`\n5. **Viewport Information Retrieval**: such as `getZoom`, `getPosition`\n\n## API Reference\n\n### Graph.zoomTo(zoom, animation, origin)\n\nZoom the canvas to a specified scale (absolute zoom).\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                                    | Type                                                            | Default | Required |\n| --------- | -------------------------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| zoom      | Target zoom scale (1 = original size, >1 zoom in, <1 zoom out) | number                                                          | -       | ✓        |\n| animation | Animation configuration                                        | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates)                       | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in to 2x\ngraph.zoomTo(2);\n\n// Zoom out to 0.5x with animation\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// Zoom in with the viewport center as the origin\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\nZoom based on the current zoom scale (relative zoom).\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                              | Type                                                            | Default | Required |\n| --------- | ---------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| ratio     | Zoom ratio (>1 zoom in, <1 zoom out)     | number                                                          | -       | ✓        |\n| animation | Animation configuration                  | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Zoom center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Zoom in by 1.2x based on the current scale\ngraph.zoomBy(1.2);\n\n// Zoom out to 0.8x based on the current scale with animation\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\nPan the graph to a specified position (absolute pan).\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                 | Type                                                            | Default | Required |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| position  | Target position coordinates | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan to a specified position\ngraph.translateTo([100, 100]);\n\n// Pan with animation\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\nPan the graph by a specified distance relative to the current position (relative pan).\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| offset    | Pan offset              | [Point](#point)                                                 | -       | ✓        |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Pan right by 100 pixels and down by 50 pixels\ngraph.translateBy([100, 50]);\n\n// Relative pan with animation\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\nRotate the canvas to a specified angle (absolute rotation).\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Target rotation angle (radians)              | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate to 45 degrees\ngraph.rotateTo(Math.PI / 4);\n\n// Rotate to 90 degrees with animation\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\nRotate based on the current angle (relative rotation).\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description                                  | Type                                                            | Default | Required |\n| --------- | -------------------------------------------- | --------------------------------------------------------------- | ------- | -------- |\n| angle     | Rotation angle increment (radians)           | number                                                          | -       | ✓        |\n| animation | Animation configuration                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n| origin    | Rotation center point (viewport coordinates) | [Point](#point)                                                 | -       |          |\n\n**Example**\n\n```typescript\n// Rotate clockwise by 30 degrees relative to the current angle\ngraph.rotateBy(Math.PI / 6);\n\n// Relative rotation with animation\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\nScale the graph to fit the appropriate size and pan to the center of the viewport.\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| options   | Fit options             | FitViewOptions                                                  | -       |          |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**FitViewOptions Type Description**\n\n| Property  | Type                   | Default    | Description                                       |\n| --------- | ---------------------- | ---------- | ------------------------------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | Fit timing: only when overflow or always          |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | Fit direction: x-axis, y-axis, or both directions |\n\n**Example**\n\n```typescript\n// Basic usage\ngraph.fitView();\n\n// Configure fit options\ngraph.fitView(\n  {\n    when: 'always', // Always fit\n    direction: 'both', // Fit in both directions\n  },\n  {\n    duration: 1000, // With animation\n  },\n);\n\n// Fit in the x direction only when content overflows\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\nPan the graph to the center of the viewport.\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**Parameters**\n\n| Parameter | Description             | Type                                                            | Default | Required |\n| --------- | ----------------------- | --------------------------------------------------------------- | ------- | -------- |\n| animation | Animation configuration | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -       |          |\n\n**Example**\n\n```typescript\n// Center the graph\ngraph.fitCenter();\n\n// Center with animation\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\nGet the current zoom scale.\n\n```typescript\ngetZoom(): number;\n```\n\n**Example**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('Current zoom scale:', currentZoom);\n```\n\n### Graph.getPosition()\n\nGet the position of the graph (position of the canvas origin in the viewport coordinate system).\n\n```typescript\ngetPosition(): Point;\n```\n\n**Example**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('Current position:', position);\n```\n\n### Graph.getRotation()\n\nGet the current rotation angle.\n\n```typescript\ngetRotation(): number;\n```\n\n**Example**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('Current rotation angle (radians):', rotation);\nconsole.log('Current rotation angle (degrees):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\nGet the viewport coordinates of the viewport center.\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('Viewport center coordinates:', center);\n```\n\n### Graph.getViewportCenter()\n\nGet the canvas coordinates of the viewport center.\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**Example**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('Canvas coordinates of the viewport center:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\nSet the zoom range of the current graph.\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**Parameters**\n\n| Parameter | Description | Type                          | Default | Required |\n| --------- | ----------- | ----------------------------- | ------- | -------- |\n| zoomRange | Zoom range  | [number, number] \\| undefined | -       | ✓        |\n\n**Example**\n\n```typescript\n// Limit the zoom range between 0.5x and 2x\ngraph.setZoomRange([0.5, 2]);\n\n// Remove zoom restrictions\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\nGet the zoom range of the current graph.\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**Example**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('Current zoom range:', range);\n```\n\n### Graph.resize()\n\nResize the canvas to the size of the graph container.\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\nResize the canvas to the specified width and height.\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**Parameters**\n\n| Parameter | Description   | Type   | Default | Required |\n| --------- | ------------- | ------ | ------- | -------- |\n| width     | Target width  | number | -       | ✓        |\n| height    | Target height | number | -       | ✓        |\n\n**Example**\n\n```typescript\n// Set the canvas size to 800x600\ngraph.resize(800, 600);\n```\n\n## Type Definitions\n\n### ViewportAnimationEffectTiming\n\nViewport animation configuration type.\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // Whether to enable animation\n  | {\n      easing?: string; // Easing function\n      duration?: number; // Animation duration (ms)\n    };\n```\n\n### Point\n\nCoordinate point type.\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\nView fit options.\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // Fit timing\n  direction?: 'x' | 'y' | 'both'; // Fit direction\n}\n```\n\n\n<!-- Skill/Rule: Api Skill (packages/site/docs/api/viewport.zh.md) -->\n---\ntitle: 视口操作\norder: 4\n---\n\n## 视口操作概述\n\nG6 提供了一系列视口操作 API，用于控制画布的缩放、平移和旋转。这些操作可以帮助用户更好地查看和交互图形内容。通过视口操作，你可以实现以下功能：\n\n- 缩放画布以查看细节或全局视图\n- 平移画布以查看不同区域\n- 旋转画布以获得不同视角\n- 自动适配内容到视口\n\n### 视口操作分类\n\nG6 的视口操作主要分为以下几类：\n\n1. **缩放操作**：如 `zoomTo`、`zoomBy`\n2. **平移操作**：如 `translateTo`、`translateBy`\n3. **旋转操作**：如 `rotateTo`、`rotateBy`\n4. **自适应操作**：如 `fitView`、`fitCenter`\n5. **视口信息获取**：如 `getZoom`、`getPosition`\n\n## API 参考\n\n### Graph.zoomTo(zoom, animation, origin)\n\n缩放画布至指定比例（绝对缩放）。\n\n```typescript\nzoomTo(zoom: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                                          | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| zoom      | 目标缩放比例 (1 = 原始大小, >1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                                      | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)                          | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 放大到2倍\ngraph.zoomTo(2);\n\n// 带动画效果的缩小到0.5倍\ngraph.zoomTo(0.5, {\n  duration: 500,\n  easing: 'ease',\n});\n\n// 以视口中心点为原点放大\ngraph.zoomTo(1.5, false, graph.getCanvasCenter());\n```\n\n### Graph.zoomBy(ratio, animation, origin)\n\n基于当前缩放比例进行缩放（相对缩放）。\n\n```typescript\nzoomBy(ratio: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                        | 类型                                                            | 默认值 | 必选 |\n| --------- | --------------------------- | --------------------------------------------------------------- | ------ | ---- |\n| ratio     | 缩放比例 (>1 放大, <1 缩小) | number                                                          | -      | ✓    |\n| animation | 动画配置                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 缩放中心点(视口坐标)        | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 在当前比例基础上放大1.2倍\ngraph.zoomBy(1.2);\n\n// 在当前比例基础上缩小到0.8倍，带动画\ngraph.zoomBy(0.8, {\n  duration: 300,\n});\n```\n\n### Graph.translateTo(position, animation)\n\n将图平移至指定位置（绝对平移）。\n\n```typescript\ntranslateTo(position: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述         | 类型                                                            | 默认值 | 必选 |\n| --------- | ------------ | --------------------------------------------------------------- | ------ | ---- |\n| position  | 目标位置坐标 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置     | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 平移到指定位置\ngraph.translateTo([100, 100]);\n\n// 带动画效果的平移\ngraph.translateTo([200, 200], {\n  duration: 1000,\n  easing: 'ease-in-out',\n});\n```\n\n### Graph.translateBy(offset, animation)\n\n将图相对当前位置平移指定距离（相对平移）。\n\n```typescript\ntranslateBy(offset: Point, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述       | 类型                                                            | 默认值 | 必选 |\n| --------- | ---------- | --------------------------------------------------------------- | ------ | ---- |\n| offset    | 平移偏移量 | [Point](#point)                                                 | -      | ✓    |\n| animation | 动画配置   | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 向右平移100像素，向下平移50像素\ngraph.translateBy([100, 50]);\n\n// 带动画效果的相对平移\ngraph.translateBy([-50, -50], {\n  duration: 500,\n});\n```\n\n### Graph.rotateTo(angle, animation, origin)\n\n旋转画布至指定角度（绝对旋转）。\n\n```typescript\nrotateTo(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 目标旋转角度(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 旋转到45度\ngraph.rotateTo(Math.PI / 4);\n\n// 带动画效果的旋转到90度\ngraph.rotateTo(Math.PI / 2, {\n  duration: 1000,\n});\n```\n\n### Graph.rotateBy(angle, animation, origin)\n\n基于当前角度进行旋转（相对旋转）。\n\n```typescript\nrotateBy(angle: number, animation?: ViewportAnimationEffectTiming, origin?: Point): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述                 | 类型                                                            | 默认值 | 必选 |\n| --------- | -------------------- | --------------------------------------------------------------- | ------ | ---- |\n| angle     | 旋转角度增量(弧度制) | number                                                          | -      | ✓    |\n| animation | 动画配置             | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n| origin    | 旋转中心点(视口坐标) | [Point](#point)                                                 | -      |      |\n\n**示例**\n\n```typescript\n// 相对当前角度顺时针旋转30度\ngraph.rotateBy(Math.PI / 6);\n\n// 带动画效果的相对旋转\ngraph.rotateBy(-Math.PI / 4, {\n  duration: 500,\n  easing: 'ease-out',\n});\n```\n\n### Graph.fitView(options, animation)\n\n将图缩放至合适大小并平移至视口中心。\n\n```typescript\nfitView(options?: FitViewOptions, animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| options   | 适配选项 | FitViewOptions                                                  | -      |      |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**FitViewOptions 类型说明**\n\n| 属性      | 类型                   | 默认值     | 描述                         |\n| --------- | ---------------------- | ---------- | ---------------------------- |\n| when      | 'overflow' \\| 'always' | 'overflow' | 适配时机：仅溢出时或始终适配 |\n| direction | 'x' \\| 'y' \\| 'both'   | 'both'     | 适配方向：x轴、y轴或两个方向 |\n\n**示例**\n\n```typescript\n// 基本使用\ngraph.fitView();\n\n// 配置适配选项\ngraph.fitView(\n  {\n    when: 'always', // 始终进行适配\n    direction: 'both', // 在两个方向上适配\n  },\n  {\n    duration: 1000, // 带动画效果\n  },\n);\n\n// 仅在内容溢出时适配x方向\ngraph.fitView({\n  when: 'overflow',\n  direction: 'x',\n});\n```\n\n### Graph.fitCenter(animation)\n\n将图平移至视口中心。\n\n```typescript\nfitCenter(animation?: ViewportAnimationEffectTiming): Promise<void>;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                                                            | 默认值 | 必选 |\n| --------- | -------- | --------------------------------------------------------------- | ------ | ---- |\n| animation | 动画配置 | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | -      |      |\n\n**示例**\n\n```typescript\n// 居中显示\ngraph.fitCenter();\n\n// 带动画效果的居中\ngraph.fitCenter({\n  duration: 500,\n  easing: 'ease-in',\n});\n```\n\n### Graph.getZoom()\n\n获取当前缩放比例。\n\n```typescript\ngetZoom(): number;\n```\n\n**示例**\n\n```typescript\nconst currentZoom = graph.getZoom();\nconsole.log('当前缩放比例:', currentZoom);\n```\n\n### Graph.getPosition()\n\n获取图的位置（画布原点在视口坐标系下的位置）。\n\n```typescript\ngetPosition(): Point;\n```\n\n**示例**\n\n```typescript\nconst position = graph.getPosition();\nconsole.log('当前位置:', position);\n```\n\n### Graph.getRotation()\n\n获取当前旋转角度。\n\n```typescript\ngetRotation(): number;\n```\n\n**示例**\n\n```typescript\nconst rotation = graph.getRotation();\nconsole.log('当前旋转角度(弧度):', rotation);\nconsole.log('当前旋转角度(度):', (rotation * 180) / Math.PI);\n```\n\n### Graph.getCanvasCenter()\n\n获取视口中心的视口坐标。\n\n```typescript\ngetCanvasCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst center = graph.getCanvasCenter();\nconsole.log('视口中心坐标:', center);\n```\n\n### Graph.getViewportCenter()\n\n获取视口中心的画布坐标。\n\n```typescript\ngetViewportCenter(): Point;\n```\n\n**示例**\n\n```typescript\nconst viewportCenter = graph.getViewportCenter();\nconsole.log('视口中心的画布坐标:', viewportCenter);\n```\n\n### Graph.setZoomRange(zoomRange)\n\n设置当前图的缩放区间。\n\n```typescript\nsetZoomRange(zoomRange: [number, number]): void;\n```\n\n**参数**\n\n| 参数      | 描述     | 类型                          | 默认值 | 必选 |\n| --------- | -------- | ----------------------------- | ------ | ---- |\n| zoomRange | 缩放区间 | [number, number] \\| undefined | -      | ✓    |\n\n**示例**\n\n```typescript\n// 限制缩放范围在0.5到2倍之间\ngraph.setZoomRange([0.5, 2]);\n\n// 移除缩放限制\ngraph.setZoomRange(undefined);\n```\n\n### Graph.getZoomRange()\n\n获取当前图的缩放区间。\n\n```typescript\ngetZoomRange(): GraphOptions['zoomRange'];\n```\n\n**示例**\n\n```typescript\nconst range = graph.getZoomRange();\nconsole.log('当前缩放区间:', range);\n```\n\n### Graph.resize()\n\n调整画布大小为图容器大小。\n\n```typescript\nresize(): void;\n```\n\n### Graph.resize(width, height)\n\n调整画布大小为指定宽高。\n\n```typescript\nresize(width: number, height: number): void;\n```\n\n**参数**\n\n| 参数   | 描述     | 类型   | 默认值 | 必选 |\n| ------ | -------- | ------ | ------ | ---- |\n| width  | 目标宽度 | number | -      | ✓    |\n| height | 目标高度 | number | -      | ✓    |\n\n**示例**\n\n```typescript\n// 设置画布大小为800x600\ngraph.resize(800, 600);\n```\n\n## 类型定义\n\n### ViewportAnimationEffectTiming\n\n视口动画配置类型。\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // 是否启用动画\n  | {\n      easing?: string; // 缓动函数\n      duration?: number; // 动画持续时间(ms)\n    };\n```\n\n### Point\n\n坐标点类型。\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n### FitViewOptions\n\n视图适配选项。\n\n```typescript\ninterface FitViewOptions {\n  when?: 'overflow' | 'always'; // 适配时机\n  direction?: 'x' | 'y' | 'both'; // 适配方向\n}\n```\n\n\n<!-- Skill/Rule: Backup Skill (packages/site/docs/backup/CameraSetting.en.md) -->\n---\ntitle: CameraSetting\n---\n\n## Options\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _string_\n\nPlugin type\n\n### aspect\n\n> _number \\| 'auto'_\n\nCamera viewport aspect ratio, only valid in perspective camera.\n\n- number : Specific aspect ratio\n\n- `'auto'` : Automatically set to the aspect ratio of the canvas\n\n### azimuth\n\n> _number_\n\nAzimuth\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\nCamera type\n\n- `'orbiting'`: Fixed viewpoint, change camera position\n\n- `'exploring'`: Similar to orbiting, but allows the camera to rotate between the North Pole and the South Pole\n\n- `'tracking'`: Fixed camera position, change viewpoint\n\n### distance\n\n> _number_ **Default:** `500`\n\nThe distance from the camera to the target\n\n### elevation\n\n> _number_\n\nElevation\n\n### far\n\n> _number_\n\nThe position of the far plane\n\n### fov\n\n> _number_\n\nCamera field of view, only valid in perspective camera\n\n### maxDistance\n\n> _number_\n\nMaximum distance\n\n### minDistance\n\n> _number_\n\nMinimum distance\n\n### near\n\n> _number_\n\nThe position of the near plane\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\nProjection mode, perspective projection is only valid in 3D scenes\n\n- `'perspective'` : perspective projection\n\n- `'orthographic'` : Orthogonal projection\n\n### roll\n\n> _number_\n\nRoll\n\n## API\n\n\n<!-- Skill/Rule: Backup Skill (packages/site/docs/backup/CameraSetting.zh.md) -->\n---\ntitle: CameraSetting 相机设置\n---\n\n## 配置项\n\n### <Badge type=\"success\">Required</Badge> type\n\n> _`camera-setting` \\| string_\n\n⚠️ **注意**：\n\n- 相机设置插件必须在 3D 场景下使用\n- 此插件在使用前需要自行注册：\n\n```javascript\nimport { register, CameraSetting, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting); // type: 'camera-setting'\n```\n\n### aspect\n\n> _number \\| `'auto'`_\n\n相机视口宽高比，仅在透视相机下有效\n\n- number : 具体的宽高比\n\n- `'auto'` : 自动设置为画布的宽高比\n\n### azimuth\n\n> _number_\n\n方位角\n\n### cameraType\n\n> _'orbiting' \\| 'exploring' \\| 'tracking'_\n\n相机类型\n\n- `'orbiting'`: 固定视点，改变相机位置\n- `'exploring'`: 类似 orbiting，但允许相机在北极和南极之间旋转\n- `'tracking'`: 固定相机位置，改变视点\n\n### distance\n\n> _number_ **Default:** `500`\n\n相机距离目标的距离\n\n### elevation\n\n> _number_\n\n仰角\n\n### far\n\n> _number_\n\n远平面位置\n\n### fov\n\n> _number_\n\n相机视角，仅在透视相机下有效\n\n### maxDistance\n\n> _number_\n\n最大视距\n\n### minDistance\n\n> _number_\n\n最小视距\n\n### near\n\n> _number_\n\n近平面位置\n\n### projectionMode\n\n> _'perspective' \\| 'orthographic'_\n\n投影模式，透视投影仅在 3D 场景下有效\n\n- `'perspective'` : 透视投影\n- `'orthographic'` : 正交投影\n\n### roll\n\n> _number_\n\n滚转角\n\n## API\n\n\n<!-- Skill/Rule: Animation Skill (packages/site/docs/manual/animation/animation.en.md) -->\n---\ntitle: Animation Overview\norder: 1\n---\n\n## Overview\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nAnimation refers to the state changes of elements over a period of time, such as the position, size, and color of nodes. In G6, animations are often used to enhance user experience and improve the coherence and smoothness of the graph update process.\n\nG6 provides a set of animation paradigms to describe element animations and has built-in some common animation effects. Users can achieve different animation effects by configuring animation parameters.\n\nThe implementation of an animation paradigm is as follows:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\nThe aforementioned animation paradigm indicates that when the `x` and `y` attributes of an element change, an animation will be executed.\n\n## Configure Animation\n\nIn G6, animation configuration is divided into global configuration and local configuration. Global configuration is mainly used to set whether animations are enabled globally, the duration of animations, and other parameters. Local configuration is primarily used to set the animation effects for elements.\n\n### Disabled Global Animation\n\nTo disable global animations, you can pass the `animation` option when instantiating the `Graph`:\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### Configure Global Animation\n\nIf you want to enable animations and also configure the default duration for the animations, you can pass the `animation` option:\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### Configure Element Animation\n\nFor individual elements, you can configure animations at different stages. For example, if you want an element to have a fade-in and fade-out effect when it enters and exits, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\nIf you want to update the position of an element with a translation transition, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\nIf you wish to disable animations for an element, you can configure it as follows:\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## Animation Paradigm\n\nThe animation configuration mentioned in the previous section actually used the built-in animation paradigm. This section introduces how to customize the animation paradigm.\n\n:::info{title=Tip}\nBefore writing an animation paradigm, it is necessary to understand the compositional structure of an element. For details, please refer to the [Element](/en/manual/element/overview) section.\n:::\n\nThe [Element](/en/manual/element/overview) section mentioned that elements in G6 are composed of one or more atomic graphics. Therefore, the animation of an element is essentially a combination of these atomic shape animations.\n\nThus, the animation paradigm is an array that describes the animation effects of each atomic shape within the element. For the element itself, it is also a special composite shape and thus has basic shape attributes such as `x`, `y`, etc.\n\nTherefore, you can directly write an animation paradigm for the element itself:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## Custom Animation\n\nIf the built-in animations do not meet your requirements, you can create custom animations. For details, please refer to [Custom Animation](/en/manual/animation/custom-animation).\n\n## Animation Priority\n\nAnimation priority refers to the precedence between global animation configuration and element-specific animation configuration. It can be summarized as follows:\n\n| Global Animation Config | Local Animation Config | Whether to Execute Animation                                                                     |\n| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------ |\n| ✅ true                 | ✅ true                | ✅ Execute animation with default configuration                                                  |\n| ✅ true                 | ❌ false               | ❌ Won't execute animation                                                                       |\n| ✅ true                 | ✅ Custom Animation    | ✅ Execute animation with local animation configuration                                          |\n| ❌ false                | ✅ true                | ❌ Won't execute animation                                                                       |\n| ❌ false                | ❌ false               | ❌ Won't execute animation                                                                       |\n| ❌ false                | ✅ Custom Animation    | ❌ Won't execute animation                                                                       |\n| ✅ Custom Animation     | ✅ true                | ✅ Execute animation with global animation configuration                                         |\n| ✅ Custom Animation     | ✅ Custom Animation    | ✅ Execute animation, local animation configuration overrides the global animation configuration |\n| ✅ Custom Animation     | ❌ false               | ❌ Won't execute animation                                                                       |\n\n## Persistent Animation\n\nIf you want elements to have persistent animations, such as the undulating effect of nodes or the ant line effect of edges, this can be achieved by customizing the elements. Below is an implementation of an edge with an Ant Line animation provided:\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\nThe `onCreate` is a lifecycle hook used to execute animations when an element is created.\n\nConfigure the edge style in the options as follows:\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\nThe `lineDash` is an array for `lineDashOffset`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\nThe `lineDashOffset` is the offset for `lineDash`, and the AntLine effect is achieved by continuously varying the `lineDashOffset`.\n\nSimilarly, you can also create a breathing effect for nodes:\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\nNode Style Configuration:\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n\n\n<!-- Skill/Rule: Animation Skill (packages/site/docs/manual/animation/animation.zh.md) -->\n---\ntitle: 动画总览\norder: 1\n---\n\n## 概述\n\n<image width=\"150px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*NkILT56xXp4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n动画是指元素在一段时间内的状态变化，例如节点的位置、大小、颜色等。在 G6 中，动画通常用于增强用户体验，提升图更新过程的连贯性和流畅度。\n\nG6 提供了一套动画范式来描述元素动画，并内置了一些常用的动画效果，用户可以通过配置动画参数来实现不同的动画效果。\n\n一个动画范式的实现如下：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n上述动画范式表示当元素的 `x` 和 `y` 属性发生变化时，会执行动画。\n\n## 配置动画\n\nG6 中动画配置分为全局配置和局部配置，全局配置主要用于配置全局是否开启动画、动画时长等参数，局部配置主要用于配置元素的动画效果。\n\n### 关闭全局动画\n\n若要关闭全局动画，可以在实例化 `Graph` 时传入 `animation` 配置项：\n\n```typescript\n{\n  animation: false,\n}\n```\n\n### 配置全局动画\n\n如果要启用动画且同时配置动画的默认播放时长，可以传入 `animation` 配置项：\n\n```typescript\n{\n  animation: {\n    duration: 500,\n  },\n}\n```\n\n### 配置元素动画\n\n对于单个元素，可以配置其在不同阶段的动画。例如希望元素在进场和退场时具有淡入淡出效果，可以以如下方式配置：\n\n```typescript\n{\n  node: {\n    animation: {\n      enter: 'fade',\n      exit: 'fade'\n    }\n  }\n}\n```\n\n如果希望更新元素位置时是以平移过渡的方式，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: {\n      update: 'translate',\n    }\n  }\n}\n```\n\n如果希望关闭元素的动画，可以配置如下：\n\n```typescript\n{\n  node: {\n    animation: false,\n  }\n}\n```\n\n## 动画范式\n\n上一节中提到的动画配置实际上使用了内置的动画范式，本节介绍如何自定义动画范式。\n\n:::info{title=提示}\n在编写动画范式之前需要了解元素的组成结构，具体请参考[元素](/manual/element/overview)一节\n:::\n\n[元素](/manual/element/overview)一节中提到：G6 中的元素是由一个或多个原子图形组合而成。因此元素的动画本质上是这些原子图形动画的组合。\n\n因此动画范式是一个数组，用于描述元素中各原子图形的动画效果。对于元素本身来说，其也是一个特殊的复合图形，因此具有基本的图形属性，如 `x`、`y` 等。\n\n因此可以直接为元素本身编写动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n];\n```\n\n## 自定义动画\n\n如果内置动画无法满足需求，可以自定义动画，具体请参考[自定义动画](/manual/animation/custom-animation)。\n\n## 动画优先级\n\n动画优先级是指全局动画配置和元素动画配置之前的优先级，可以归纳如下：\n\n| 全局动画配置 | 局部动画配置 | 是否执行动画                                      |\n| ------------ | ------------ | ------------------------------------------------- |\n| ✅ true      | ✅ true      | ✅ 执行动画，以默认动画配置执行                   |\n| ✅ true      | ❌ false     | ❌ 不执行该类元素动画                             |\n| ✅ true      | ✅ 配置动画  | ✅ 执行动画，以局部动画配置执行                   |\n| ❌ false     | ✅ true      | ❌ 不执行任何动画                                 |\n| ❌ false     | ❌ false     | ❌ 不执行任何动画                                 |\n| ❌ false     | ✅ 配置动画  | ❌ 不执行任何动画                                 |\n| ✅ 配置动画  | ✅ true      | ✅ 执行动画，以全局动画配置执行                   |\n| ✅ 配置动画  | ✅ 配置动画  | ✅ 执行动画，将局部动画配置覆盖全局动画配置后执行 |\n| ✅ 配置动画  | ❌ false     | ❌ 不执行该类元素动画                             |\n\n## 持续动画\n\n如果希望元素具有持续动画，例如节点的波动效果、边的蚂蚁线效果等，可以通过自定义元素方式实现，下面提供一个具有蚂蚁线(Ant Line)动画的边的实现：\n\n```typescript\nimport { Line } from '@antv/g6';\n\nclass AntLine extends Line {\n  onCreate() {\n    this.shapeMap.key.animate([{ lineDashOffset: -20 }, { lineDashOffset: 0 }], {\n      duration: 500,\n      iterations: Infinity,\n    });\n  }\n}\n```\n\n其中 `onCreate` 是一个生命周期钩子，用于在元素创建时执行动画。\n\n在 options 中配置边样式：\n\n```typescript\n{\n  edge: {\n    type: 'ant-line',\n    style:{\n      lineDash: [10, 10]\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/ant-line.md\"></embed>\n\n其中 `lineDash` 是 `lineDashOffset` 的数组，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {}\n}\n```\n\n其中 `lineDashOffset` 是 `lineDash` 的偏移量，通过不断变化 `lineDashOffset` 来实现飞线效果。\n\n同样的，还可以实现节点的呼吸效果：\n\n```typescript\nimport { Circle } from '@antv/g6';\n\nclass BreathingCircle extends Circle {\n  onCreate() {\n    this.shapeMap.halo.animate([{ lineWidth: 5 }, { lineWidth: 10 }], {\n      duration: 1000,\n      iterations: Infinity,\n      direction: 'alternate',\n    });\n  }\n}\n```\n\n节点样式配置：\n\n```typescript\n{\n  node: {\n    type: 'breathing-circle',\n    style: {\n      halo: true,\n      haloLineWidth: 5,\n    },\n  },\n}\n```\n\n<embed src=\"@/common/manual/core-concept/animation/breathing-circle.md\"></embed>\n\n\n<!-- Skill/Rule: Animation Skill (packages/site/docs/manual/animation/custom-animation.en.md) -->\n---\ntitle: Custom Animation\norder: 2\n---\n\n## Overview\n\n## Implement Animation\n\nFor circular node (Circle) elements, the main shape is a circle. Now, let's create an animation for it so that when the size of the node changes, it transitions with a scaling animation:\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nNow let's create a graph instance and update the element size to trigger the update animation:\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### Principle Analysis\n\nWhen animating an element, the element converts its animation frame parameters into animation frame parameters for its individual sub-graphics and executes the corresponding animations.\n\nIn the example above, by updating the node size, an animation was performed on the node, and its animation frame parameters were:\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\nAfter obtaining the attribute, the node element converts it into animation frame parameters for the main shape (circle):\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\nTherefore, what is ultimately happening here is that a transition animation is being performed on the circle, changing its radius from 10 to 20.\n\n#### Composite Animation\n\nBy directly combining the position change animation with the size change animation into a single animation paradigm, you can obtain a composite animation paradigm:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\nAnd update both the position and size of the node simultaneously:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\nAdd color transition:\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\nExecute node update:\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ Move the pointer to the graph below and click the play button on the left to replay\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n\n\n<!-- Skill/Rule: Animation Skill (packages/site/docs/manual/animation/custom-animation.zh.md) -->\n---\ntitle: 自定义动画\norder: 2\n---\n\n## 概述\n\n## 实现动画\n\n对于圆形节点（Circle）元素，其主图形是一个圆形，现在为其编写一个动画，当节点的尺寸发生变化时，能够以缩放的方式进行过渡动画：\n\n```typescript\n[\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n下面我们创建一个图实例并更新元素尺寸来触发更新动画：\n\n```typescript\nconst graph = new Graph({\n  container: 'container',\n  width: 50,\n  height: 50,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 25, y: 25, size: 20 } }],\n  },\n  node: {\n    animation: {\n      update: [{ fields: ['r'], shape: 'key' }],\n    },\n  },\n});\n\ngraph.draw().then(() => {\n  graph.updateNodeData([{ id: 'node-1', style: { size: 40 } }]);\n  graph.draw();\n});\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/implement-animation.md\"></embed>\n\n#### 原理分析\n\n当对一个元素执行动画时，该元素会将其动画帧参数转化为其各个子图形上的动画帧参数，并执行对应的动画。\n\n在上面的例子中，通过更新节点尺寸(size)，对该节点执行了动画，其动画帧参数为：\n\n```json\n[{ \"size\": 20 }, { \"size\": 40 }]\n```\n\n节点元素拿到该属性后，将其转化为主图形（圆形）的动画帧参数：\n\n```json\n[{ \"r\": 10 }, { \"r\": 20 }]\n```\n\n因此这里最终是对圆形执行了半径从 10 到 20 的过渡动画。\n\n#### 复合动画\n\n直接将位置变化动画和尺寸变化动画合并到一个动画范式即可得到复合动画范式：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r'],\n    shape: 'key',\n  },\n];\n```\n\n并同时更新该节点的位置和尺寸：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40 } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-1.md\"></embed>\n\n加入颜色过渡：\n\n```typescript\n[\n  {\n    fields: ['x', 'y'],\n  },\n  {\n    fields: ['r', 'fill'],\n    shape: 'key',\n  },\n];\n```\n\n执行节点更新：\n\n```typescript\ngraph.updateNodeData([{ id: 'node-1', style: { x: 175, size: 40, fill: 'pink' } }]);\ngraph.draw();\n```\n\n> ⬇️ 指针移动至下方图中，并点击左侧播放按钮进行重新播放\n\n<embed src=\"@/common/manual/custom-extension/animation/composite-animation-2.md\"></embed>\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/AutoAdaptLabel.en.md) -->\n---\ntitle: AutoAdaptLabel\norder: 1\n---\n\n## Overview\n\nAuto-adapt label display is a dynamic label management strategy designed to intelligently adjust which labels should be displayed or hidden based on factors such as spatial allocation of the current visible range and node importance. By analyzing the visible area in real-time, it ensures that users receive the most relevant and clear information display in different interaction scenarios, while avoiding visual overload and information redundancy.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Node size changes\n- Graph scaling\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // Throttle time\n      padding: 10, // Extra spacing when detecting overlap\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                      | Type                                                                                                                              | Default            | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- |\n| type      | Interaction type name                                                                                                                                                                                                                                                                            | string                                                                                                                            | `auto-adapt-label` | √        |\n| enable    | Whether to enable this interaction                                                                                                                                                                                                                                                               | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                                                   | true               |          |\n| throttle  | Label update throttle time (ms)                                                                                                                                                                                                                                                                  | number                                                                                                                            | 100                |          |\n| padding   | Extra spacing when detecting label overlap                                                                                                                                                                                                                                                       | number \\| number[]                                                                                                                | 0                  |          |\n| sort      | Custom sorting function, sorting elements from high to low importance, with higher importance elements having higher label display priority. Generally, combo > node > edge                                                                                                                      | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                |                    |          |\n| sortNode  | Sort nodes from high to low importance, with higher importance nodes having higher label display priority. Several built-in [centrality algorithms](#nodecentralityoptions) are available, or a custom sorting function can be used. Note that if `sort` is set, `sortNode` will not take effect | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/en/manual/data#nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |          |\n| sortEdge  | Sort edges from high to low importance, with higher importance edges having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortEdge` will not take effect                                                                  | (edgeA: [EdgeData](/en/manual/data#edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                    |                    |          |\n| sortCombo | Sort groups from high to low importance, with higher importance groups having higher label display priority. By default, it is sorted according to the order of data. Note that if `sort` is set, `sortCombo` will not take effect                                                               | (comboA: [ComboData](/en/manual/data#combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |          |\n\n### NodeCentralityOptions\n\nMethods for measuring node centrality\n\n- `'degree'`: Degree centrality, measured by the degree of the node (number of connected edges). Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measured by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measured by the reciprocal of the sum of the shortest path lengths from the node to all other nodes. Nodes with high closeness centrality can usually reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measured by the degree of connection of the node to other central nodes. Nodes with high eigenvector centrality are usually connected to other important nodes\n- `'pagerank'`: PageRank centrality, measured by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to webpage ranking algorithms\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/AutoAdaptLabel.zh.md) -->\n---\ntitle: 标签自适应显示 AutoAdaptLabel\norder: 1\n---\n\n## 概述\n\n标签自适应显示是一种动态标签管理策略，旨在根据当前可视范围的空间分配、节点重要性等因素，智能调整哪些标签应显示或隐藏。通过对可视区域的实时分析，确保用户在不同的交互场景下获得最相关最清晰的信息展示，同时避免视觉过载和信息冗余。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 节点尺寸变化\n- 图形缩放\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/auto-adapt-label.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['auto-adapt-label'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'auto-adapt-label',\n      throttle: 200, // 节流时间\n      padding: 10, // 检测重叠时的额外间距\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                        | 类型                                                                                                                                   | 默认值             | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ---- |\n| type      | 交互类型名称                                                                                                                                                                                | string                                                                                                                                 | `auto-adapt-label` | √    |\n| enable    | 是否启用该交互                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                                      | true               |      |\n| throttle  | 标签更新节流时间（ms）                                                                                                                                                                      | number                                                                                                                                 | 100                |      |\n| padding   | 标签检测重叠时的额外间距                                                                                                                                                                    | number \\| number[]                                                                                                                     | 0                  |      |\n| sort      | 自定义排序函数，根据元素的重要性从高到低排序，重要性越高的元素其标签显示优先级越高。一般情况下 combo > node > edge                                                                          | (a: ElementDatum, b: ElementDatum) => -1 \\| 0 \\| 1                                                                                     |                    |      |\n| sortNode  | 根据节点的重要性从高到低排序，重要性越高的节点其标签显示优先级越高。内置几种[中心性算法](#nodecentralityoptions)，也可以自定义排序函数。需要注意，如果设置了 `sort`，则 `sortNode` 不会生效 | [NodeCentralityOptions](#nodecentralityoptions) \\| (nodeA: [NodeData](/manual/data#节点数据nodedata), nodeB: NodeData => -1 \\| 0 \\| 1) | `type: 'degree'`   |      |\n| sortEdge  | 根据边的重要性从高到低排序，重要性越高的边其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortEdge` 不会生效                                               | (edgeA: [EdgeData](/manual/data#边数据edgedata), edgeB: EdgeData) => -1 \\| 0 \\| 1                                                      |                    |      |\n| sortCombo | 根据群组的重要性从高到低排序，重要性越高的群组其标签显示优先级越高。默认按照数据先后进行排序。需要注意，如果设置了 `sort`，则 `sortCombo` 不会生效                                          | (comboA: [ComboData](/manual/data#组合数据combodata), comboB: ComboData) => -1 \\| 0 \\| 1                                               |                    |      |\n\n### NodeCentralityOptions\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 200, y: 100, labelText: '短标签' } },\n    { id: 'node2', style: { x: 360, y: 100, labelText: '中等长度的标签' } },\n    { id: 'node3', style: { x: 280, y: 220, labelText: '这是一个非常非常长的标签，需要自适应显示' } },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node3' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'auto-adapt-label',\n      type: 'auto-adapt-label',\n      padding: 0,\n      throttle: 200,\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/BrushSelect.en.md) -->\n---\ntitle: BrushSelect\norder: 2\n---\n\n## Overview\n\nBrush select allows users to click and drag a box to enclose elements, selecting the elements within the box.\n\n## Usage Scenarios\n\nThis interaction is mainly used for:\n\n- Quickly selecting a batch of elements\n- Quickly deselecting a batch of elements\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | Type                                                                             | Default                   | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | -------- |\n| type           | Interaction type name. This plugin is built-in, and you can use it with `type: 'brush-select'`.                                                                                                                                                                                                                                                                                                                                                                                                                              | `brush-select` \\| string                                                         | `brush-select`            | ✓        |\n| animation      | Whether to enable animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | boolean                                                                          | false                     |          |\n| enable         | Whether to enable brush select functionality                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)  | true                      |          |\n| enableElements | Types of elements that can be selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |          |\n| immediately    | Whether to select immediately, only effective when [selection mode](#mode) is `default`, [example](#immediately)                                                                                                                                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |          |\n| mode           | Selection mode, [example](#mode)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |          |\n| onSelect       | Callback for selected element state                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |          |\n| state          | Switch to this state when selected                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |          |\n| style          | Specify the style of the selection box, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                  | See below                 |          |\n| trigger        | Press this shortcut key in combination with a mouse click to perform selection **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means selection can be performed with a mouse click without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Elements are immediately selected as the box encloses them\n      trigger: [], // No need to press other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nFour selection modes are built-in:\n\n- `union`: Retain the current state of selected elements and add the specified state.\n- `intersect`: If the selected elements already have the specified state, retain it; otherwise, clear the state.\n- `diff`: Invert the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Attribute         | Description               | Type                                     | Default   |\n| ----------------- | ------------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style               | string                                   |           |\n| fill              | Fill color                | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity              | number \\| string                         | 0.1       |\n| isBillboard       | Enable billboard mode     | boolean                                  |           |\n| isSizeAttenuation | Enable size attenuation   | boolean                                  |           |\n| lineCap           | Line end style            | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash configuration        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash offset               | number                                   |           |\n| lineJoin          | Line join style           | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width                | number \\| string                         | 1         |\n| opacity           | Overall opacity           | number \\| string                         |           |\n| radius            | Rectangle corner radius   | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur degree        | number                                   |           |\n| shadowColor       | Shadow color              | string                                   |           |\n| shadowOffsetX     | Shadow X direction offset | number                                   |           |\n| shadowOffsetY     | Shadow Y direction offset | number                                   |           |\n| stroke            | Stroke color              | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity            | number \\| string                         |           |\n| visibility        | Visibility                | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level           | number                                   | 2         |\n\n**Example**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/BrushSelect.zh.md) -->\n---\ntitle: 框选 BrushSelect\norder: 2\n---\n\n## 概述\n\n鼠标点击拖一个框笼罩元素，框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素\n- 快速取消选中一批元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/brush-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['brush-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select-1',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                                                                                                                                                                                                                                                                                                                                            | 类型                                                                             | 默认值                    | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------------------- | ---- |\n| type           | 交互类型名称。此插件已内置，你可以通过 `type: 'brush-select'` 来使用它。                                                                                                                                                                                                                                                                                                        | `brush-select` \\| string                                                         | `brush-select`            | ✓    |\n| animation      | 是否启用动画                                                                                                                                                                                                                                                                                                                                                                    | boolean                                                                          | false                     |      |\n| enable         | 是否启用框选功能                                                                                                                                                                                                                                                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                | true                      |      |\n| enableElements | 可框选的元素类型                                                                                                                                                                                                                                                                                                                                                                | ( `node` \\| `edge` \\| `combo` )[]                                                | [`node`, `combo`, `edge`] |      |\n| immediately    | 是否及时框选, 仅在 [框选模式 mode](#mode) 为 `default` 时生效，[示例](#immediately)                                                                                                                                                                                                                                                                                             | boolean                                                                          | false                     |      |\n| mode           | 框选的选择模式，[示例](#mode)                                                                                                                                                                                                                                                                                                                                                   | `union` \\| `intersect` \\| `diff` \\| `default`                                    | `default`                 |      |\n| onSelect       | 框选元素状态回调                                                                                                                                                                                                                                                                                                                                                                | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]> |                           |      |\n| state          | 被选中时切换到该状态                                                                                                                                                                                                                                                                                                                                                            | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`      | `selected`                |      |\n| style          | 指定框选时的框样式，[配置项](#style)                                                                                                                                                                                                                                                                                                                                            |                                                                                  | 见下文                    |      |\n| trigger        | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                         | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n内置支持四种框选的选择模式：\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'brush-select',\n        key: 'brush-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'brush-select',\n      type: 'brush-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('BrushSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'brush-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'brush-select',\n      key: 'brush-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'brush-select',\n      type: 'brush-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ClickSelect.en.md) -->\n---\ntitle: ClickSelect\norder: 3\n---\n\n## Overview\n\nWhen an element is clicked, it will be highlighted.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Focusing on elements\n- Viewing element details\n- Viewing element relationships\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['click-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // Selection spread range\n      state: 'active', // Selected state\n      neighborState: 'neighborActive', // Neighbor node attached state\n      unselectedState: 'inactive', // Unselected node state\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option          | Description                                                                                                                                                                                                                                                        | Type                                                                            | Default        | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- | -------------- | -------- |\n| type            | Behavior type name. This behavior is built-in, and you can use it with `type: 'click-select'`.                                                                                                                                                                     | `click-select` \\| string                                                        | `click-select` | ✓        |\n| animation       | Whether to enable animation effects when switching element states                                                                                                                                                                                                  | boolean                                                                         | true           |          |\n| degree          | Controls the highlight spread range, [example](#degree)                                                                                                                                                                                                            | number \\| (event:[Event](/en/api/event#event-object-properties)) => number      | 0              |          |\n| enable          | Whether to enable the click element function, supports dynamic control through functions, [example](#enable)                                                                                                                                                       | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean) | true           |          |\n| multiple        | Whether to allow multiple selections                                                                                                                                                                                                                               | boolean                                                                         | false          |          |\n| state           | The state applied when an element is selected                                                                                                                                                                                                                      | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| neighborState   | The state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements, [example](#neighborstate)                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        | `selected`     |          |\n| unselectedState | The state applied to all other elements except the selected element and its affected neighbor elements when an element is selected, [example](#unselectedState)                                                                                                    | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight`        |                |          |\n| onClick         | Callback when an element is clicked                                                                                                                                                                                                                                | (event: [Event](/en/api/event#event-object-properties)) => void                 |                |          |\n| trigger         | Press this shortcut key in combination with a mouse click to perform multi-selection, key reference: _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                        | `['shift']`    |          |\n\n### degree\n\nControls the highlight spread range\n\n- For nodes, `0` means only the current node is selected, `1` means the current node and its directly adjacent nodes and edges are selected, and so on.\n- For edges, `0` means only the current edge is selected, `1` means the current edge and its directly adjacent nodes are selected, and so on.\n\n> In the following example, when `degree: 0` only the <span style='color:#E4504D'>red</span> point is highlighted;\n> When `degree: 1` the <span style='color:#E4504D'>red</span> and <span style='color:#FFC40C'>orange</span> points are highlighted.\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\nWhether to enable the click element function\n\nIt can be dynamically controlled through functions, for example, only enabled when a node is selected.\n\n```js\n{\n  //⚠️ Note, you need to set both the node and the canvas, otherwise the user will not listen to the event when clicking the canvas\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\nSimilarly, if you only want edges to be selected:\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\nThe state applied to elements with n-degree relationships when an element is selected. The value of n is controlled by the degree attribute, for example, degree 1 means directly adjacent elements\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // State attached to the directly clicked node\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\nWhen an element is selected, the state applied to all other elements except the selected element and the spread neighbor elements.\n\nBuilt-in states: `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Example\n\n### Click to select nodes and their directly connected nodes\n\n**Clicking a node** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#0f0'>active</span>\n<br>\n**Adjacent nodes** will switch from <span style='color:#E4504D'>default state</span> to <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // Selected node state\n      active: {\n        fill: '#0f0',\n      },\n      // Adjacent node state\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // State attached to adjacent nodes\n      neighborState: 'neighborActive',\n      // Unselected node state\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ClickSelect.zh.md) -->\n---\ntitle: 点击选中 ClickSelect\norder: 3\n---\n\n## 概述\n\n当鼠标点击元素时，会使元素高亮。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 聚焦元素\n- 查看元素详情\n- 查看元素关系\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['click-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'click-select',\n      key: 'click-select-1',\n      degree: 2, // 选中扩散范围\n      state: 'active', // 选中的状态\n      neighborState: 'neighborActive', // 相邻节点附着状态\n      unselectedState: 'inactive', // 未选中节点状态\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项          | 说明                                                                                                                                                                                                       | 类型                                                                     | 默认值         | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -------------- | ---- |\n| type            | 交互类型名称。此交互已内置，你可以通过 `type: 'click-select'` 来使用它。                                                                                                                                   | `click-select` \\| string                                                 | `click-select` | ✓    |\n| animation       | 是否在元素状态切换时启用动画效果                                                                                                                                                                           | boolean                                                                  | true           |      |\n| degree          | 控制了高亮扩散范围，[示例](#degree)                                                                                                                                                                        | number \\| (event:[Event](/api/event#事件对象属性)) => number             | 0              |      |\n| enable          | 是否启用点击元素的功能，支持通过函数的方式动态控制是否启用，[示例](#enable)                                                                                                                                | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)        | true           |      |\n| multiple        | 是否允许多选                                                                                                                                                                                               | boolean                                                                  | false          |      |\n| state           | 当元素被选中时应用的状态                                                                                                                                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| neighborState   | 当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素，[示例](#neighborstate)                                                                   | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` | `selected`     |      |\n| unselectedState | 当有元素被选中时，除了选中元素及其受影响的邻居元素外，其他所有元素应用的状态，[示例](#unselectedState)                                                                                                     | string \\| `selected` \\| `active`\\| `inactive`\\| `disabled`\\| `highlight` |                |      |\n| onClick         | 点击元素时的回调                                                                                                                                                                                           | (event: [Event](/api/event#事件对象属性)) => void                        |                |      |\n| trigger         | 按下该快捷键配合鼠标点击进行多选，按键参考： _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                 | `['shift']`    |      |\n\n### degree\n\n控制了高亮扩散范围\n\n- 对于节点来说，`0` 表示只选中当前节点，`1` 表示选中当前节点及其直接相邻的节点和边，以此类推。\n- 对于边来说，`0` 表示只选中当前边，`1` 表示选中当前边及其直接相邻的节点，以此类推。\n\n> 如下示例，当 `degree: 0` 仅高亮<span style='color:#E4504D'>红色</span>点;\n> 当 `degree: 1` 高亮<span style='color:#E4504D'>红色</span>和<span style='color:#FFC40C'>橙色</span>点。\n\n<embed src=\"@/common/api/behaviors/click-element.md\"></embed>\n\n### enable\n\n是否启用点击元素的功能\n\n可以通过函数的方式动态控制是否启用，例如只有节点被选中时才启用。\n\n```js\n{\n  //⚠️ 注意，这里需要同时设置节点和画布，否则用户点击画布时将不会监听到事件\n  enable: (event) => ['node', 'canvas'].includes(event.targetType);\n}\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 60 } },\n      { id: 'node2', style: { x: 200, y: 60 } },\n      { id: 'node3', style: { x: 300, y: 60 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      enable: (event) => ['node', 'canvas'].includes(event.targetType),\n    },\n  ],\n});\n\ngraph.render();\n```\n\n同理，如果只希望边能被选中：\n\n```js\n{\n  enable: (event) => ['edge', 'canvas'].includes(event.targetType);\n}\n```\n\n### neighborState\n\n当有元素选中时，其相邻 n 度关系的元素应用的状态。n 的值由属性 degree 控制，例如 degree 为 1 时表示直接相邻的元素\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      // 被直接点击的节点附着的状态\n      state: 'active',\n      // 相邻的节点附着的状态\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n        halo: true,\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### unselectedState\n\n当有元素被选中时，除了被选中元素和扩散的邻居元素外，其他所有元素应用的状态。\n\n内置状态： `selected` `active` `inactive` `disabled` `highlight`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 示例\n\n### 点击选中节点及其直接相连的节点\n\n**点击节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#0f0'>active</span>\n<br>\n**相邻节点** 会从 <span style='color:#E4504D'>默认状态</span> 切换为 <span style='color:#FFC40C'>neighborActive</span>\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      // 选中节点状态\n      active: {\n        fill: '#0f0',\n      },\n      // 相邻节点状态\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      // 相邻节点附着状态\n      neighborState: 'neighborActive',\n      // 未选中节点状态\n      unselectedState: 'inactive',\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0f0',\n      },\n      neighborActive: {\n        fill: '#FFC40C',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      neighborState: 'neighborActive',\n      unselectedState: 'inactive',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#E4504D',\n    },\n    state: {\n      active: {\n        fill: '#0b0',\n      },\n    },\n  },\n  behaviors: [\n    {\n      type: 'click-select',\n      degree: 1,\n      state: 'active',\n      unselectedState: 'inactive',\n      multiple: true,\n      trigger: ['shift'],\n    },\n    'drag-element',\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/CollapseExpand.en.md) -->\n---\ntitle: CollapseExpand\norder: 4\n---\n\n## Overview\n\nCollapseExpand is a built-in behavior in G6 used to implement the expand/collapse functionality for nodes or combos. Through double-click (default) or single-click actions, users can flexibly control the expand and collapse states of graph elements, effectively managing the visualization hierarchy of the graph structure and reducing visual complexity.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Managing large hierarchical graphs, enabling layered browsing of tree or network graphs\n- Simplifying the display of complex graphs, expanding areas of interest as needed\n- Hiding branch nodes that are temporarily not needed, focusing on important information\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates to the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // Change the trigger method to single-click\n      animation: true, // Enable animation effects\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                         | Type                                                                     | Default Value     | Required |\n| ---------- | --------------------------------------------------- | ------------------------------------------------------------------------ | ----------------- | -------- |\n| type       | Behavior type name                                  | `collapse-expand` \\| string                                              | `collapse-expand` | ✓        |\n| animation  | Enable expand/collapse animation effects            | boolean                                                                  | true              |          |\n| enable     | Enable expand/collapse functionality                | boolean \\| ((event: [/en/api/event#event-object-properties]) => boolean) | true              |          |\n| trigger    | Trigger method, can be single-click or double-click | `click` \\| `dblclick`                                                    | `dblclick`        |          |\n| onCollapse | Callback function when collapse is completed        | (id: string) => void                                                     | -                 |          |\n| onExpand   | Callback function when expand is completed          | (id: string) => void                                                     | -                 |          |\n| align      | Align with the target element to avoid view offset  | boolean                                                                  | true              |          |\n\n## Code Examples\n\n### Basic Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // other configurations...\n});\n```\n\n### Use Single-Click to Trigger Expand/Collapse\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // Change the default double-click trigger to single-click\n    },\n  ],\n});\n```\n\n### Custom Expand/Collapse Callback\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`Node ${id} has collapsed`);\n        // Execute custom logic\n      },\n      onExpand: (id) => {\n        console.log(`Node ${id} has expanded`);\n        // Execute custom logic\n      },\n    },\n  ],\n});\n```\n\n### Conditional Enablement of Expand/Collapse Functionality\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // Enable expand/collapse functionality only when the target is a node type\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Disable Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // other configurations...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // Disable expand/collapse animation effects\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. How to determine if a node is collapsed?\n\nYou can check the `collapsed` property in the node data:\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. How to programmatically expand or collapse a node?\n\nIn addition to being triggered by user interaction, you can also directly control using [collapseElement](/en/api/element#graphcollapseelementid-options) or [expandElement](/en/api/element#graphexpandelementid-options):\n\n```javascript\n// Collapse node\ngraph.collapseElement('nodeId', { animation: true });\n\n// Expand node\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/CollapseExpand.zh.md) -->\n---\ntitle: 展开/收起元素 CollapseExpand\norder: 4\n---\n\n## 概述\n\nCollapseExpand 是 G6 中用于实现节点或组合（Combo）展开/收起功能的内置交互。通过双击（默认）或单击操作，用户可以灵活控制图元素的展开与收起状态，有效管理图结构的可视化层次，降低视觉复杂度。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 管理大型层次结构图，实现树状图或网络图的分层浏览\n- 简化复杂图的展示，按需展开关注区域\n- 隐藏暂时不需要查看的分支节点，聚焦于重要信息\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/collapse-expand.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一 behavior：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['collapse-expand'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      key: 'collapse-expand-1',\n      trigger: 'click', // 修改触发方式为单击\n      animation: true, // 启用动画效果\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                           | 类型                                                                      | 默认值            | 必选 |\n| ---------- | ------------------------------ | ------------------------------------------------------------------------- | ----------------- | ---- |\n| type       | 交互类型名称                   | `collapse-expand` \\| string                                               | `collapse-expand` | ✓    |\n| animation  | 是否启用展开/收起动画效果      | boolean                                                                   | true              |      |\n| enable     | 是否启用展开/收起功能          | boolean \\| ((event: [IPointerEvent](/api/event#事件对象属性)) => boolean) | true              |      |\n| trigger    | 触发方式，可选单击或双击       | `click` \\| `dblclick`                                                     | `dblclick`        |      |\n| onCollapse | 完成收起时的回调函数           | (id: string) => void                                                      | -                 |      |\n| onExpand   | 完成展开时的回调函数           | (id: string) => void                                                      | -                 |      |\n| align      | 是否对准目标元素，避免视图偏移 | boolean                                                                   | true              |      |\n\n## 代码示例\n\n### 基础展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['collapse-expand'],\n  // 其他配置...\n});\n```\n\n### 使用单击触发展开/收起\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'click', // 将默认的双击触发改为单击触发\n    },\n  ],\n});\n```\n\n### 自定义展开/收起回调\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      onCollapse: (id) => {\n        console.log(`节点 ${id} 已收起`);\n        // 执行自定义逻辑\n      },\n      onExpand: (id) => {\n        console.log(`节点 ${id} 已展开`);\n        // 执行自定义逻辑\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用展开/收起功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      // 只有当目标是节点类型时才启用展开/收起功能\n      enable: (event) => event.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 关闭动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      animation: false, // 关闭展开/收起动画效果\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 如何判断一个节点是否处于收起状态？\n\n可以通过检查节点数据中的 `collapsed` 属性：\n\n```javascript\nconst isCollapsed = (nodeId) => {\n  const nodeData = graph.getNodeData(nodeId);\n  return nodeData?.style?.collapsed === true;\n};\n```\n\n### 2. 如何以编程方式展开或收起节点？\n\n除了通过用户交互触发，你还可以使用 [collapseElement](/api/element#graphcollapseelementid-options) 或 [expandElement](/api/element#graphexpandelementid-options) 直接控制：\n\n```javascript\n// 收起节点\ngraph.collapseElement('nodeId', { animation: true });\n\n// 展开节点\ngraph.expandElement('nodeId', { animation: true });\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 300, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 300, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 100, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 50, y: 150 } },\n      { id: 'node5', combo: 'combo2', style: { x: 150, y: 150 } },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node3', target: 'node5' },\n    ],\n    combos: [\n      { id: 'combo1', style: { labelText: '双击折叠', collapsed: true } },\n      { id: 'combo2', style: { labelText: '单击折叠', collapsed: false } },\n    ],\n  },\n  behaviors: [\n    {\n      type: 'collapse-expand',\n      trigger: 'dblclick',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo1',\n    },\n    {\n      type: 'collapse-expand',\n      trigger: 'click',\n      enable: (event) => event.targetType === 'combo' && event.target.id === 'combo2',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/CreateEdge.en.md) -->\n---\ntitle: CreateEdge\norder: 5\n---\n\n## Overview\n\nCreateEdge is a built-in behavior in G6 for interactively creating edges on the canvas. After the user triggers the behavior (click or drag), the edge will follow the mouse movement and connect to the target node to complete the creation. If canceled, it will be automatically removed.\n\nAdditionally, this behavior supports customizing the style of the edge, such as color, line style, arrow, etc., to meet different visualization needs.\n\nThe elements that can be connected by this behavior are `node` and `combo`.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Visualization scenarios that require interactive creation of connections between nodes, such as flowcharts, knowledge graphs, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration\n\n```javascript\n// Use default configuration\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['create-edge'], // Directly add, use default configuration\n});\n\n// Or use custom configuration\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // Behavior configuration, create edge by clicking\n      style: {}, // Custom edge style\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                 | Type                                                                                                     | Default       | Required |\n| -------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type     | Behavior type name                                                                                          | string                                                                                                   | `create-edge` | √        |\n| trigger  | The way to trigger the creation of a new edge: `click` means click to trigger; `drag` means drag to trigger | `click` \\| `drag`                                                                                        | `drag`        |          |\n| enable   | Whether to enable this behavior                                                                             | boolean \\| ((event: [Event](/en/api/event#event-object-properties)) => boolean)                          | true          |          |\n| onCreate | Callback function for creating an edge, returns edge data                                                   | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => [EdgeData](/en/manual/data#edge-data-edgedata) | -             |          |\n| onFinish | Callback function for successfully creating an edge                                                         | (edge: [EdgeData](/en/manual/data#edge-data-edgedata)) => void                                           | -             |          |\n| style    | Style of the newly created edge, [configuration options](#style)                                            | See below                                                                                                | -             |          |\n\n### style\n\nConfigure the style of the newly created edge, for detailed configuration options, please refer to [Element - Edge - General Edge Properties - Style](/en/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## Code Examples\n\n### Basic Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### Custom Edge Creation Function\n\n```javascript\nconst graph = new Graph({\n  // Other configurations,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: 'red',\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### Create Edge by Clicking\n\n```javascript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/CreateEdge.zh.md) -->\n---\ntitle: 创建边 CreateEdge\norder: 5\n---\n\n## 概述\n\nCreateEdge 是 G6 中用于实现画布中交互式创建边（Edge）的内置交互。用户触发交互（点击或拖拽）后，边会随鼠标移动，连接到目标节点即完成创建，若取消则自动移除。\n\n此外，该交互支持自定义边的样式，如颜色、线条样式、箭头等，以适应不同的可视化需求。\n\n该交互支持连接的元素为 `node` 和 `combo`。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要交互式创建节点间连接关系的可视化场景，如流程图、知识图谱等\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/create-edge.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n```javascript\n// 使用默认配置\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['create-edge'], // 直接添加，使用默认配置\n});\n\n// 或使用自定义配置\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click', // 交互配置，通过点击创建边\n      style: {}, // 边自定义样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                        | 类型                                                                                       | 默认值        | 必选 |\n| -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------- | ---- |\n| type     | 交互类型名称                                                | string                                                                                     | `create-edge` | √    |\n| trigger  | 触发新建边的方式：`click` 表示点击触发；`drag` 表示拖拽触发 | `click` \\| `drag`                                                                          | `drag`        |      |\n| enable   | 是否启用该交互                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                          | true          |      |\n| onCreate | 创建边回调函数，返回边数据                                  | (edge: [EdgeData](/manual/data#边数据edgedata)) => [EdgeData](/manual/data#边数据edgedata) | -             |      |\n| onFinish | 成功创建边回调函数                                          | (edge: [EdgeData](/manual/data#边数据edgedata)) => void                                    | -             |      |\n| style    | 新建边的样式，[配置项](#style)                              | 见下面                                                                                     | -             |      |\n\n### style\n\n配置新创建边的样式，详细配置项请参考 [元素 - 边 - 通用边属性 - 样式](/manual/element/edge/base-edge#style)\n\n```json\n{\n  \"style\": {\n    \"stroke\": \"red\",\n    \"lineWidth\": 2\n  }\n}\n```\n\n## 代码示例\n\n### 基础创建边功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['create-edge'],\n});\n```\n\n### 自定义创建边功能\n\n```javascript\nconst graph = new Graph({\n  // 其他配置,\n  behaviors: [\n    {\n      type: 'create-edge',\n      style: {\n        stroke: red,\n        lineWidth: 3,\n      },\n    },\n  ],\n});\n```\n\n### 使用点击创建边\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'click',\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: [\n    {\n      type: 'create-edge',\n      trigger: 'drag',\n      style: {\n        fill: 'red',\n        lineWidth: 2,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/custom-behavior.en.md) -->\n---\ntitle: Custom Behavior\norder: 16\n---\n\n## Overview\n\nCustom behavior allows users to define one or more related interaction behaviors as a complete interaction based on the comprehensive [event mechanism](/en/api/event) provided by G6, thereby achieving interaction logic that fits business scenarios.\n\n### Execution Logic of Behavior\n\nTypically:\n\n1. Listen for user interaction events\n\n2. Update the canvas or perform other operations based on the events\n\nFor example, the `DragCanvas` behavior listens for pointer drag events and updates the camera position based on the drag distance.\n\n### Difference Between Behavior and Plugin\n\n- Both behavior and plugin base classes are derived from the [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) base class within G6, so the implementation methods for behavior and plugin are basically the same.\n- However, based on the concept of visualization, behavior is usually used to handle user interaction events, while plugins are usually used to handle canvas rendering logic, additional component rendering, etc.\n\n:::info{title=Tip}\nDue to conceptual distinctions, behavior instances cannot be obtained, while plugin instances can be obtained ([getPluginInstance](/en/api/plugin#graphgetplugininstancekey)).\n:::\n\n## When to Use Custom Behavior?\n\n- **Purpose**:\n\n  When users need to implement interaction logic that fits business scenarios, we usually need to cooperate with G6's event system to respond to related events and execute the required interaction logic.\n\n- **Without Custom Behavior**:\n\n  If custom behavior is not used, users need to perform a series of event listening and response processing through `graph.on` after creating a Graph instance, making code logic processing and orchestration extremely difficult.\n\n- **Advantages of Behavior**:\n\n  Each behavior is an independent code module, and the existence of the behavior system facilitates users to decouple business logic, avoid code bloat, and facilitate subsequent maintenance.\n\n- **Conclusion**:\n\n  > 1. When users need to implement any interaction logic, they should first consider custom behavior.\n  > 2. When built-in behavior cannot fully meet business needs, users can also adjust and modify through custom behavior (inheriting built-in behavior).\n  >\n  > _(If the features supported by built-in behavior are more general, or if there are bugs in built-in behavior, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Implementing Behavior\n\nThe implementation of a behavior is quite flexible, and you can implement your behavior in your preferred style.\n\nBelow is a simple custom behavior implementation. When the user clicks on the canvas, a node is added to the canvas (the fill color of the added node can be defined through behavior configuration):\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // Unbind events when destroyed\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In the example code, we implemented a `ClickAddNode` behavior, which adds an event listener to the Graph in the constructor. When the user clicks on the canvas, a node is added at the click position, and the fill color of the added node can be configured.\n- `BaseBehavior` is the base class for all behaviors, and each custom behavior needs to inherit this base class.\n\n> Click on the blank area of the canvas below to add a node, and switch the right panel to configure the node color.\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=Tip}\nThe above example is the simplest behavior implementation. In actual development, you may also need to handle logic such as enabling and disabling behaviors.\n\nIn addition, there may be event conflicts between multiple behaviors, and you need to handle these conflicts carefully.\n:::\n\n## Registering Behavior\n\nRegister through the register method provided by G6\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## Configuring Behavior\n\nYou can pass in the behavior type name or configuration parameter object in `behaviors`, such as the above ClickAddNode. See [Configuring Behavior](/en/manual/behavior/overview#配置和使用) for details.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/custom-behavior.zh.md) -->\n---\ntitle: 自定义交互\norder: 16\n---\n\n## 概述\n\n自定义交互允许用户基于 G6 提供的完善的[事件机制](/api/event)，把一个或多个相关的交互行为定义为一个完整的交互，以此实现符合业务场景的交互逻辑。\n\n### 交互的执行逻辑\n\n通常为：\n\n1. 监听用户交互事件\n\n2. 根据事件更新画布或执行其他操作\n\n例如 `DragCanvas` 交互监听指针拖拽事件，根据拖拽的距离更新相机的位置。\n\n### 交互与插件的区别\n\n- 交互和插件的基类都是由 G6 内部的 [BaseExtension](https://github.com/antvis/G6/blob/v5/packages/g6/src/registry/extension/index.ts) 基类派生而来，因此交互和插件的实现方式基本相同\n- 但基于可视化的概念区分，交互通常用于处理用户交互事件，而插件通常用于处理画布的渲染逻辑、额外组件渲染等\n\n:::info{title=提示}\n因概念上的区分，交互实例不可获取，插件实例可获取（ [getPluginInstance](/api/plugin#graphgetplugininstancekey) ）\n:::\n\n## 什么时候需要自定义交互？\n\n- **目的**：\n\n  当用户在实现符合业务场景的交互逻辑时，我们通常需要配合 G6 的事件系统，对相关事件作出响应，执行需要的交互逻辑。\n\n- **不使用自定义交互**：\n\n  如果不使用自定义交互，用户需要在创建 Graph 实例后，通过 `graph.on` 进行一系列的事件监听和响应处理，代码逻辑处理和编排会显得异常艰难。\n\n- **交互的优势**：\n\n  每个交互行为都是独立的代码模块，交互系统的存在方便用户解耦业务逻辑、避免代码臃肿以及方便用户后续维护等。\n\n- **结论**：\n\n  > 1、当用户需要实现任何交互逻辑时，应当首先考虑自定义交互。\n  >\n  > 2、当内置交互无法完全满足业务需求时，用户也可以通过自定义交互（继承内置交互）进行调整和修改。\n  >\n  > _（如果需要内置交互支持的特性是较通用的，或者内置交互存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 实现交互\n\n一个交互的实现相当灵活，你可以以你喜欢的风格实现你的交互。\n\n下面是一个简单的自定义交互实现，当用户点击画布时，会在画布上添加一个节点（可通过交互配置定义所添加节点的填充颜色）：\n\n```typescript\nimport type { BaseBehaviorOptions, RuntimeContext, IPointerEvent } from '@antv/g6';\nimport { BaseBehavior, CanvasEvent } from '@antv/g6';\n\ninterface ClickAddNodeOptions extends BaseBehaviorOptions {\n  fill: string;\n}\n\nexport class ClickAddNode extends BaseBehavior<ClickAddNodeOptions> {\n  static defaultOptions: Partial<ClickAddNodeOptions> = {\n    fill: 'red',\n  };\n  constructor(context: RuntimeContext, options: ClickAddNodeOptions) {\n    super(context, Object.assign({}, ClickAddNode.defaultOptions, options));\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(CanvasEvent.CLICK, this.addNode);\n  }\n  private addNode = (event: IPointerEvent) => {\n    const { graph } = this.context;\n    const { layerX, layerY } = event.nativeEvent as PointerEvent;\n    graph.addNodeData([\n      {\n        id: 'node-' + Date.now(),\n        style: { x: layerX, y: layerY, fill: this.options.fill },\n      },\n    ]);\n    graph.draw();\n  };\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(CanvasEvent.CLICK, this.addNode);\n  }\n  public destroy() {\n    // 销毁时解绑事件\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在示例代码中，我们实现了一个 `ClickAddNode` 交互，该交互在构造函数中添加了 Graph 的事件监听，当用户点击画布时，会在点击位置添加一个节点，并且支持配置所添加节点的填充颜色。\n- `BaseBehavior` 是所有交互的基类，每个自定义交互都需要继承这个基类实现。\n\n> 点击下面画布中的空白位置以添加一个节点，可切换右侧面板配置节点颜色\n\n<embed src=\"@/common/manual/custom-extension/behavior/implement-behaviors.md\"></embed>\n\n:::info{title=提示}\n上述示例是一个最简单的交互实现，实际开发过程中，你可能还需要处理交互的启用与禁用等逻辑。\n\n此外，多个交互之间可能会有事件冲突，你需要小心处理这些冲突。\n:::\n\n## 注册交互\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ClickAddNode } from 'your-custom-behavior-path';\n\nregister(ExtensionCategory.BEHAVIOR, 'click-add-node', ClickAddNode);\n```\n\n## 配置交互\n\n可在 `behaviors` 中传入交互类型名称或配置参数对象，比如上面的 ClickAddNode ，详见[配置交互](/manual/behavior/overview#配置和使用)\n\n```typescript\nconst graph = new Graph({\n  // 其他配置\n  behaviors: [\n    {\n      type: 'click-add-node',\n      fill: 'blue',\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragCanvas.en.md) -->\n---\ntitle: DragCanvas\norder: 6\n---\n\n## Overview\n\nDragCanvas is a built-in behavior in G6 for implementing canvas dragging functionality, supporting panning the entire canvas by dragging with a mouse or touching the screen. This is the most basic and commonly used navigation behavior in graph visualization, allowing users to freely explore graph content beyond the current viewport.\n\n## Usage Scenarios\n\nThis behavior is mainly used for:\n\n- Navigating and browsing large charts to view content outside the current viewport\n- Adjusting the view focus to move areas of interest to the center of the viewport\n- Combining with zoom interactions to achieve a complete canvas navigation experience\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // Only allow horizontal dragging\n      key: 'drag-behavior', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                          | Type                                                                                                                                                               | Default                                                                                                           | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | -------- |\n| type        | Behavior type name                                                                                                                                                                                                   | string                                                                                                                                                             | `drag-canvas`                                                                                                     | ✓        |\n| enable      | Whether to enable this behavior                                                                                                                                                                                      | boolean \\| ((event: [Event](/en/api/event#event-object-properties) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(Only enabled when clicking on the canvas) |          |\n| animation   | Drag animation configuration, only effective when using keyboard movement                                                                                                                                            | [ViewportAnimationEffectTiming](/en/api/graph#viewportanimationeffecttiming)                                                                                       | -                                                                                                                 |          |\n| direction   | Allowed drag direction, optional values are: <br/>- Set to `'both'` (default): Allow dragging in any direction <br/>- Set to `'x'`: Only allow horizontal dragging <br/>- Set to `'y'`: Only allow vertical dragging | `'x'` \\| `'y'` \\| `'both'`                                                                                                                                         | `'both'` (no direction restriction)                                                                               |          |\n| range       | Draggable viewport range (in viewport size units), [example](#range)                                                                                                                                                 | number \\| number[]                                                                                                                                                 | Infinity                                                                                                          |          |\n| sensitivity | Distance to trigger a single keyboard movement                                                                                                                                                                       | number                                                                                                                                                             | 10                                                                                                                |          |\n| trigger     | Keyboard keys to trigger dragging, [example](#trigger)                                                                                                                                                               | object                                                                                                                                                             | -                                                                                                                 |          |\n| onFinish    | Callback function when dragging is completed                                                                                                                                                                         | () => void                                                                                                                                                         | -                                                                                                                 |          |\n\n### range\n\n`range` is used to control the draggable range of the canvas:\n\n- Set as a single number: Use the same value for all four directions\n- Set as an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can drag 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can drag 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], 0 means no dragging, Infinity means unlimited dragging.\n\n### trigger\n\n`trigger` allows you to configure keyboard keys to control canvas movement:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for moving up\n    down: ['ArrowDown'], // Shortcut key for moving down\n    left: ['ArrowLeft'], // Shortcut key for moving left\n    right: ['ArrowRight'] // Shortcut key for moving right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Dragging Function\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### Only Allow Horizontal Dragging\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // Only allow horizontal dragging\n    },\n  ],\n});\n```\n\n### Limit Dragging Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // Limit dragging range to 1.5 viewport sizes\n    },\n  ],\n});\n```\n\n### Control Movement with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // Add smooth animation effect\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. Difference between DragCanvas and other behaviors\n\n- `DragCanvas` is used for dragging the entire canvas view\n- `DragElement` is used for dragging individual graph elements (nodes/edges/combinations)\n- `ScrollCanvas` is used for scrolling the canvas with the mouse wheel without changing the zoom ratio\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragCanvas.zh.md) -->\n---\ntitle: 拖拽画布 DragCanvas\norder: 6\n---\n\n## 概述\n\nDragCanvas 是 G6 中用于实现画布拖拽功能的内置交互，支持通过鼠标或触摸屏幕拖动来平移整个画布。这是图可视化中最基础且常用的导航交互，让用户能够自由探索超出当前视口的图内容。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 导航和浏览大型图表，查看当前视口外的内容\n- 调整视图焦点，将感兴趣的区域移动到视口中心\n- 与缩放交互结合，实现完整的画布导航体验\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      key: 'drag-canvas-1',\n      direction: 'x', // 只允许水平方向拖拽\n      key: 'drag-behavior', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                                                                   | 类型                                                                                                                                                 | 默认值                                                                                      | 必选 |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                                                           | string                                                                                                                                               | `drag-canvas`                                                                               | ✓    |\n| enable      | 是否启用该交互                                                                                                                                         | boolean \\| ((event: [Event](/api/event#事件对象属性) \\| [KeyboardEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent)) => boolean) | `(event) => 'eventType' in event ? event.targetType === 'canvas': true`(仅在点击画布时启用) |      |\n| animation   | 拖拽动画配置，仅在使用按键移动时有效                                                                                                                   | [ViewportAnimationEffectTiming](/api/graph#viewportanimationeffecttiming)                                                                            | -                                                                                           |      |\n| direction   | 允许的拖拽方向，可选值有：<br/>- 设为 `'both'`（默认）：允许在任意方向拖拽 <br/>- 设为 `'x'`：只允许水平方向拖拽 <br/>- 设为 `'y'`：只允许垂直方向拖拽 | `'x'` \\| `'y'` \\| `'both'`                                                                                                                           | `'both'` (不限制方向)                                                                       |      |\n| range       | 可拖拽的视口范围(以视口大小为单位)，[示例](#range)                                                                                                     | number \\| number[]                                                                                                                                   | Infinity                                                                                    |      |\n| sensitivity | 触发一次按键移动的距离                                                                                                                                 | number                                                                                                                                               | 10                                                                                          |      |\n| trigger     | 触发拖拽的键盘按键，[示例](#trigger)                                                                                                                   | object                                                                                                                                               | -                                                                                           |      |\n| onFinish    | 拖拽完成时的回调函数                                                                                                                                   | () => void                                                                                                                                           | -                                                                                           |      |\n\n### range\n\n`range` 用于控制画布可拖拽的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以拖拽2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可拖拽1个视口，左右方向可拖拽2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能拖拽，Infinity表示无限拖拽。\n\n### trigger\n\n`trigger` 允许你配置键盘按键来控制画布移动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上移动的快捷键\n    down: ['ArrowDown'], // 向下移动的快捷键\n    left: ['ArrowLeft'], // 向左移动的快捷键\n    right: ['ArrowRight'] // 向右移动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础拖拽功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas'],\n});\n```\n\n### 只允许水平拖拽\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      direction: 'x', // 只允许水平拖拽\n    },\n  ],\n});\n```\n\n### 限制拖拽范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      range: 1.5, // 限制拖拽范围为1.5个视口大小\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制移动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n      animation: {\n        duration: 100, // 添加平滑动画效果\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. DragCanvas与其他交互的区别\n\n- `DragCanvas` 用于拖拽整个画布视图\n- `DragElement` 用于拖拽单个图元素（节点/边/组合）\n- `ScrollCanvas` 用于滚轮滚动画布，不改变缩放比例\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragElement.en.md) -->\n---\ntitle: DragElement\norder: 7\n---\n\n## Overview\n\nDragElement is a built-in behavior in G6 for implementing **element dragging** functionality. It has the following core features:\n\n1. **Support for multiple element types**: Supports dragging of both nodes and combos simultaneously\n2. **Intelligent multi-selection**: Supports dragging multiple selected elements at the same time\n3. **Visual feedback**: Provides various visual feedback mechanisms such as ghost nodes, edge visibility, mouse styles, etc.\n4. **Flexible drag effects**: Supports various drag operation effects such as move, link, free drag, etc.\n5. **Parent-child relationship handling**: Automatically handles element hierarchy during dragging, especially when dealing with combo structures\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // Enable ghost node\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type       | Behavior type name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | `drag-element`                                 | ✓        |\n| key        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| enable     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| animation  | Whether to enable drag animation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | boolean                                                  | true                                           |          |\n| 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`                                     |          |\n| dropEffect | Defines the operation effect after dragging ends, optional values are: <br/>- `link`: Set the dragged element as a child of the target element <br/>- `move`: Move the element and automatically update the size of the parent element (such as combo) <br/>- `none`: Only update the position of the drag target without performing other operations                                                                                                                                                           | `link` \\| `move` \\| `none`                               | `move`                                         |          |\n| hideEdge   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |          |\n| shadow     | Whether to enable ghost nodes, which use a shape to follow the mouse movement. [Customize ghost node style](#shadow-style-configuration) ⚠️Note: React nodes do not support enabling                                                                                                                                                                                                                                                                                                                            | boolean                                                  | false                                          |          |\n| cursor     | Customize the mouse style during dragging, [configuration options](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                     | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n### shadow Style Configuration\n\nWhen `shadow: true` is enabled, you can customize the style of the ghost node with the following properties:\n\n| Option               | Description                       | Type                                | Default                                     |\n| -------------------- | --------------------------------- | ----------------------------------- | ------------------------------------------- |\n| shadowFill           | Ghost node fill color             | string                              | `#F3F9FF`                                   |\n| shadowFillOpacity    | Ghost node fill color opacity     | number                              | 0.5                                         |\n| shadowStroke         | Ghost node stroke color           | string                              | `#1890FF`                                   |\n| shadowStrokeOpacity  | Ghost node stroke opacity         | number                              | 0.9                                         |\n| shadowLineDash       | Ghost node dash configuration     | number[]                            | [5, 5]                                      |\n| shadowZIndex         | Ghost node rendering level        | number                              | 100                                         |\n| shadowWidth          | Ghost node width                  | number                              | Width of the target element's bounding box  |\n| shadowHeight         | Ghost node height                 | number                              | Height of the target element's bounding box |\n| shadowOpacity        | Overall opacity of the ghost node | number                              |                                             |\n| shadowLineWidth      | Ghost node line width             | number                              |                                             |\n| shadowLineCap        | Ghost node line cap style         | `'butt'` \\| `'round'` \\| `'square'` |                                             |\n| shadowLineJoin       | Ghost node line join style        | `'miter'` \\| `'round'` \\| `'bevel'` |                                             |\n| shadowLineDashOffset | Ghost node dash offset            | number                              |                                             |\n| shadowCursor         | Ghost node mouse style            | string                              |                                             |\n| shadowVisibility     | Ghost node visibility             | `'visible'` \\| `'hidden'`           |                                             |\n\nExample configuration:\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // Customize ghost node style\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> Note: The ghost node style inherits from [BaseStyleProps](/en/manual/element/shape/properties#baseshapestyle), the above configuration items are obtained by adding the `shadow` prefix to the property name.\n\n## Code Examples\n\n### Multi-selection Dragging\n\nNeed to cooperate with the `click-select` behavior to achieve multi-selection, and then associate the selected state through the `state` parameter:\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // All nodes in the selected state will be moved simultaneously during dragging\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragElement.zh.md) -->\n---\ntitle: 拖拽元素 DragElement\norder: 7\n---\n\n## 概述\n\nDragElement 是 G6 中用于实现 **元素拖拽** 功能的内置交互。它具有以下核心特性：\n\n1. **多元素类型支持**：可以同时支持节点（Node）和组合（Combo）的拖拽\n2. **智能多选**：支持同时拖拽多个选中状态的元素\n3. **视觉反馈**：提供幽灵节点、边的显隐、鼠标样式等多种视觉反馈机制\n4. **灵活的拖拽效果**：支持移动、链接、自由拖拽等多种拖拽操作效果\n5. **父子关系处理**：自动处理拖拽过程中的元素层级关系，特别是在处理 Combo 结构时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/drag-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element',\n      key: 'drag-element-1',\n      enableAnimation: true,\n      dropEffect: 'move',\n      shadow: true, // 启用拖拽幽灵节点\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type       | 交互类型名称                                                                                                                                                                                                                                                                                                                                            | string                                                   | `drag-element`                                 | ✓    |\n| key        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| enable     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| animation  | 是否启用拖拽动画                                                                                                                                                                                                                                                                                                                                        | boolean                                                  | true                                           |      |\n| state      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| dropEffect | 定义拖拽结束后的操作效果，可选值有：<br/>- `link`: 将拖拽元素设置为目标元素的子元素 <br/>- `move`: 移动元素并自动更新父元素（如 Combo）的尺寸 <br/>- `none`: 仅更新拖拽目标的位置，不执行其他操作                                                                                                                                                       | `link` \\| `move` \\| `none`                               | `move`                                         |      |\n| hideEdge   | 控制拖拽过程中边的显示状态，可选值有： <br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                     | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                         |      |\n| shadow     | 是否启用幽灵节点，即用一个图形代替节点跟随鼠标移动。[自定义幽灵节点样式](#shadow-样式配置) ⚠️注意：React 节点不支持启用                                                                                                                                                                                                                                 | boolean                                                  | false                                          |      |\n| cursor     | 自定义鼠标样式，[配置项](#cursor)                                                                                                                                                                                                                                                                                                                       | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n### shadow 样式配置\n\n当启用 `shadow: true` 时，可以通过以下属性自定义幽灵节点的样式：\n\n| 配置项               | 说明                   | 类型                                | 默认值               |\n| -------------------- | ---------------------- | ----------------------------------- | -------------------- |\n| shadowFill           | 幽灵节点填充色         | string                              | `#F3F9FF`            |\n| shadowFillOpacity    | 幽灵节点填充色透明度   | number                              | 0.5                  |\n| shadowStroke         | 幽灵节点描边颜色       | string                              | `#1890FF`            |\n| shadowStrokeOpacity  | 幽灵节点描边透明度     | number                              | 0.9                  |\n| shadowLineDash       | 幽灵节点虚线配置       | number[]                            | [5, 5]               |\n| shadowZIndex         | 幽灵节点渲染层级       | number                              | 100                  |\n| shadowWidth          | 幽灵节点宽度           | number                              | 目标元素的包围盒宽度 |\n| shadowHeight         | 幽灵节点高度           | number                              | 目标元素的包围盒高度 |\n| shadowOpacity        | 幽灵节点整体透明度     | number                              |                      |\n| shadowLineWidth      | 幽灵节点线宽度         | number                              |                      |\n| shadowLineCap        | 幽灵节点线段端点样式   | `'butt'` \\| `'round'` \\| `'square'` |                      |\n| shadowLineJoin       | 幽灵节点线段连接处样式 | `'miter'` \\| `'round'` \\| `'bevel'` |                      |\n| shadowLineDashOffset | 幽灵节点虚线偏移量     | number                              |                      |\n| shadowCursor         | 幽灵节点鼠标样式       | string                              |                      |\n| shadowVisibility     | 幽灵节点可见性         | `'visible'` \\| `'hidden'`           |                      |\n\n示例配置：\n\n```javascript\n{\n  type: 'drag-element',\n  shadow: true,\n  // 自定义幽灵节点样式\n  shadowFill: '#E8F3FF',\n  shadowFillOpacity: 0.4,\n  shadowStroke: '#1890FF',\n  shadowStrokeOpacity: 0.8,\n  shadowLineDash: [4, 4],\n  shadowZIndex: 99\n}\n```\n\n> 注意：幽灵节点样式继承自 [BaseStyleProps](/manual/element/shape/properties#baseshapestyle)，上述配置项是在属性名前添加 `shadow` 前缀得到的。\n\n## 代码示例\n\n### 多选推拽\n\n需要配合 `click-select` 行为实现多选，然后通过 `state` 参数关联选中状态：\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'click-select',\n      multiple: true,\n      state: 'selected',\n    },\n    {\n      type: 'drag-element',\n      state: 'selected', // 拖拽时会同时移动所有 selected 状态的节点\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragElementForce.en.md) -->\n---\ntitle: DragElementForce\norder: 8\n---\n\n## Overview\n\nDragElementForce 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.\n\n<img alt=\"Effect of DragElementForce\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // Fix node position after dragging\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | Type                                                     | Default                                        | Required |\n| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | -------- |\n| type                                       | Behavior type name, set `type: 'drag-element-force'` to enable this behavior                                                                                                                                                                                                                                                                                                                                                                                                                                    | string                                                   | `drag-element-force`                           | ✓        |\n| key                                        | Unique identifier for the behavior, used for subsequent operations                                                                                                                                                                                                                                                                                                                                                                                                                                              | string                                                   | -                                              |          |\n| fixed                                      | Whether to keep the node position fixed after dragging ends, boolean values represent: <br/>- true: After dragging ends, the node's position will remain fixed and not be affected by the layout algorithm <br/>- false: After dragging ends, the node's position will continue to be affected by the layout algorithm                                                                                                                                                                                          | boolean                                                  | false                                          |          |\n| enable                                     | Whether to enable the drag function, by default nodes and combos can be dragged                                                                                                                                                                                                                                                                                                                                                                                                                                 | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |          |\n| 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`                                     |          |\n| hideEdge                                   | Controls the display state of edges during dragging, optional values are: <br/>- `none`: Do not hide any edges <br/>- `out`: Hide edges with the current node as the source node <br/>- `in`: Hide edges with the current node as the target node <br/>- `both`: Hide all edges related to the current node <br/>- `all`: Hide all edges in the graph <br/>⚠️ Note: When `shadow` (ghost node) is enabled, the `hideEdge` configuration will not take effect.                                                   | `none` \\| `all` \\| `in` \\| `out` \\| `both`               | `none`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                          |\n| cursor                                     | Customize the mouse style during dragging, [example](#cursor)                                                                                                                                                                                                                                                                                                                                                                                                                                                   | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |          |\n| trigger                                    | Press this shortcut key in combination with mouse perform drag element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> ⚠️ Note, setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to fail. The two cannot be configured simultaneously. | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | [`shift`]                                      |          |\n\n### cursor\n\n`cursor` is used to customize the mouse pointer style during dragging:\n\n- `default`: Pointer style in default state\n- `grab`: Pointer style when hovering over a draggable element\n- `grabbing`: Pointer style when dragging\n\nOptional 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`\n\nExample configuration:\n\n```js\ncursor: {\n  default: 'default',    // Use normal pointer by default\n  grab: 'grab',         // Show grab pointer when draggable\n  grabbing: 'grabbing'  // Show grabbing pointer when dragging\n}\n```\n\n## FAQ\n\n### 1. What is the difference between DragElementForce and DragElement?\n\n- `DragElementForce` is specifically used for `d3-force` or `d3-force-3d` layouts, and recalculates the layout in real-time during dragging\n- `DragElement` is a general drag interaction and does not trigger layout recalculation\n\n## Practical Example\n\n### Mesh Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### Fix Dragged Nodes\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Shadow Style\n\n### shadow{[BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#%E7%BB%98%E5%9B%BE%E5%B1%9E%E6%80%A7)}\n\n<details><summary>An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.</summary>\n\nTextStyleProps includes the following properties:\n\n- fill\n- fontSize\n- fontWeight\n- ...\n\nicon{TextStyleProps} means you need to use the following property names:\n\n- iconFill\n- iconFontSize\n- iconFontWeight\n- ...\n\n</details>\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/DragElementForce.zh.md) -->\n---\ntitle: 力导向拖拽元素 DragElementForce\norder: 8\n---\n\n## 概述\n\nDragElementForce 是 G6 中用于实现 `d3-force` 和 `d3-force-3d` 布局下节点拖拽的内置交互。在拖拽过程中会 **实时重新计算布局**，使得图的布局能够动态调整以适应节点的新位置。\n\n<img alt=\"力导向拖拽元素效果图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-element-force'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      key: 'drag-element-force-1',\n      fixed: true, // 拖拽后固定节点位置\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                                     | 说明                                                                                                                                                                                                                                                                                                                                                    | 类型                                                     | 默认值                                         | 必选 |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------- | ---- |\n| type                                       | 交互类型名称，这里设置 `type: 'drag-element-force'` 启用此交互                                                                                                                                                                                                                                                                                          | string                                                   | `drag-element-force`                           | ✓    |\n| key                                        | 交互唯一标识符，用于后续操作交互                                                                                                                                                                                                                                                                                                                        | string                                                   | -                                              |      |\n| fixed                                      | 在拖拽结束后，节点是否保持固定位置，布尔值代表：<br/>- true: 在拖拽结束后，节点的位置将保持固定，不受布局算法的影响 <br/>- false: 在拖拽结束后，节点的位置将继续受到布局算法的影响                                                                                                                                                                      | boolean                                                  | false                                          |      |\n| enable                                     | 是否启用拖拽功能，默认可以拖拽节点和 Combo                                                                                                                                                                                                                                                                                                              | boolean \\| ((event: IElementDragEvent) => boolean)       | `['node', 'combo'].includes(event.targetType)` |      |\n| state                                      | 节点选中状态的标识，启用多选时会基于该状态查找选中的节点                                                                                                                                                                                                                                                                                                | string                                                   | `selected`                                     |      |\n| hideEdge                                   | 控制拖拽过程中边的显示状态，可选值有：<br/>- `none`: 不隐藏任何边 <br/>- `out`: 隐藏以当前节点为源节点的边 <br/>- `in`: 隐藏以当前节点为目标节点的边 <br/>- `both`: 隐藏与当前节点相关的所有边 <br/>- `all`: 隐藏图中所有边 <br/>⚠️ 注意：当启用 `shadow`（幽灵节点）时，`hideEdge` 配置将不生效。                                                      | `none` \\| `all` \\| `in` \\| `out` \\| `both`                                      | `none`                                                                                                                                                                                                                                                                                                                                                  |                                                          |\n| cursor                                     | 自定义鼠标样式，[示例](#cursor)                                                                                                                                                                                                                                                                                                                         | { default?: Cursor; grab: Cursor; grabbing: Cursor }     | -                                              |      |\n| trigger                                    | 同时按下快捷键才能拖拽元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> ⚠️ 注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。 | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[] | []                                             |      |\n\n### cursor\n\n`cursor` 用于自定义拖拽过程中的鼠标指针样式：\n\n- `default`: 默认状态下的指针样式\n- `grab`: 鼠标悬停在可拖拽元素上时的指针样式\n- `grabbing`: 正在拖拽时的指针样式\n\n可选值有：`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`\n\n示例配置：\n\n```js\ncursor: {\n  default: 'default',    // 默认使用普通指针\n  grab: 'grab',         // 可拖拽时显示抓取指针\n  grabbing: 'grabbing'  // 拖拽中显示抓取中指针\n}\n```\n\n## 常见问题\n\n### 1. DragElementForce 和 DragElement 有什么区别？\n\n- `DragElementForce` 专门用于 `d3-force` 或 `d3-force-3d` 布局，拖拽时会实时重新计算布局\n- `DragElement` 是通用的拖拽交互，不会触发布局重新计算\n\n## 实际案例\n\n### 网格效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfunction getData(size = 10) {\n  const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));\n  const edges = [];\n  for (let y = 0; y < size; ++y) {\n    for (let x = 0; x < size; ++x) {\n      if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });\n      if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });\n    }\n  }\n  return { nodes, edges };\n}\n\nconst graph = new Graph({\n  data: getData(),\n  layout: {\n    type: 'd3-force',\n    manyBody: {\n      strength: -30,\n    },\n    link: {\n      strength: 1,\n      distance: 20,\n      iterations: 10,\n    },\n  },\n  node: {\n    style: {\n      size: 10,\n      fill: '#000',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#000',\n    },\n  },\n  behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();\n});\n```\n\n### 固定被拖拽的节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(10).fill(0).map((_, i) => ({ id: `${i}`, label: `${i}` })),\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '5' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      labelPlacement: 'middle',\n      labelFill: '#fff',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    link: {\n      distance: 100,\n      strength: 2,\n    },\n    collide: {\n      radius: 40,\n    },\n  },\n  behaviors: [\n    {\n      type: 'drag-element-force',\n      fixed: true,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/FixElementSize.en.md) -->\n---\ntitle: FixElementSize\norder: 9\n---\n\n## Overview\n\nFixElementSize is a built-in interaction provided by G6, used to **maintain the size of certain elements within nodes unchanged during the zooming process.** It enhances visual consistency and operability during zooming.\nBy listening to viewport changes, it automatically scales elements marked as \"fixed size\" to ensure they maintain a relatively constant display size at different zoom levels. It supports global enablement and also allows control over specific elements or nodes as needed.\n\n## Use Cases\n\nThis interaction is mainly used for:\n\n- Graphical elements or embedded components (buttons, labels, etc.) that need to maintain a fixed visual size\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## Basic Usage\n\nAdd this interaction in the graph configuration\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // Enable this interaction\n      state: 'selected', // State of elements to fix size\n      reset: true, // Restore style when elements are redrawn\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option      | Description                                                                                                                                                                                                    | Type                                                                         | Default                                                                                             | Required |\n| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------- |\n| type        | Interaction type name                                                                                                                                                                                          | string                                                                       | `fix-element-size`                                                                                  | ✓        |\n| enable      | Whether to enable this interaction, [example](#enable)                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean) | true                                                                                                |          |\n| reset       | Whether to restore style when elements are redrawn                                                                                                                                                             | boolean                                                                      | `false`                                                                                             |          |\n| state       | Specify the state of elements to fix size                                                                                                                                                                      | string                                                                       | \"\"                                                                                                  |          |\n| node        | Node configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed, [example](#node)                                     | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| nodeFilter  | Node filter, used to filter which nodes maintain a fixed size during zooming                                                                                                                                   | (datum: [NodeData](/manual/data#nodedata)) => boolean                        | `() => true`                                                                                        |          |\n| edge        | Edge configuration item, used to define which attributes maintain a fixed visual size. By default, the lineWidth and labelFontSize attributes are fixed, usage is the same as [node configuration item](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |          |\n| edgeFilter  | Edge filter, used to filter which edges maintain a fixed size during zooming                                                                                                                                   | (datum: [EdgeData](/manual/data#edgedata)) => boolean                        | `() => true`                                                                                        |          |\n| combo       | Combo configuration item, used to define which attributes maintain a fixed visual size. By default, the entire Combo will be fixed, usage is the same as [node configuration item](#node)                      | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]                        |                                                                                                     |          |\n| comboFilter | Combo filter, used to filter which Combos maintain a fixed size during zooming                                                                                                                                 | (datum: [ComboData](/manual/data#combodata)) => boolean                      | `() => true`                                                                                        |          |\n\n### enable\n\nWhether to enable the fixed element size interaction. By default, it is enabled when zooming out the canvas\n\nBy default, it is enabled when zooming out the canvas, set `enable: (event) => event.data.scale < 1`; if you want to enable it when zooming in, set `enable: (event) => event.data.scale > 1`; if you want to enable it when both zooming in and out, set `enable: true`\n\n### node\n\nNode configuration item, used to define which attributes maintain a fixed visual size. If not specified (i.e., undefined), the entire node will be fixed\n\n**Example**\n\nIf you want to fix the lineWidth of the main shape of the node during zooming, you can configure it like this:\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\nIf you want to keep the size of the element label unchanged during zooming, you can configure it like this:\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| Parameter | Description                                                                                                                                                        | Type                                                   | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | ------- | -------- |\n| shape     | Specify the shape to fix size, it can be the class name of the shape, or a function that receives all shapes constituting the element and returns the target shape | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -       | ✓        |\n| fields    | Specify the fields of the shape to fix size. If not specified, the entire shape size is fixed by default                                                           | string[]                                               | -       | ✘        |\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/FixElementSize.zh.md) -->\n---\ntitle: 缩放画布时固定元素大小 FixElementSize\norder: 9\n---\n\n## 概述\n\nFixElementSize 是 G6 提供的一种内置交互，用于在视图缩放过程中，**保持节点中某些元素的尺寸不随缩放变化。** 提升缩放过程中的视觉一致性与可操作性。\n通过监听视口变化，自动对标记为“固定尺寸”的元素进行缩放补偿，确保它们在不同缩放级别下保持相对恒定的显示尺寸。支持全局启用，也支持按需控制具体元素或节点的适配行为。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 需要固定视觉大小的图形元素或嵌入式组件（按钮、标签等）\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/fix-element-size.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['fix-element-size'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'fix-element-size',\n      enable: true, // 开启该交互\n      state: 'selected', // 要固定大小的元素状态\n      reset: true, // 元素重绘时还原样式\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项      | 说明                                                                                                              | 类型                                                              | 默认值                                                                                              | 必选 |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ---- |\n| type        | 交互类型名称                                                                                                      | string                                                            | `fix-element-size`                                                                                  | √    |\n| enable      | 是否启用该交互，[示例](#enable)                                                                                   | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean) | true                                                                                                |      |\n| reset       | 元素重绘时是否还原样式                                                                                            | boolean                                                           | `false`                                                                                             |      |\n| state       | 指定要固定大小的元素状态                                                                                          | string                                                            | \"\"                                                                                                  |      |\n| node        | 节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定，[示例](#node)   | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| nodeFilter  | 节点过滤器，用于过滤哪些节点在缩放过程中保持固定大小                                                              | (datum: [NodeData](/manual/data#节点数据nodedata)) => boolean     | `() => true`                                                                                        |      |\n| edge        | 边配置项，用于定义哪些属性在视觉上保持固定大小。默认固定 lineWidth、labelFontSize 属性，用法同[node配置项](#node) | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             | `[ shape: 'key', fields: ['lineWidth'] ,  shape: 'halo', fields: ['lineWidth'] ,  shape: 'label' ]` |      |\n| edgeFilter  | 边过滤器，用于过滤哪些边在缩放过程中保持固定大小                                                                  | (datum: [EdgeData](/manual/data#边数据edgedata)) => boolean       | `() => true`                                                                                        |      |\n| combo       | Combo 配置项，用于定义哪些属性在视觉上保持固定大小。默认整个 Combo 将被固定，用法同[node配置项](#node)            | [FixShapeConfig](#fixshapeconfig) \\| FixShapeConfig[]             |                                                                                                     |      |\n| comboFilter | Combo 过滤器，用于过滤哪些 Combo 在缩放过程中保持固定大小                                                         | (datum: [ComboData](/manual/data#组合数据combodata)) => boolean   | `() => true`                                                                                        |      |\n\n### enable\n\n是否启用固定元素大小交互。默认在缩小画布时启用\n\n默认在缩小画布时启用，设置 `enable: (event) => event.data.scale < 1`；如果希望在放大画布时启用，设置 `enable: (event) => event.data.scale > 1`；如果希望在放大缩小画布时都启用，设置 `enable: true`\n\n### node\n\n节点配置项，用于定义哪些属性在视觉上保持固定大小。若未指定（即为 undefined），则整个节点将被固定\n\n**示例**\n\n如果在缩放过程中希望固定节点主图形的 lineWidth，可以这样配置：\n\n```ts\n{\n  node: [{ shape: 'key', fields: ['lineWidth'] }];\n}\n```\n\n如果在缩放过程中想保持元素标签大小不变，可以这样配置：\n\n```ts\n{\n  shape: 'label';\n}\n```\n\n### FixShapeConfig\n\n| 参数   | 描述                                                                                                 | 类型                                                   | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------ | ---- |\n| shape  | 指定要固定大小的图形，可以是图形的类名字，或者是一个函数，该函数接收构成元素的所有图形并返回目标图形 | string \\| ((shapes: DisplayObject[]) => DisplayObject) | -      | ✓    |\n| fields | 指定要固定大小的图形属性字段。如果未指定，则默认固定整个图形的大小                                   | string[]                                               | -      | ✘    |\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node0', size: 50, label: '0', style: { x: 326, y: 268 }, states: ['selected'] },\n    { id: 'node1', size: 30, label: '1', style: { x: 280, y: 384 }, states: ['selected'] },\n    { id: 'node2', size: 30, label: '2', style: { x: 234, y: 167 } },\n    { id: 'node3', size: 30, label: '3', style: { x: 391, y: 368 } },\n    { id: 'node4', size: 30, label: '4', style: { x: 444, y: 209 } },\n    { id: 'node5', size: 30, label: '5', style: { x: 378, y: 157 } },\n    { id: 'node6', size: 15, label: '6', style: { x: 229, y: 400 } },\n    { id: 'node7', size: 15, label: '7', style: { x: 281, y: 440 } },\n    { id: 'node8', size: 15, label: '8', style: { x: 188, y: 119 } },\n    { id: 'node9', size: 15, label: '9', style: { x: 287, y: 157 } },\n    { id: 'node10', size: 15, label: '10', style: { x: 185, y: 200 } },\n    { id: 'node11', size: 15, label: '11', style: { x: 238, y: 110 } },\n    { id: 'node12', size: 15, label: '12', style: { x: 239, y: 221 } },\n    { id: 'node13', size: 15, label: '13', style: { x: 176, y: 160 } },\n    { id: 'node14', size: 15, label: '14', style: { x: 389, y: 423 } },\n    { id: 'node15', size: 15, label: '15', style: { x: 441, y: 341 } },\n    { id: 'node16', size: 15, label: '16', style: { x: 442, y: 398 } },\n  ],\n  edges: [\n    { source: 'node0', target: 'node1', label: '0-1', states: ['selected'] },\n    { source: 'node0', target: 'node2', label: '0-2' },\n    { source: 'node0', target: 'node3', label: '0-3' },\n    { source: 'node0', target: 'node4', label: '0-4' },\n    { source: 'node0', target: 'node5', label: '0-5' },\n    { source: 'node1', target: 'node6', label: '1-6' },\n    { source: 'node1', target: 'node7', label: '1-7' },\n    { source: 'node2', target: 'node8', label: '2-8' },\n    { source: 'node2', target: 'node9', label: '2-9' },\n    { source: 'node2', target: 'node10', label: '2-10' },\n    { source: 'node2', target: 'node11', label: '2-11' },\n    { source: 'node2', target: 'node12', label: '2-12' },\n    { source: 'node2', target: 'node13', label: '2-13' },\n    { source: 'node3', target: 'node14', label: '3-14' },\n    { source: 'node3', target: 'node15', label: '3-15' },\n    { source: 'node3', target: 'node16', label: '3-16' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.label,\n      size: (d) => d.size,\n      lineWidth: 1,\n    },\n  },\n  edge: { style: { labelText: (d) => d.label } },\n  behaviors: [\n    'zoom-canvas',\n    'drag-canvas',\n    {\n      key: 'fix-element-size',\n      type: 'fix-element-size',\n      enable: (event) => event.data.scale < 1,\n      state: 'selected',\n      reset: true,\n    },\n    { type: 'click-select', key: 'click-select', multiple: true },\n  ],\n  autoFit: 'center',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/FocusElement.en.md) -->\n---\ntitle: FocusElement\norder: 10\n---\n\n## Overview\n\nFocusElement is a built-in behavior in G6 used to implement the element focusing feature, allowing elements to be focused to the center of the view by clicking on them. This behavior helps users quickly locate and focus on specific graph elements.\n\n## Use Cases\n\n- Quickly center the focused nodes or edges in the display\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                                                                                                                                                                                                                                                                                                                                 | Type                                                            | Default                                | Required |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | -------- |\n| type      | Behavior type name                                                                                                                                                                                                                                                                                                                                                          | string                                                          | `focus-element`                        | ✓        |\n| animation | Focus animation settings                                                                                                                                                                                                                                                                                                                                                    | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |          |\n| enable    | Whether to enable the focus feature                                                                                                                                                                                                                                                                                                                                         | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |          |\n| trigger   | Press this shortcut key in combination with mouse perform foucs element **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_. If set to an **empty array**, it means drag element can be performed with mouse without pressing other keys <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | [`shift`]                              |          |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## Code Examples\n\n### Basic Focus Feature\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### Custom Animation Effects\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### Conditional Focus Enablement\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // Enable focus only for nodes, not edges\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/FocusElement.zh.md) -->\n---\ntitle: 聚焦元素 FocusElement\norder: 10\n---\n\n## 概述\n\nFocusElement 是 G6 中用于实现元素聚焦功能的内置交互，支持通过点击元素将其聚焦到视图中心。这个交互可以帮助用户快速定位和关注特定的图元素。\n\n## 使用场景\n\n- 快速将关注的节点或边居中显示\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/focus-element.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['focus-element'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 500,\n        easing: 'ease-in',\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项    | 说明                                                                                                                                                                                                                                                           | 类型                                                            | 默认值                                 | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------- | ---- |\n| type      | 交互类型名称                                                                                                                                                                                                                                                   | string                                                          | `focus-element`                        | ✓    |\n| animation | 聚焦动画效果设置                                                                                                                                                                                                                                               | [ViewportAnimationEffectTiming](#viewportanimationeffecttiming) | `{ duration: 500, easing: 'ease-in' }` |      |\n| enable    | 是否启用聚焦功能                                                                                                                                                                                                                                               | boolean \\| ((event: IElementEvent) => boolean)                  | true                                   |      |\n| trigger   | 同时按下快捷键才能聚焦元素 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ 。若设为**空数组**时则表示不需要按下其他按键配合 <br/> | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]        | []                                     |      |\n\n### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## 代码示例\n\n### 基础聚焦功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['focus-element'],\n});\n```\n\n### 自定义动画效果\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      animation: {\n        duration: 800,\n        easing: 'ease-in-out',\n      },\n    },\n  ],\n});\n```\n\n### 条件性启用聚焦\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'focus-element',\n      enable: (event) => {\n        // 只对节点启用聚焦，边不聚焦\n        return event.target.type === 'node';\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', combo: 'combo1', style: { x: 110, y: 150 } },\n    { id: 'node2', combo: 'combo1', style: { x: 190, y: 150 } },\n    { id: 'node3', combo: 'combo2', style: { x: 150, y: 260 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n  combos: [{ id: 'combo1', combo: 'combo2' }, { id: 'combo2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  node: {\n    style: { labelText: (d) => d.id },\n  },\n  data,\n  behaviors: ['collapse-expand', 'focus-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/HoverActivate.en.md) -->\n---\ntitle: HoverActivate\norder: 11\n---\n\n## Overview\n\nHoverActivate is a built-in behavior in G6 used to implement the hover activation effect on elements. When the mouse hovers over nodes or edges, it automatically triggers visual feedback such as highlighting and displaying. This behavior is an important means of enhancing data exploration in graph visualization, helping users quickly focus on target elements and obtain related information.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly locating elements of interest in complex relationship graphs\n- Displaying additional information of nodes through hover\n- Highlighting connection paths by activating edges when analyzing relationships between nodes\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // Specify an identifier for the behavior for dynamic updates\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option        | Description                                 | Type                                           | Default          | Required |\n| ------------- | ------------------------------------------- | ---------------------------------------------- | ---------------- | -------- |\n| type          | Behavior type name                          | string                                         | `hover-activate` | ✓        |\n| animation     | Whether to enable animation                 | boolean                                        | true             |          |\n| enable        | Whether to enable hover feature             | boolean \\| ((event: IPointerEvent) => boolean) | true             |          |\n| degree        | Degree of relationship to activate elements | number \\| ((event: IPointerEvent) => number);  | 0                |          |\n| direction     | Specify edge direction                      | `both` \\| `in` \\| `out`                        | `both`           |          |\n| state         | State of activated elements                 | string                                         | `active`         |          |\n| inactiveState | State of inactive elements                  | string                                         | -                |          |\n| onHover       | Callback when element is hovered            | (event: IPointerEvent) => void                 | -                |          |\n| onHoverEnd    | Callback when hover ends                    | (event: IPointerEvent) => void                 | -                |          |\n\n### enable\n\n`enable` is used to control whether to enable hover highlighting of elements, and can receive a function for dynamic control\n\nFor example: Enable hover highlighting only for nodes\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hover Usage\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['hover-activate'],\n});\n```\n\n### Node Trigger Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### Flowchart Node Hover Next Node Highlight\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/HoverActivate.zh.md) -->\n---\ntitle: 悬停激活 HoverActivate\norder: 11\n---\n\n## 概述\n\nHoverActivate 是 G6 中用于实现元素悬停激活效果的内置交互，当鼠标悬停在节点或边上时，会自动触发高亮、显示等视觉反馈。该交互是图可视化中增强数据探索的重要手段，有助于用户快速聚焦目标元素并获取相关信息。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 在复杂关系图中快速定位关注元素\n- 通过悬停信息展示节点额外信息\n- 分析节点间关联关系时，通过激活边凸显连接路径\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/hover-activate.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      key: 'hover-activate-1', // 为交互指定标识符，方便动态更新\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项        | 说明                 | 类型                                           | 默认值           | 必选 |\n| ------------- | -------------------- | ---------------------------------------------- | ---------------- | ---- |\n| type          | 交互类型名称         | string                                         | `hover-activate` | ✓    |\n| animation     | 是否开启动画效果     | boolean                                        | true             |      |\n| enable        | 是否开启悬浮元素功能 | boolean \\| ((event: IPointerEvent) => boolean) | true             |      |\n| degree        | 激活元素的n度关系    | number \\| ((event: IPointerEvent) => number);  | 0                |      |\n| direction     | 指定边方向           | `both` \\| `in` \\| `out`                        | `both`           |      |\n| state         | 激活元素的状态       | string                                         | `active`         |      |\n| inactiveState | 不激活元素的状态     | string                                         | -                |      |\n| onHover       | 当元素被悬停时的回调 | (event: IPointerEvent) => void                 | -                |      |\n| onHoverEnd    | 当悬停结束时的回调   | (event: IPointerEvent) => void                 | -                |      |\n\n### enable\n\n`enable` 用于控制是否开启元素的悬浮高亮，可接收一个函数来动态控制\n\n例如：只有节点开启悬浮高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础悬浮用法\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['hover-activate'],\n});\n```\n\n### 节点触发高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n### 流程图移入节点 下一步节点高亮\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'hover-activate',\n      degree: 1,\n      direction: 'out',\n      enable: (e) => {\n        if (e.targetType === 'node') {\n          return true;\n        }\n        return false;\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst format = (data) => {\n  const { nodes, edges } = data;\n  return {\n    nodes: nodes.map(({ id, ...node }) => ({ id, data: node })),\n    edges: edges.map(({ id, source, target, ...edge }) => ({ id, source, target, data: edge })),\n  };\n};\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/xiaomi.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: format(data),\n      behaviors: ['hover-activate'],\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        nodeSize: 24,\n      },\n      animation: false,\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/LassoSelect.en.md) -->\n---\ntitle: LassoSelect\norder: 12\n---\n\n## Overview\n\nClick and drag the mouse to draw an **irregular** box to enclose elements, and the elements within the selected range will be selected.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Quickly selecting a batch of elements, making it easier to avoid elements you don't want to select\n- Quickly deselecting a batch of elements, making it easier to avoid elements you want to keep\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: ['shift', 'alt', 'control'], // Use multiple keys for selection\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option                      | Description                                                                                                                                                                                                                               | Type                                                                                                                           | Default                   | Required |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | -------- |\n| type                        | Behavior type name. This plugin is built-in, you can use it by `type: 'lasso-select'`.                                                                                                                                                    | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓        |\n| animation                   | Whether to enable animation                                                                                                                                                                                                               | boolean                                                                                                                        | false                     |          |\n| enable                      | Whether to enable lasso selection                                                                                                                                                                                                         | boolean \\| ((event: [Event](/api/event#event-object-properties)) => boolean)                                                   | true                      |          |\n| enableElements              | Types of elements that can be selected                                                                                                                                                                                                    | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |          |\n| [immediately](#immediately) | Whether to select immediately, only effective when [selection mode](#mode) is `default`                                                                                                                                                   | boolean                                                                                                                        | false                     |          |\n| [mode](#mode)               | Selection mode                                                                                                                                                                                                                            | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |          |\n| onSelect                    | Callback for selected element state                                                                                                                                                                                                       | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |          |\n| state                       | State to switch to when selected                                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |          |\n| [style](#style)             | Style of the box during selection                                                                                                                                                                                                         | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [Default](#style)         |          |\n| trigger                     | Press this shortcut key along with mouse click to select **Key reference:** _<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |          |\n\n### immediately\n\nWhether to select immediately, only effective when selection mode is `default`\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Elements are immediately selected when the box encloses them\n      trigger: [], // No need for other keys, just click and drag the mouse to select\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // Immediate selection\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\nSelection mode\n\n- `union`: Keep the current state of selected elements and add the specified state.\n- `intersect`: Retain the specified state if the selected elements already have it; otherwise, clear the state.\n- `diff`: Toggle the specified state of the selected elements.\n- `default`: Clear the current state of selected elements and add the specified state.\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // Selection mode, default selection mode\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| Property          | Description             | Type                                     | Default   |\n| ----------------- | ----------------------- | ---------------------------------------- | --------- |\n| cursor            | Mouse style             | string                                   |           |\n| fill              | Fill color              | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | Fill opacity            | number \\| string                         | 0.1       |\n| isBillboard       | Billboard mode          | boolean                                  |           |\n| isSizeAttenuation | Size attenuation        | boolean                                  |           |\n| lineCap           | Line cap style          | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | Dash line config        | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | Dash line offset        | number                                   |           |\n| lineJoin          | Line join style         | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | Line width              | number \\| string                         | 1         |\n| opacity           | Overall opacity         | number \\| string                         |           |\n| radius            | Rectangle corner radius | number \\| string \\| number[]             |           |\n| shadowBlur        | Shadow blur level       | number                                   |           |\n| shadowColor       | Shadow color            | string                                   |           |\n| shadowOffsetX     | Shadow X offset         | number                                   |           |\n| shadowOffsetY     | Shadow Y offset         | number                                   |           |\n| stroke            | Stroke color            | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | Stroke opacity          | number \\| string                         |           |\n| visibility        | Visibility              | `visible` \\| `hidden`                    |           |\n| zIndex            | Rendering level         | number                                   | 2         |\n\n**Example**:\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // Dashed outline\n        // RGB super colorful box\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\nPress this shortcut key along with mouse click to select, if set to an **empty array**, it means mouse click to select without needing to press other keys.\n\nNote that setting `trigger` to `['drag']` will cause the `drag-canvas` behavior to be disabled. They cannot be configured simultaneously.\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/LassoSelect.zh.md) -->\n---\ntitle: 套索选择 LassoSelect\norder: 12\n---\n\n## 概述\n\n鼠标点击拖出一个 **不规则的** 框框笼罩元素，精准框选范围内的元素会被选中。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 快速选中一批元素，并且更容易的避开不想选的元素\n- 快速取消选中一批元素，并且更容易的避开想保留的元素\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/lasso-select.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['lasso-select'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: ['shift', 'alt', 'control'], // 配合多种按键进行框选\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项                      | 说明                                                                                                                                                                                                          | 类型                                                                                                                           | 默认值                    | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | ---- |\n| type                        | 交互类型名称。此插件已内置，你可以通过 `type: 'lasso-select'` 来使用它。                                                                                                                                      | `lasso-select` \\| string                                                                                                       | `lasso-select`            | ✓    |\n| animation                   | 是否启用动画                                                                                                                                                                                                  | boolean                                                                                                                        | false                     |      |\n| enable                      | 是否启用框选功能                                                                                                                                                                                              | boolean \\| ((event: [Event](/api/event#事件对象属性)) => boolean)                                                              | true                      |      |\n| enableElements              | 可框选的元素类型                                                                                                                                                                                              | ( `node` \\| `edge` \\| `combo` )[]                                                                                              | [`node`, `combo`, `edge`] |      |\n| [immediately](#immediately) | 是否及时框选, 仅在[框选模式 mode](#mode)为 `default` 时生效                                                                                                                                                   | boolean                                                                                                                        | false                     |      |\n| [mode](#mode)               | 框选的选择模式                                                                                                                                                                                                | `union` \\| `intersect` \\| `diff` \\| `default`                                                                                  | `default`                 |      |\n| onSelect                    | 框选元素状态回调                                                                                                                                                                                              | (states:Record&lt;string,string\\|string[]>) =>Record&lt;string,string\\|string[]>                                               |                           |      |\n| state                       | 被选中时切换到该状态                                                                                                                                                                                          | string \\| `selected` \\| `active` \\| `inactive` \\| `disabled` \\| `highlight`                                                    | `selected`                |      |\n| [style](#style)             | 框选时的 框样式                                                                                                                                                                                               | <a href=\"/manual/element/shape/properties\" target=\"_blank\" rel=\"noopener noreferrer\">RectStyleProps extends BaseStyleProps</a> | [默认值](#style)          |      |\n| trigger                     | 按下该快捷键配合鼠标点击进行框选 **按键参考：** _<a href=\"https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values\" target=\"_blank\" rel=\"noopener noreferrer\">MDN Key Values</a>_ | string[] \\| (`Control` \\| `Shift`\\| `Alt` \\| `......`)[]                                                                       | [`shift`]                 |      |\n\n### immediately\n\n是否及时框选, 仅在框选模式为 `default` 时生效\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 可以看到框框笼罩过去时，元素立即被框选了\n      trigger: [], // 不需要配合其他按键，点击鼠标拖动即可框选\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 100, y: 50 } },\n      { id: 'node-2', style: { x: 260, y: 50 } },\n      { id: 'node-3', style: { x: 280, y: 100 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      immediately: true, // 立即框选\n      trigger: [],\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n});\n\ngraph.render();\n```\n\n### mode\n\n框选的选择模式\n\n- `union`：保持已选元素的当前状态，并添加指定的 state 状态。\n- `intersect`：如果已选元素已有指定的 state 状态，则保留；否则清除该状态。\n- `diff`：对已选元素的指定 state 状态进行取反操作。\n- `default`：清除已选元素的当前状态，并添加指定的 state 状态。\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      mode: 'default', // 框选模式, 默认框选模式\n    },\n  ],\n});\n```\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: [\n        { id: 'node-1', style: { x: 200, y: 100 } },\n        { id: 'node-2', style: { x: 360, y: 100 } },\n        { id: 'node-3', style: { x: 280, y: 220 } },\n      ],\n      edges: [\n        { source: 'node-1', target: 'node-2' },\n        { source: 'node-1', target: 'node-3' },\n        { source: 'node-2', target: 'node-3' },\n      ],\n    },\n    node: {\n      style: { fill: '#7e3feb' },\n      state: {\n        custom: { fill: '#ffa940' },\n      },\n    },\n    edge: {\n      stroke: '#8b9baf',\n      state: {\n        custom: { stroke: '#ffa940' },\n      },\n    },\n    behaviors: [\n      {\n        type: 'lasso-select',\n        key: 'lasso-select',\n        trigger: [],\n        immediately: true,\n      },\n    ],\n    plugins: [{ type: 'grid-line', size: 30 }],\n    animation: true,\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      animation: false,\n      enable: true,\n      enableElements: ['node', 'edge', 'combo'],\n      mode: 'default',\n      state: 'selected',\n    };\n    const optionFolder = gui.addFolder('lassoSelect Options');\n    optionFolder.add(options, 'type').disable(true);\n\n    optionFolder.add(options, 'state', ['active', 'selected', 'custom']);\n    optionFolder.add(options, 'mode', ['union', 'intersect', 'diff', 'default']);\n    // .onChange((e) => {\n    //   immediately.show(e === 'default');\n    // });\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.updateBehavior({\n        key: 'lasso-select',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### style\n\n| 属性              | 描述               | 类型                                     | 默认值    |\n| ----------------- | ------------------ | ---------------------------------------- | --------- |\n| cursor            | 鼠标样式           | string                                   |           |\n| fill              | 填充颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| fillOpacity       | 填充透明度         | number \\| string                         | 0.1       |\n| isBillboard       | 是否启用公告牌模式 | boolean                                  |           |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                  |           |\n| lineCap           | 线段端点样式       | `butt` \\| `round` \\| `square`            |           |\n| lineDash          | 虚线配置           | number \\| string \\| (string \\| number)[] |           |\n| lineDashOffset    | 虚线偏移量         | number                                   |           |\n| lineJoin          | 线段连接处样式     | `miter` \\| `round` \\| `bevel`            |           |\n| lineWidth         | 线宽度             | number \\| string                         | 1         |\n| opacity           | 整体透明度         | number \\| string                         |           |\n| radius            | 矩形圆角半径       | number \\| string \\| number[]             |           |\n| shadowBlur        | 阴影模糊程度       | number                                   |           |\n| shadowColor       | 阴影颜色           | string                                   |           |\n| shadowOffsetX     | 阴影 X 方向偏移    | number                                   |           |\n| shadowOffsetY     | 阴影 Y 方向偏移    | number                                   |           |\n| stroke            | 描边颜色           | string \\| Pattern \\| null                | `#1677FF` |\n| strokeOpacity     | 描边透明度         | number \\| string                         |           |\n| visibility        | 可见性             | `visible` \\| `hidden`                    |           |\n| zIndex            | 渲染层级           | number                                   | 2         |\n\n**示例**：\n\n```js\nconst graph = new Graph({\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n```\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 100 } },\n      { id: 'node-2', style: { x: 360, y: 100 } },\n      { id: 'node-3', style: { x: 280, y: 220 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-1', target: 'node-3' },\n      { source: 'node-2', target: 'node-3' },\n    ],\n  },\n  node: {\n    style: { fill: '#7e3feb' },\n  },\n  edge: {\n    stroke: '#8b9baf',\n  },\n  behaviors: [\n    {\n      type: 'lasso-select',\n      key: 'lasso-select',\n      trigger: [],\n      immediately: true,\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2], // 虚线外框\n        // rgb超级炫彩框框\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n  plugins: [{ type: 'grid-line', size: 30 }],\n  animation: true,\n});\n\ngraph.render();\n```\n\n### trigger\n\n按下该快捷键配合鼠标点击进行框选，若设为**空数组**时则表示鼠标点击进行框选，不需要按下其他按键配合。\n\n注意，`trigger` 设置为 `['drag']` 时会导致 `drag-canvas` 行为失效。两者不可同时配置。\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 200, y: 250 } },\n      { id: 'node-2', style: { x: 250, y: 200 } },\n      { id: 'node-3', style: { x: 300, y: 250 } },\n      { id: 'node-4', style: { x: 250, y: 300 } },\n    ],\n    edges: [\n      { source: 'node-1', target: 'node-2' },\n      { source: 'node-2', target: 'node-3' },\n      { source: 'node-3', target: 'node-4' },\n      { source: 'node-4', target: 'node-1' },\n    ],\n  },\n  behaviors: [\n    {\n      key: 'lasso-select',\n      type: 'lasso-select',\n      enable: true,\n      animation: false,\n      mode: 'default', // union intersect diff default\n      state: 'selected', // 'active', 'selected', 'inactive', ...\n      trigger: [], // ['Shift', 'Alt', 'Control', 'Drag', 'Meta', ...]\n      style: {\n        width: 0,\n        height: 0,\n        lineWidth: 4,\n        lineDash: [2, 2],\n        fill: 'linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%)',\n        stroke: 'pink',\n        fillOpacity: 0.2,\n        zIndex: 2,\n        pointerEvents: 'none',\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/OptimizeViewportTransform.en.md) -->\n---\ntitle: OptimizeViewportTransform\norder: 13\n---\n\n## Overview\n\nOptimizeViewportTransform is a built-in behavior in G6 used to enhance the performance of large-scale graph behaviors.\n\nThis behavior implements a **selective rendering strategy**, temporarily hiding non-critical visual elements during viewport transformations (such as dragging, zooming, scrolling, etc.) to significantly reduce rendering computation load, improve frame rate, and response speed. After the viewport transformation operation ends, the system automatically restores the visibility of all elements after a set delay to ensure complete visual presentation.\n\nThis behavior is implemented based on the [event system](/en/api/event) by listening to the `GraphEvent.BEFORE_TRANSFORM` and `GraphEvent.AFTER_TRANSFORM` events, precisely capturing the start and end timing of viewport transformations, and dynamically controlling element visibility. Therefore, it must be used in conjunction with viewport operation behaviors (such as `drag-canvas`, `zoom-canvas`, or `scroll-canvas`) to be effective.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Smooth behavior of large-scale graphs (thousands of nodes/edges)\n- Performance-sensitive application scenarios\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // Specify an identifier for the behavior for dynamic updates\n      debounce: 300, // Set a longer debounce time\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option   | Description                                                                                                          | Type                                   | Default                       | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | -------- |\n| type     | Behavior type name                                                                                                   | string                                 | `optimize-viewport-transform` | ✓        |\n| enable   | Whether to enable this behavior                                                                                      | boolean \\| ((event: Event) => boolean) | true                          |          |\n| debounce | How long after the operation ends to restore the visibility of all elements (milliseconds)                           | number                                 | 200                           |          |\n| shapes   | Specify the graphical elements that should remain visible during canvas operations, [configuration options](#shapes) | function                               | `(type) => type === 'node'`   |          |\n\n### Shapes\n\n`shapes` is used to specify the graphical elements that need to remain visible during canvas operations. By default, nodes are always visible, while edges and combos are temporarily hidden during canvas operations to improve performance.\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // Dynamically decide whether to remain visible based on element type and graphical object\n    if (type === 'node') return true; // All nodes remain visible\n    if (type === 'edge' && shape.get('importante')) return true; // Important edges remain visible\n    return false; // Other graphics are hidden\n  };\n}\n```\n\n[Example](#keep-specific-elements-visible)\n\n## Code Examples\n\n### Basic Optimization Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### Custom Debounce Time\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // Set a longer debounce time, restoring visibility of all elements 0.5 seconds after the operation stops\n    },\n  ],\n});\n```\n\n### Keep Specific Elements Visible\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 Try dragging the canvas to see the effect\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Enable/Disable Optimization Based on Graph Element Count\n\nYou can dynamically decide whether to enable optimization based on the number of graph elements:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // Enable optimization when exceeding 500 elements\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. When should this behavior be used?\n\nWhen the graph contains a large number of nodes and edges (usually more than 500 elements), using this behavior can significantly improve operational smoothness. It is especially useful in environments with high performance requirements or limited hardware performance.\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/OptimizeViewportTransform.zh.md) -->\n---\ntitle: 优化视口变换 OptimizeViewportTransform\norder: 13\n---\n\n## 概述\n\nOptimizeViewportTransform 是 G6 中用于提升大规模图表交互性能的内置交互。\n\n该交互通过实现**选择性渲染策略**，在视口变换过程中（即用户进行拖拽、缩放、滚动等操作时）临时隐藏非关键视觉元素，从而显著降低渲染计算负载，提高帧率和响应速度。当视口变换操作结束后，系统会在设定的延迟时间后自动恢复所有元素的可见性，确保完整的视觉呈现。\n\n此交互基于 [事件系统](/api/event) 实现，通过监听 `GraphEvent.BEFORE_TRANSFORM` 和 `GraphEvent.AFTER_TRANSFORM` 事件，精确捕捉视口变换的开始和结束时机，进而执行元素可见性的动态控制。因此，必须与视口操作类交互（如 `drag-canvas`、`zoom-canvas` 或 `scroll-canvas`）配合使用才能发挥作用。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 大规模图表（上千节点/边）的流畅交互\n- 性能敏感的应用场景\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['optimize-viewport-transform'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'optimize-viewport-transform',\n      key: 'optimize-viewport-transform-1', // 为交互指定标识符，方便动态更新\n      debounce: 300, // 设置更长的防抖时间\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项   | 说明                                                          | 类型                                   | 默认值                        | 必选 |\n| -------- | ------------------------------------------------------------- | -------------------------------------- | ----------------------------- | ---- |\n| type     | 交互类型名称                                                  | string                                 | `optimize-viewport-transform` | ✓    |\n| enable   | 是否启用该交互                                                | boolean \\| ((event: Event) => boolean) | true                          |      |\n| debounce | 操作结束后多长时间恢复显示所有元素（毫秒）                    | number                                 | 200                           |      |\n| shapes   | 指定在操作画布过程中始终保持可见的图形元素，[配置项](#shapes) | function                               | `(type) => type === 'node'`   |      |\n\n### Shapes\n\n`shapes` 用于指定在画布操作过程中需要保持可见的图形元素。默认情况下，节点始终可见，而边和组合在操作画布时会被临时隐藏以提升性能。\n\n```javascript\n{\n  shapes: (type, shape) => {\n    // 根据元素类型和图形对象动态决定是否保持可见\n    if (type === 'node') return true; // 所有节点保持可见\n    if (type === 'edge' && shape.get('importante')) return true; // 重要的边保持可见\n    return false; // 其他图形隐藏\n  };\n}\n```\n\n[示例](#保持特定元素可见)\n\n## 代码示例\n\n### 基础优化功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['drag-canvas', 'zoom-canvas', 'optimize-viewport-transform'],\n});\n```\n\n### 自定义防抖时间\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      debounce: 500, // 设置更长的防抖时间，在操作停止后0.5秒才恢复显示所有元素\n    },\n  ],\n});\n```\n\n### 保持特定元素可见\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n```\n\n> 👇 试试拖拽一下画布，看看效果吧\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    style: {\n      labelText: 'Drag Canvas!',\n    },\n  },\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'optimize-viewport-transform',\n      shapes: (type, shape) => {\n        if (type === 'node' && shape.className === 'key') return true;\n        return false;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 根据图表元素数量动态启用/禁用优化\n\n可以根据图表元素数量动态决定是否启用优化：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    'zoom-canvas',\n    function () {\n      // 超出500个元素时启用优化\n      const enable = graph.getNodeData().length + graph.getEdgeData().length > 500;\n      return {\n        type: 'optimize-viewport-transform',\n        key: 'optimize-behavior',\n        enable,\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 什么情况下应该使用此交互？\n\n当图表包含大量节点和边（通常超过500个元素）时，使用此交互可以显著提升操作流畅度。在性能要求高或硬件性能有限的环境中尤其有用。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  node: {\n    style: {\n      labelText: (datum) => datum.id,\n    },\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'scroll-canvas', 'optimize-viewport-transform'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/overview.en.md) -->\n---\ntitle: Behavior Overview\norder: 0\n---\n\n## What is Behavior\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nBehavior refers to the interactive operations between users and chart elements, such as dragging the canvas, selecting nodes, zooming the view, etc. Good behavior design allows users to explore and understand graph data more intuitively. **Proper configuration of behaviors is a key step in building efficient and usable charts**.\n\n### Changes in G6 5.0 Behavior System\n\nG6 5.0 removed the concept of \"Behavior Mode\" (Mode), and directly lists the required behavior behaviors in `behaviors`, simplifying the configuration. This makes behavior configuration more intuitive and easier to get started with.\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## Built-in Behaviors\n\nG6 provides a variety of built-in behaviors that are **ready to use without registration**:\n\n| Category            | Behavior Name                                                                  | Registration Type             | Function Description                                         |\n| ------------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------------------------------ |\n| Navigation          |                                                                                |                               |                                                              |\n|                     | [Drag Canvas](/en/manual/behavior/drag-canvas)                                 | `drag-canvas`                 | Drag the entire canvas view                                  |\n|                     | [Zoom Canvas](/en/manual/behavior/zoom-canvas)                                 | `zoom-canvas`                 | Zoom the canvas view                                         |\n|                     | [Scroll Canvas](/en/manual/behavior/scroll-canvas)                             | `scroll-canvas`               | Scroll the canvas using the wheel                            |\n|                     | [Optimize Viewport Transform](/en/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | Optimize view transform performance                          |\n| Selection           |                                                                                |                               |                                                              |\n|                     | [Click Select](/en/manual/behavior/click-select)                               | `click-select`                | Click to select graph elements                               |\n|                     | [Brush Select](/en/manual/behavior/brush-select)                               | `brush-select`                | Select elements by dragging a rectangular area               |\n|                     | [Lasso Select](/en/manual/behavior/lasso-select)                               | `lasso-select`                | Freely draw an area to select elements                       |\n| Editing             |                                                                                |                               |                                                              |\n|                     | [Create Edge](/en/manual/behavior/create-edge)                                 | `create-edge`                 | Interactively create new edges                               |\n|                     | [Drag Element](/en/manual/behavior/drag-element)                               | `drag-element`                | Drag nodes or combos                                         |\n|                     | [Force-directed Drag](/en/manual/behavior/drag-element-force)                  | `drag-element-force`          | Drag nodes in force-directed layout                          |\n| Data Exploration    |                                                                                |                               |                                                              |\n|                     | [Collapse/Expand](/en/manual/behavior/collapse-expand)                         | `collapse-expand`             | Expand or collapse subtree nodes                             |\n|                     | [Focus Element](/en/manual/behavior/focus-element)                             | `focus-element`               | Focus on specific elements and automatically adjust the view |\n|                     | [Hover Activate](/en/manual/behavior/hover-activate)                           | `hover-activate`              | Highlight elements when hovering                             |\n| Visual Optimization |                                                                                |                               |                                                              |\n|                     | [Fix Element Size](/en/manual/behavior/fix-element-size)                       | `fix-element-size`            | Fix the element size to a specified value                    |\n|                     | [Auto-adapt Label](/en/manual/behavior/auto-adapt-label)                       | `auto-adapt-label`            | Automatically adjust label position                          |\n\nFor detailed configuration of each behavior, refer to the [Built-in Behavior Documentation](/en/manual/behavior/drag-canvas).\n\n:::warning{title=Behavior Compatibility}\nSome behaviors may overlap in triggering mechanisms, such as `brush-select` and `drag-canvas` both using mouse dragging. In such cases, you can avoid conflicts by modifying the trigger key (e.g., hold `Shift` to drag and select).\n:::\n\n## Custom Behaviors\n\nWhen built-in behaviors cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend by inheriting built-in behaviors\n- Create entirely new behavior behaviors\n\nUnlike built-in behaviors, **custom behaviors need to be registered before use**. For detailed tutorials, refer to the [Custom Behavior](/en/manual/behavior/custom-behavior) documentation.\n\n## Configuration and Usage\n\n### Basic Configuration\n\nThe simplest way is to directly specify the required behaviors through the `behaviors` array when initializing the graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### Configure Behavior Parameters\n\nFor behaviors that require custom parameters, you can configure properties using the `object` form:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // Configure sensitivity\n      key: 'zoom-behavior', // Specify a key for the behavior for subsequent updates\n    },\n  ],\n});\n```\n\n### Dynamically Update Behaviors\n\nG6 supports dynamically managing behavior behaviors during the runtime of the graph instance to meet complex behavior needs:\n\nYou can adjust behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method:\n\n```javascript\n// Add new behavior\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// Remove behavior\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\nYou can update the configuration of behaviors using the [updateBehavior](/en/api/behavior#graphupdatebehaviorbehavior) method:\n\n```javascript\n// Update a single behavior\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // Disable the behavior\n});\n```\n\n:::warning{title=Note}\nWhen using the `updateBehavior` method, you need to specify a unique `key` for the behavior during initialization.\n:::\n\n### Uninstall Behaviors\n\nYou can also uninstall behaviors using the [setBehaviors](/en/api/behavior#graphsetbehaviorsbehaviors) method by setting the behavior configuration list to empty:\n\n```javascript\ngraph.setBehaviors([]);\n```\n\nFor more behavior-related APIs, refer to the [Behavior API Documentation](/en/api/behavior).\n\n## Behavior and Events\n\nBehaviors are essentially implemented through event listening and response. Although built-in behaviors have encapsulated common behavior behaviors, you can also directly implement custom behavior logic through the event API.\n\n### Event Listening Example\n\n```javascript\n// Use event constants (recommended)\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// Listen for node clicks\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// Listen for edge hover\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\nThe event system is the foundation for implementing behaviors. Mastering the event API is crucial for understanding and extending behavior behaviors. For more event-related information, refer to the [Event Documentation](/en/api/event).\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/overview.zh.md) -->\n---\ntitle: 交互总览\norder: 0\n---\n\n## 什么是交互\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n交互(Behavior)是指用户与图表元素之间的互动操作，如拖拽画布、选择节点、缩放视图等。良好的交互设计能让用户更直观地探索和理解图数据。**合理配置交互是构建高效可用图表的关键环节**。\n\n### G6 5.0 交互系统变化\n\nG6 5.0 移除了 \"交互模式\"(Mode) 概念，直接在 `behaviors` 中列出需要的交互行为，简化了配置方式。这使得交互配置更加直观，上手更加简单。\n\n```javascript {4}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n## 内置交互\n\nG6 提供了多种开箱即用的内置交互，**无需注册，直接配置即可使用**：\n\n| 分类     | 交互名称                                                     | 注册类型                      | 功能描述                   |\n| -------- | ------------------------------------------------------------ | ----------------------------- | -------------------------- |\n| 导航     |                                                              |                               |                            |\n|          | [拖拽画布](/manual/behavior/drag-canvas)                     | `drag-canvas`                 | 拖动整个画布视图           |\n|          | [缩放画布](/manual/behavior/zoom-canvas)                     | `zoom-canvas`                 | 缩放画布视图               |\n|          | [滚动画布](/manual/behavior/scroll-canvas)                   | `scroll-canvas`               | 使用滚轮滚动画布           |\n|          | [优化视口变换](/manual/behavior/optimize-viewport-transform) | `optimize-viewport-transform` | 优化视图变换性能           |\n| 选择     |                                                              |                               |                            |\n|          | [点击选择](/manual/behavior/click-select)                    | `click-select`                | 点击选择图元素             |\n|          | [框选](/manual/behavior/brush-select)                        | `brush-select`                | 通过拖拽矩形区域选择元素   |\n|          | [套索选择](/manual/behavior/lasso-select)                    | `lasso-select`                | 自由绘制区域选择元素       |\n| 编辑     |                                                              |                               |                            |\n|          | [创建边](/manual/behavior/create-edge)                       | `create-edge`                 | 交互式创建新的边           |\n|          | [拖拽元素](/manual/behavior/drag-element)                    | `drag-element`                | 拖动节点或组合             |\n|          | [力导向拖拽](/manual/behavior/drag-element-force)            | `drag-element-force`          | 力导向布局中拖动节点       |\n| 数据探索 |                                                              |                               |                            |\n|          | [折叠/展开](/manual/behavior/collapse-expand)                | `collapse-expand`             | 展开或收起子树节点         |\n|          | [聚焦元素](/manual/behavior/focus-element)                   | `focus-element`               | 聚焦特定元素，自动调整视图 |\n|          | [悬停激活](/manual/behavior/hover-activate)                  | `hover-activate`              | 鼠标悬停时高亮元素         |\n| 视觉优化 |                                                              |                               |                            |\n|          | [固定元素大小](/manual/behavior/fix-element-size)            | `fix-element-size`            | 将元素大小固定为指定值     |\n|          | [自适应标签](/manual/behavior/auto-adapt-label)              | `auto-adapt-label`            | 自动调整标签位置           |\n\n各交互的详细配置可参考 [内置交互文档](/manual/behavior/drag-canvas)。\n\n:::warning{title=交互兼容性}\n某些交互在触发机制上可能存在重叠，如 `brush-select` 和 `drag-canvas` 都使用鼠标拖拽。这种情况下可以通过修改触发按键（如按住 `Shift` 拖拽选择）来避免冲突。\n:::\n\n## 自定义交互\n\n当内置交互无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置交互进行扩展\n- 创建全新的交互行为\n\n与内置交互不同，**自定义交互需要先注册后使用**。详细教程请参考 [自定义交互](/manual/behavior/custom-behavior) 文档。\n\n## 配置和使用\n\n### 基本配置\n\n最简单的方式是在图实例初始化时，通过 `behaviors` 数组直接指定需要的交互：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'click-select'],\n});\n```\n\n### 配置交互参数\n\n对于需要自定义参数的交互，可以使用 `object` 的形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    'drag-canvas',\n    {\n      type: 'zoom-canvas',\n      sensitivity: 1.5, // 配置灵敏度\n      key: 'zoom-behavior', // 为交互指定key，便于后续更新\n    },\n  ],\n});\n```\n\n### 动态更新交互\n\nG6 支持在图实例运行期间动态管理交互行为，满足复杂交互需求：\n\n可以通过 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法调整交互：\n\n```javascript\n// 添加新交互\ngraph.setBehaviors((behaviors) => [...behaviors, 'lasso-select']);\n\n// 移除交互\ngraph.setBehaviors((behaviors) => behaviors.filter((b) => b !== 'click-select'));\n```\n\n可以使用 [updateBehavior](/api/behavior#graphupdatebehaviorbehavior) 方法更新交互的配置：\n\n```javascript\n// 更新单个交互\ngraph.updateBehavior({\n  key: 'zoom-behavior',\n  sensitivity: 2,\n  enable: false, // 禁用该交互\n});\n```\n\n:::warning{title=注意}\n使用`updateBehavior`方法时，需要在初始化时为交互指定唯一的`key`。\n:::\n\n### 卸载交互\n\n使用 [setBehaviors](/api/behavior#graphsetbehaviorsbehaviors) 方法同样可以卸载交互，将交互配置列表置为空即可：\n\n```javascript\ngraph.setBehaviors([]);\n```\n\n更多与交互相关的 API 请参考 [交互 API 文档](/api/behavior)。\n\n## 交互与事件\n\n交互本质上是通过事件监听和响应来实现的。虽然内置交互已经封装了常见的交互行为，但你也可以通过事件 API 直接实现自定义交互逻辑。\n\n### 事件监听示例\n\n```javascript\n// 使用事件常量（推荐）\nimport { NodeEvent, EdgeEvent } from '@antv/g6';\n\n// 监听节点点击\ngraph.on(NodeEvent.CLICK, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'selected');\n});\n\n// 监听边悬停\ngraph.on(EdgeEvent.POINTER_OVER, (evt) => {\n  const { target } = evt;\n  graph.setElementState(target.id, 'highlight');\n});\n```\n\n事件系统是实现交互的基础，掌握事件 API 对于理解和扩展交互行为至关重要。更多事件相关信息，请参考 [事件文档](/api/event)。\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ScrollCanvas.en.md) -->\n---\ntitle: ScrollCanvas\norder: 14\n---\n\n## Overview\n\nScrollCanvas is a built-in behavior in G6 used to implement the canvas scrolling feature, supporting panning the canvas using the mouse wheel or keyboard arrow keys. This interaction is particularly useful for browsing larger charts, allowing users to explore different areas of the chart without changing the zoom level.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large chart content that exceeds the visible area\n- Exploring different parts of the graph while maintaining the current zoom level\n- Precisely adjusting the view position, especially when precise scrolling is needed in one-dimensional directions\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n      direction: 'y', // Allow only vertical scrolling\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                         | Type                                                                                                                                                                                          | Default                          | Required |\n| -------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | -------- |\n| type           | Behavior type name                                                                  | string                                                                                                                                                                                        | `scroll-canvas`                  | ✓        |\n| enable         | Whether to enable this behavior                                                     | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                             |          |\n| direction      | Allowed scrolling direction, [configuration options](#direction)                    | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (no direction limit) |          |\n| range          | Scrollable viewport range (in viewport size units), [configuration options](#range) | number \\| number[]                                                                                                                                                                            | 1                                |          |\n| sensitivity    | Scrolling sensitivity, the larger the value, the faster the scrolling               | number                                                                                                                                                                                        | 1                                |          |\n| trigger        | Keyboard shortcuts to trigger scrolling, [configuration options](#trigger)          | object                                                                                                                                                                                        | -                                |          |\n| onFinish       | Callback function when scrolling is finished                                        | () => void                                                                                                                                                                                    | -                                |          |\n| preventDefault | Whether to prevent the browser's default event                                      | boolean                                                                                                                                                                                       | true                             |          |\n\n### Direction\n\n`direction` is used to limit the scrolling direction:\n\n- Not set or set to `undefined`: Allow scrolling in any direction\n- Set to `'x'`: Allow only horizontal scrolling\n- Set to `'y'`: Allow only vertical scrolling\n\nThis is useful in specific visualization scenarios, such as in timeline charts where only horizontal scrolling may be needed.\n\n### Range\n\n`range` is used to control the scrollable range of the canvas:\n\n- Set to a single number: Use the same value for all four directions\n- Set to an array: Specify the range for [top, right, bottom, left] directions respectively\n\nFor example:\n\n```javascript\nrange: 2; // Can scroll 2 viewport distances in any direction\nrange: [1, 2, 1, 2]; // Can scroll 1 viewport up and down, 2 viewports left and right\n```\n\nThe value range for each direction is [0, Infinity], where 0 means no scrolling, and Infinity means unlimited scrolling.\n\n### Trigger\n\n`trigger` allows you to configure keyboard arrow keys to control canvas scrolling:\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // Shortcut key for scrolling up\n    down: ['ArrowDown'], // Shortcut key for scrolling down\n    left: ['ArrowLeft'], // Shortcut key for scrolling left\n    right: ['ArrowRight'] // Shortcut key for scrolling right\n  }\n}\n```\n\nYou can also configure combination keys:\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + Up Arrow\n    down: ['Control', 'ArrowDown'], // Ctrl + Down Arrow\n    left: ['Control', 'ArrowLeft'], // Ctrl + Left Arrow\n    right: ['Control', 'ArrowRight'] // Ctrl + Right Arrow\n  }\n}\n```\n\n## Code Examples\n\n### Basic Scrolling Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### Allow Only Horizontal Scrolling\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // Allow only horizontal scrolling\n    },\n  ],\n});\n```\n\n### Custom Scrolling Sensitivity and Range\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // Increase scrolling sensitivity\n      range: [0.5, 2, 0.5, 2], // Smaller limits up and down, larger limits left and right\n    },\n  ],\n});\n```\n\n### Control Scrolling with Keyboard Arrow Keys\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What is the difference between ScrollCanvas and ZoomCanvas?\n\n- `ScrollCanvas` is used to pan the canvas without changing the zoom level\n- `ZoomCanvas` is used to zoom the canvas, changing the view's zoom level\n\nThey are often used together to provide complete canvas navigation functionality:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ScrollCanvas.zh.md) -->\n---\ntitle: 滚动画布 ScrollCanvas\norder: 14\n---\n\n## 概述\n\nScrollCanvas 是 G6 中用于实现画布滚动功能的内置交互，支持通过鼠标滚轮或键盘方向键平移画布。这种交互方式对于浏览较大的图表特别有用，能让用户在不改变缩放比例的情况下探索图表的不同区域。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览超出可视区域的大型图表内容\n- 在保持当前缩放比例的情况下探索图的不同部分\n- 精确调整查看位置，尤其是在一维方向上需要精确滚动时\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/scroll-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['scroll-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      key: 'scroll-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n      direction: 'y', // 只允许垂直方向滚动\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                 | 类型                                                                                                                                                                                          | 默认值                   | 必选 |\n| -------------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ---- |\n| type           | 交互类型名称                                         | string                                                                                                                                                                                        | `scroll-canvas`          | ✓    |\n| enable         | 是否启用该交互                                       | boolean \\| ((event: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) \\| [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent)) => boolean) | true                     |      |\n| direction      | 允许的滚动方向，[配置项](#direction)                 | `'x'` \\| `'y'` \\| `undefined`                                                                                                                                                                 | `undefined` (不限制方向) |      |\n| range          | 可滚动的视口范围(以视口大小为单位)，[配置项](#range) | number \\| number[]                                                                                                                                                                            | 1                        |      |\n| sensitivity    | 滚动灵敏度，值越大滚动速度越快                       | number                                                                                                                                                                                        | 1                        |      |\n| trigger        | 触发滚动的键盘快捷键，[配置项](#trigger)             | object                                                                                                                                                                                        | -                        |      |\n| onFinish       | 滚动完成时的回调函数                                 | () => void                                                                                                                                                                                    | -                        |      |\n| preventDefault | 是否阻止浏览器默认事件                               | boolean                                                                                                                                                                                       | true                     |      |\n\n### Direction\n\n`direction` 用于限制滚动的方向：\n\n- 不设置或设为 `undefined`：允许在任意方向滚动\n- 设为 `'x'`：只允许水平方向滚动\n- 设为 `'y'`：只允许垂直方向滚动\n\n这在特定的可视化场景下很有用，例如在时间轴图表中可能只需要水平滚动。\n\n### Range\n\n`range` 用于控制画布可滚动的范围：\n\n- 设置为单个数字：四个方向使用相同的值\n- 设置为数组：分别指定 [上, 右, 下, 左] 四个方向的范围\n\n例如：\n\n```javascript\nrange: 2; // 在任何方向上都可以滚动2个视口的距离\nrange: [1, 2, 1, 2]; // 上下方向可滚动1个视口，左右方向可滚动2个视口\n```\n\n每个方向的取值范围是 [0, Infinity]，0表示不能滚动，Infinity表示无限滚动。\n\n### Trigger\n\n`trigger` 允许你配置键盘方向键来控制画布滚动：\n\n```javascript\n{\n  trigger: {\n    up: ['ArrowUp'],     // 向上滚动的快捷键\n    down: ['ArrowDown'], // 向下滚动的快捷键\n    left: ['ArrowLeft'], // 向左滚动的快捷键\n    right: ['ArrowRight'] // 向右滚动的快捷键\n  }\n}\n```\n\n你也可以配置组合键：\n\n```javascript\n{\n  trigger: {\n    up: ['Control', 'ArrowUp'],     // Ctrl + 上箭头\n    down: ['Control', 'ArrowDown'], // Ctrl + 下箭头\n    left: ['Control', 'ArrowLeft'], // Ctrl + 左箭头\n    right: ['Control', 'ArrowRight'] // Ctrl + 右箭头\n  }\n}\n```\n\n## 代码示例\n\n### 基础滚动功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['scroll-canvas'],\n});\n```\n\n### 只允许水平滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      direction: 'x', // 只允许水平滚动\n    },\n  ],\n});\n```\n\n### 自定义滚动灵敏度和范围\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      sensitivity: 1.8, // 提高滚动灵敏度\n      range: [0.5, 2, 0.5, 2], // 上下方向限制较小，左右方向限制较大\n    },\n  ],\n});\n```\n\n### 使用键盘方向键控制滚动\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'scroll-canvas',\n      trigger: {\n        up: ['ArrowUp'],\n        down: ['ArrowDown'],\n        left: ['ArrowLeft'],\n        right: ['ArrowRight'],\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. ScrollCanvas 和 ZoomCanvas 有什么区别？\n\n- `ScrollCanvas` 用于平移画布，不改变缩放比例\n- `ZoomCanvas` 用于缩放画布，改变视图的缩放比例\n\n两者常结合使用，提供完整的画布导航功能：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas', 'scroll-canvas'],\n});\n```\n\n### 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['scroll-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ZoomCanvas.en.md) -->\n---\ntitle: ZoomCanvas\nordeR: 15\n---\n\n## Overview\n\nZoomCanvas is a built-in behavior in G6 used to implement the canvas zooming feature, supporting zooming in and out of the canvas using the mouse wheel or keyboard shortcuts. This is one of the most commonly used interactions in graph visualization, helping users view both the overall structure and local details of the graph.\n\n## Use Cases\n\nThis behavior is mainly used for:\n\n- Browsing large-scale graph data, freely switching between the whole and details\n- Focusing on specific areas for detailed analysis\n\n## Online Experience\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## Basic Usage\n\nAdd this behavior in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string form. This method is simple but only supports default configuration and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and can dynamically update the configuration at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // Specify an identifier for the behavior for dynamic updates\n      sensitivity: 1.5, // Set sensitivity\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option         | Description                                                                                            | Type                                                                                | Default             | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------------- | -------- |\n| type           | Behavior type name                                                                                     | string                                                                              | `zoom-canvas`       | ✓        |\n| animation      | Zoom animation effect settings                                                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |          |\n| enable         | Whether to enable this behavior                                                                        | boolean \\| ((event: Event) => boolean)                                              | true                |          |\n| origin         | Zoom center point (viewport coordinates)                                                               | [Point](/api/viewport#point)                                                        | -                   |          |\n| onFinish       | Callback function when zooming is finished                                                             | () => void                                                                          | -                   |          |\n| preventDefault | Whether to prevent the browser's default event                                                         | boolean                                                                             | true                |          |\n| sensitivity    | Zoom sensitivity, the larger the value, the faster the zoom                                            | number                                                                              | 1                   |          |\n| trigger        | How to trigger zooming, supports mouse wheel and keyboard shortcuts, [configuration options](#trigger) | string[] \\| object                                                                  | -                   |          |\n\n### Trigger\n\n`trigger` has two usage methods, suitable for different scenarios:\n\n#### Method 1: Modifier keys combined with the mouse wheel\n\nIf you want to trigger zooming only when certain keys are pressed while scrolling the mouse wheel, you can configure it like this:\n\n```javascript\n{\n  trigger: ['Control']; // Hold down the Control key and scroll the mouse wheel to zoom\n}\n```\n\nCommon modifier keys include:\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> Not sure what value corresponds to a keyboard key? Refer to [MDN Key Values](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).\n\n#### Method 2: Pure keyboard shortcuts\n\nIf you want to control zooming entirely using the keyboard, you can set up key combinations:\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // Zoom in shortcut\n    zoomOut: ['Control', '-'], // Zoom out shortcut\n    reset: ['Control', '0']    // Reset zoom ratio shortcut\n  }\n}\n```\n\n## Code Examples\n\n### Basic Zoom Functionality\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### Custom Zoom Center\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n### Custom Zoom Sensitivity\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n    },\n  ],\n});\n```\n\n### Zoom with Shift + Mouse Wheel\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // Hold down the Shift key and scroll to zoom\n    },\n  ],\n});\n```\n\n### Control Zoom with Keyboard Shortcuts\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = to zoom in\n        zoomOut: ['Control', '-'], // Ctrl + - to zoom out\n        reset: ['Control', '0'], // Ctrl + 0 to reset\n      },\n    },\n  ],\n});\n```\n\n### Supports pinch-to-zoom on mobile devices\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // Other configurations for the PC side...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // Lower sensitivity for smoother zoom changes\n        origin: this.getCanvasCenter(), // Zoom with the viewport center as the origin\n      };\n    },\n  ],\n});\n```\n\n## FAQ\n\n### 1. What if the canvas zoom exceeds the expected range?\n\nTo avoid excessive zooming in or out, you can set zoom limits:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  zoomRange: [0.5, 3], // Allow zooming out to 50% and zooming in to 300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. How to use it with other interactions?\n\nZooming and dragging are common combinations for a complete navigation experience:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. Conflicts when using two-finger touchpad input and scroll-canvas simultaneously\n\nOn a touchpad, both two-finger swipe (for scrolling) and pinch (for zooming) gestures are often interpreted as `wheel` events.\n\nBecause both `zoom-canvas` and `scroll-canvas` respond to `wheel` events by default, using them together can cause conflicts, such as a single gesture triggering both scrolling and zooming.\n\nYou can resolve this by checking the `event.ctrlKey` property. On most platforms, a pinch gesture sets `event.ctrlKey` to `true`, while a swipe does not. This allows you to conditionally enable `zoom-canvas` only for pinch gestures.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // When ctrlKey is true, it performs a two-finger pinch or spread operation; when false, it performs a two-finger swipe operation.\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## Practical Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Behavior Skill (packages/site/docs/manual/behavior/ZoomCanvas.zh.md) -->\n---\ntitle: 缩放画布 ZoomCanvas\nordeR: 15\n---\n\n## 概述\n\nZoomCanvas 是 G6 中用于实现画布缩放功能的内置交互，支持通过鼠标滚轮或键盘快捷键调整画布缩放比例。这是图可视化中最常用的交互之一，能帮助用户查看图的整体结构和局部细节。\n\n## 使用场景\n\n这一交互主要用于：\n\n- 浏览大规模图数据，在整体与细节之间自由切换\n- 聚焦到特定区域进行详细分析\n\n## 在线体验\n\n<embed src=\"@/common/api/behaviors/zoom-canvas.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一交互：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['zoom-canvas'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      key: 'zoom-canvas-1', // 为交互指定标识符，方便动态更新\n      sensitivity: 1.5, // 设置灵敏度\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 配置项         | 说明                                                     | 类型                                                                                | 默认值              | 必选 |\n| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------- | ---- |\n| type           | 交互类型名称                                             | string                                                                              | `zoom-canvas`       | ✓    |\n| animation      | 缩放动画效果设置                                         | [ViewportAnimationEffectTiming](/manual/graph/option#viewportanimationeffecttiming) | `{ duration: 200 }` |      |\n| enable         | 是否启用该交互                                           | boolean \\| ((event: Event) => boolean)                                              | true                |      |\n| origin         | 缩放中心点(视口坐标)                                     | [Point](/api/viewport#point)                                                        | -                   |      |\n| onFinish       | 缩放完成时的回调函数                                     | () => void                                                                          | -                   |      |\n| preventDefault | 是否阻止浏览器默认事件                                   | boolean                                                                             | true                |      |\n| sensitivity    | 缩放灵敏度，值越大缩放速度越快                           | number                                                                              | 1                   |      |\n| trigger        | 触发缩放的方式，支持滚轮和键盘快捷键，[配置项](#trigger) | string[] \\| object                                                                  | -                   |      |\n\n### Trigger\n\n`trigger`有两种使用方式，分别适用于不同场景：\n\n#### 方式一：与滚轮结合的修饰键\n\n当你希望只有在按下某些键的同时滚动滚轮才触发缩放时，可以这样配置：\n\n```javascript\n{\n  trigger: ['Control']; // 按住 Control 键同时滚动鼠标滚轮才能缩放\n}\n```\n\n常见的修饰键有：\n\n- `Control`\n- `Shift`\n- `Alt`\n\n> 不知道键盘按键对应什么值？请参考 [MDN Key Values](https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values)。\n\n#### 方式二：纯键盘快捷键\n\n当你希望完全使用键盘控制缩放操作时，可以设置组合键：\n\n```javascript\n{\n  trigger: {\n    zoomIn: ['Control', '+'],  // 放大快捷键\n    zoomOut: ['Control', '-'], // 缩小快捷键\n    reset: ['Control', '0']    // 重置缩放比例快捷键\n  }\n}\n```\n\n## 代码示例\n\n### 基础缩放功能\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 自定义缩放中心\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    function () {\n      return {\n        type: 'zoom-canvas',\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n### 自定义缩放灵敏度\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n    },\n  ],\n});\n```\n\n### 使用Shift+滚轮进行缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: ['Shift'], // 按住 Shift 键同时滚动才能缩放\n    },\n  ],\n});\n```\n\n### 使用键盘快捷键控制缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      trigger: {\n        zoomIn: ['Control', '='], // Ctrl + = 放大\n        zoomOut: ['Control', '-'], // Ctrl + - 缩小\n        reset: ['Control', '0'], // Ctrl + 0 重置\n      },\n    },\n  ],\n});\n```\n\n### 支持移动端双指缩放\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: [\n    {\n      type: 'zoom-canvas',\n      // PC 端其他配置...\n    },\n    function () {\n      return {\n        type: 'zoom-canvas',\n        trigger: ['pinch'],\n        sensitivity: 0.8, // 降低灵敏度，缩放变化更平缓\n        origin: this.getCanvasCenter(), // 以视口中心为原点进行缩放\n      };\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 画布缩放超出了预期范围怎么办？\n\n为避免缩放过大或过小，可以设置缩放限制：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  zoomRange: [0.5, 3], // 允许缩小到50%和放大到300%\n  behaviors: ['zoom-canvas'],\n});\n```\n\n### 2. 如何与其他交互结合使用？\n\n缩放与拖拽是常见的组合，实现完整的导航体验：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n```\n\n### 3. 触控板双指操作下，与 scroll-canvas 同时使用时的冲突\n\n在触控板上，双指滑动（用于滚动）和双指捏合（用于缩放）手势通常都会被解析为 `wheel` 事件。\n\n由于 `zoom-canvas` 和 `scroll-canvas` 默认都会响应 `wheel` 事件，当它们同时使用时会产生冲突，例如一个手势会同时触发滚动和缩放。\n\n你可以通过检查 `event.ctrlKey` 属性来解决这个问题。在多数平台上，捏合手势会使 `event.ctrlKey` 为 `true`，而滑动则不会。这允许你有条件地仅为捏合手势启用 `zoom-canvas`。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }],\n  },\n  behaviors: [\n    'scroll-canvas',\n    {\n      key: 'custom-zoom-canvas',\n      type: 'zoom-canvas',\n      enable: (event) => {\n        return event.ctrlKey; // ctrlKey 为 true 时，是双指捏合或扩张操作，false 时是双指滑动操作\n      },\n    },\n  ],\n});\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'grid',\n  },\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }, { id: 'node3' }, { id: 'node4' }, { id: 'node5' }],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node1', target: 'node3' },\n      { source: 'node1', target: 'node4' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n    ],\n  },\n  behaviors: ['zoom-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/contribute.en.md) -->\n---\ntitle: contribute\norder: 14\n---\n\nTo contribute, you need to understand G6's code structure and development workflow. The code repository for G6 is located at: https://github.com/antvis/G6\n\nIf you want to fix a bug or add a new feature, you need to first fork a copy of the code to your repository, then make modifications in your repository, and finally submit a Pull Request (PR) to the G6 repository.\n\n## Project Structure\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 Core Implementation</small>\n          <ul>\n            <li>\n              __tests__\n              <small>Testing and Development Environment</small>\n              <ul>\n                <li>\n                  assets\n                  <small>Test Static Resources</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bugfix Test Case</small>\n                </li>\n                <li>\n                  dataset\n                  <small>Test Dataset</small>\n                </li>\n                <li>\n                  demos\n                  <small>Development Demos</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>Test Snapshots</small>\n                </li>\n                <li>\n                  perf\n                  <small>Performance Test Case</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>Performance Test Reports</small>\n                </li>\n                <li>\n                  unit\n                  <small>Test Cases</small>\n                </li>\n                <li>\n                  utils\n                  <small>Test Utility Functions</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>Animation Executors and Built-in Animations</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>Built-in Interactions</small>   \n                </li>\n                <li>\n                  constants\n                  <small>Constants and Enumeration Values</small>   \n                </li>\n                <li>\n                  elements\n                  <small>Built-in Elements</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>Built-in Combos</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>Built-in Edges</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>Built-in Nodes</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>Composite Shapes</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>Layout References and Encapsulation</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>Built-in Palettes</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>Built-in Plugins</small>   \n                </li>\n                <li>\n                  registry\n                  <small>Registry Module</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph and Core Controller</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification Type Definitions</small>   \n                </li>\n                <li>\n                  themes\n                  <small>Built-in Themes</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>Built-in Data Transformations</small>   \n                </li>\n                <li>\n                  types\n                  <small>Type Definitions</small>   \n                </li>\n                <li>\n                  utils\n                  <small>Utility Functions</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>Export Items</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>Pre-operations</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>Development Environment Vite Configuration</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D Extension</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D Behaviors</small>\n            </li>\n            <li>\n              elements\n              <small>3D Elements</small>\n            </li>\n            <li>\n              plugins\n              <small>3D Plugins</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D Renderer</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React Node Extension</small>\n          <ul>\n            <li>\n              elements\n              <small>React Elements</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph Encapsulation</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>Official Website and Documentation</small>\n          <ul>\n            <li>\n              docs\n              <small>Tutorials and API</small>\n            </li>\n            <li>\n              examples\n              <small>Graph Examples</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>Configuration File</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## Development Process\n\n1. Fork and Pull the Code\n\nFork the G6 repository on Github to your account, then clone it locally.\n\n```bash\n# Navigate to your workspace\ncd /path/to/your/workspace\n\n# Navigate to the G6 directory\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. Install Dependencies\n\n:::warning{title=Warning}\nPlease ensure your local environment meets the following requirements:\n\n- [Node.js](https://nodejs.org/) version >= 18\n- [pnpm](https://pnpm.io/) version >= 8\n\n:::\n\n```bash\n# Enter the G6 code directory\ncd G6\n\n# Install Dependencies\npnpm install\n```\n\n3. Start the Development Environment\n\n```bash\n# Enter the g6 code directory.\ncd ./packages/g6\n\n# Start the development environment\npnpm dev\n```\n\nAt this point, you can access G6's development environment and preview the examples by visiting http://127.0.0.1:8080 in your web browser.\n\n4. Develop New Features or Fix Bugs\n\nSwitch to a development branch:\n\n```bash\ngit checkout -b [branch name]\n```\n\nMake code modifications according to your needs and test locally.\n\n5. Write Test Cases\n\nIn the `packages/g6/__tests__/unit` directory, write test cases to ensure your code behaves as expected.\n\nValidate Your Code with Tests：\n\n```bash\npnpm test\n```\n\n6. Submit a Pull Request (PR)\n\n```bash\n# Stage changes\ngit add .\n\n# Commit Changes\ngit commit -m \"[commit type]: commit message\"\n\n# Push to Your Repository\ngit push\n```\n\nSubmit a Pull Request (PR) to the G6 repository on GitHub.\n\n## Testing and Coverage\n\nG6 utilizes Jest for conducting unit tests, with the test cases situated in the `packages/g6/__tests__/unit` directory.\n\nWe require that all code submissions must pass tests to ensure code quality.\n\nThe coverage rate for the current PR (Pull Request) submission is advised not to fall below the coverage rate of the existing codebase, and it is <text style=\"color: red;\">not to fall below 90%</text>.\n\n### Update Test Snapshots\n\nG6 extends Jest tests and provides the `toMatchSnapshot` assertion for generating and comparing snapshots.\n\nIf the current possible modification affects the generation of some screenshots, it is necessary to check whether there are failed test cases by executing `pnpm test`.\n\nWhen a failed test case is found, the console will print the path of the failed test, as well as the path information of the benchmark screenshot and the current screenshot. You can hold the `Ctrl` or `Command` key and click the path to view the specific test case or screenshot.\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\nIf it is confirmed that this modification is correct, then please manually delete the corresponding benchmark screenshots and regenerate the screenshots:\n\n**Regenerate all screenshots**:\n\n1. Delete all files in the `packages/g6/__tests__/unit/snapshots` directory\n2. Execute `pnpm test`\n\n**Regenerate a single screenshot**:\n\n1. Delete the corresponding file in the `packages/g6/__tests__/snapshots` directory (test cases in the `unit` directory will generate the corresponding directory under `snapshots`)\n2. Execute `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## Code Standards\n\nThe G6 code adheres to the following standards:\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## Commit Conventions\n\nG6 adopts the [Conventional Commits](https://www.conventionalcommits.org/) specification, and the commit message format is as follows:\n\n```\n<type>[optional scope]: <description>\n```\n\nThe type field can be one of the following:\n\n- feat: A new feature\n- fix: A bug fix\n- docs: Documentation update\n- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)\n- refactor: Code change that neither fixes a bug nor adds a feature\n- perf: A code change that improves performance\n- test: Adding missing or correcting existing tests\n- build: Changes that affect the build system or external dependencies\n- ci: Changes to our CI configuration files and scripts\n- chore: Other changes that don't modify src or test files\n- revert: Reverts a previous commit\n\nFor example:\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\nPlease ensure that your commit messages conform to the standards, and try to use English descriptions whenever possible. This helps us better manage the code.\n\n## Pull Request (PR) Standards\n\nAfter completing the above steps, you can submit a PR to the G6 repository. Please ensure that your PR adheres to the following standards:\n\n- A single PR should address only one issue.\n- The title of the PR should be concise and clear.\n- The description of the PR should be clear and detailed. If the changes involve the user interface, please include screenshots.\n- The PR must pass CI (Continuous Integration) checks.\n\n## Code Review\n\nAfter your PR is submitted, we will review your code. Please be patient and await the results of the review. If there are any areas that require modification, we will point them out within the PR.\n\n## Release Process\n\nWe regularly release new versions. If your PR is for a non-urgent bug fix, it will be included in the next release. If your PR addresses an urgent bug fix, we will release a new version as soon as possible.\n\nThis project uses changeset to manage version release, and the specific release process is as follows:\n\n1. Complete related development work\n2. Create a branch from v5 (any name you want)\n3. Run `npm run version` command, fill in the information according to the prompt, and the version number will be updated automatically\n4. Commit the changes to the remote repository\n5. Create a PR on GitHub, add the `publish` label, and merge the branch to v5\n6. After the branch is merged, GitHub Actions will be triggered automatically, and the package will be published to npm\n7. After the release, the Release note needs to be updated. Execute \"pnpm tag\" in the packages/g6\n8. Fill in the tag information on the newly opened Github link. First, select the previous tag, and then select the current tag to obtain the changes. After confirming that there are no issues, release it.\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/contribute.zh.md) -->\n---\ntitle: 参与贡献\norder: 14\n---\n\n要参与贡献，你需要了解 G6 的代码结构和开发流程。G6 的代码仓库地址是：https://github.com/antvis/G6\n\n如果你想要修复一个 bug 或者增加一个新功能，你需要先 fork 一份代码到你的仓库，然后在你的仓库中进行修改，最后提交 PR 到 G6 的仓库。\n\n## 项目结构\n\n<Tree>\n  <ul>\n    <li>\n      packages\n      <ul>\n        <li>\n          g6\n          <small>G6 核心实现</small>\n          <ul>\n            <li>\n              __tests__\n              <small>测试及开发环境</small>\n              <ul>\n                <li>\n                  assets\n                  <small>测试静态资源</small>\n                </li>\n                <li>\n                  bugs\n                  <small>Bug 修复测试用例</small>\n                </li>\n                <li>\n                  dataset\n                  <small>测试数据集</small>\n                </li>\n                <li>\n                  demos\n                  <small>开发示例</small>\n                </li>\n                <li>\n                  snapshots\n                  <small>测试截图</small>\n                </li>\n                <li>\n                  perf\n                  <small>性能测试用例</small>\n                </li>\n                <li>\n                  perf-report\n                  <small>性能测试报告</small>\n                </li>\n                <li>\n                  unit\n                  <small>测试用例</small>\n                </li>\n                <li>\n                  utils\n                  <small>测试工具函数</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              src\n              <ul>\n                <li>\n                  animations\n                  <small>动画执行器及内置动画</small>   \n                </li>\n                <li>\n                  behaviors\n                  <small>内置交互</small>   \n                </li>\n                <li>\n                  constants\n                  <small>常量及枚举值</small>   \n                </li>\n                <li>\n                  elements\n                  <small>内置元素</small>\n                  <ul>\n                    <li>\n                      combos\n                      <small>内置组合</small>\n                    </li>\n                    <li>\n                      edges\n                      <small>内置边</small>\n                    </li>\n                    <li>\n                      nodes\n                      <small>内置节点</small>\n                    </li>\n                    <li>\n                      shapes\n                      <small>复合图形</small>\n                    </li>\n                  </ul>\n                </li>\n                <li>\n                  layouts\n                  <small>布局引用及封装</small>   \n                </li>\n                <li>\n                  palettes\n                  <small>内置色板</small>   \n                </li>\n                <li>\n                  plugins\n                  <small>内置插件</small>   \n                </li>\n                <li>\n                  registry\n                  <small>注册模块</small>   \n                </li>\n                <li>\n                  runtime\n                  <small>Graph 及核心控制器</small>   \n                </li>\n                <li>\n                  spec\n                  <small>Specification 类型定义</small>   \n                </li>\n                <li>\n                  themes\n                  <small>内置主题</small>   \n                </li>\n                <li>\n                  transforms\n                  <small>内置数据转换</small>   \n                </li>\n                <li>\n                  types\n                  <small>类型定义</small>   \n                </li>\n                <li>\n                  utils\n                  <small>工具函数</small>   \n                </li>\n                <li>\n                  exports.ts\n                  <small>导出项</small>   \n                </li>\n                <li>\n                  preset.ts\n                  <small>预操作</small>\n                </li>\n              </ul>\n            </li>\n            <li>\n              vite.config.js\n              <small>开发环境 Vite 配置</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-3d/src\n          <small>3D 扩展</small>\n          <ul>\n            <li>\n              behaviors\n              <small>3D 交互</small>\n            </li>\n            <li>\n              elements\n              <small>3D 元素</small>\n            </li>\n            <li>\n              plugins\n              <small>3D 插件</small>\n            </li>\n            <li>\n              renderer.ts\n              <small>3D 渲染器</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          g6-extension-react/src\n          <small>React 节点扩展</small>\n          <ul>\n            <li>\n              elements\n              <small>React 元素</small>\n            </li>\n            <li>\n              graph\n              <small>React Graph 封装</small>\n            </li>\n          </ul>\n        </li>\n        <li>\n          site\n          <small>官网及文档</small>\n          <ul>\n            <li>\n              docs\n              <small>教程及 API</small>\n            </li>\n            <li>\n              examples\n              <small>图表示例</small>\n            </li>\n            <li>\n              .dumirc.ts\n              <small>配置文件</small>\n            </li>\n          </ul>\n        </li>\n      </ul>\n    </li>\n\n  </ul>\n</Tree>\n\n## 开发流程\n\n1. Fork 并拉取代码\n\n在 Github 中 Fork [G6](https://github.com/antvis/G6) 到你的仓库，并拉取到本地。\n\n```bash\n# 进入你的工作目录\ncd /path/to/your/workspace\n\n# 克隆 G6 代码\ngit clone git@github.com:[your username]/G6.git\n```\n\n2. 安装依赖\n\n:::warning{title=注意}\n请验证你的本地环境是否符合要求：\n\n- [Node.js](https://nodejs.org/) 版本 >= 18\n- [pnpm](https://pnpm.io/) 版本 >= 8\n\n:::\n\n```bash\n# 进入 G6 代码目录\ncd G6\n\n# 安装依赖\npnpm install\n```\n\n3. 启动开发环境\n\n```bash\n# 进入 G6 代码目录\ncd ./packages/g6\n\n# 启动开发环境\npnpm dev\n```\n\n此时，你可以在浏览器中访问 `http://127.0.0.1:8080` 查看 G6 的开发环境并预览开发示例。\n\n4. 开发新功能或修复 bug\n\n切换到开发分支：\n\n```bash\ngit checkout -b [branch name]\n```\n\n根据你的需求，修改代码并在本地测试。\n\n5. 编写测试用例\n\n在 `packages/g6/__tests__/unit` 目录下编写测试用例，确保你的代码符合预期。\n\n确保你的代码通过测试：\n\n```bash\npnpm test\n```\n\n6. 提交 PR\n\n```bash\n# 添加修改\ngit add .\n\n# 提交修改\ngit commit -m \"[commit type]: commit message\"\n\n# 推送到你的仓库\ngit push\n```\n\n在 Github 中提交 PR 到 G6 仓库。\n\n## 测试与覆盖率\n\nG6 使用 Jest 进行单元测试，测试用例位于 `packages/g6/__tests__/unit` 目录下。\n\n我们要求所有的代码提交都需要通过测试，确保代码质量。\n\n当前 PR 提交的覆盖率不建议低于当前代码库的覆盖率，且<text style=\"color: red;\">不得低于 90%</text>。\n\n### 更新测试截图\n\nG6 扩展了 Jest 测试，提供了 `toMatchSnapshot` 断言用于生成以及对比快照。\n\n如果当前可能修改影响了部分截图的生成，需要通过执行 `pnpm test` 检查是否有测试用例失败。\n\n当发现测试失败的用例时，控制台会打印出失败的测试路径，以及基准截图和当前截图的路径信息。你可以按住 `Ctrl` 或 `Command` 键并点击路径，查看具体的测试用例或截图。\n\n<img width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*39j5TKAePWsAAAAAAAAAAAAADmJ7AQ/original\"/>\n\n如果确认本次修改是正确的，那么请手动删除对应的基准截图，并重新生成截图：\n\n**重新生成全部截图**：\n\n1. 删除 `packages/g6/__tests__/unit/snapshots` 目录下的所有文件\n2. 执行 `pnpm test`\n\n**重新生成单个截图**：\n\n1. 删除 `packages/g6/__tests__/snapshots` 目录下对应的文件（`unit`目录下测试用例会在`snapshots`下生成对应的目录）\n2. 执行 `npx jest __tests__/unit/xx/xxx.spec.ts`\n\n## 代码规范\n\nG6 编码尊循以下规范：\n\n- eslint:recommended\n- @typescript-eslint/recommended\n- jsdoc/recommended-error\n\n## 提交规范\n\nG6 采用 [Conventional Commits](https://www.conventionalcommits.org/) 规范，提交信息格式如下：\n\n```\n<type>[optional scope]: <description>\n```\n\ntype 有以下几种：\n\n- feat: 新功能\n- fix: 修复 bug\n- docs: 文档更新\n- style: 代码格式（不影响代码运行的变动）\n- refactor: 重构\n- perf: 性能优化\n- test: 测试\n- build: 构建工具相关的变动\n- ci: CI 配置\n- chore: 其他无关紧要的变动\n- revert: 撤销\n\n例如：\n\n```\nfeat: add new feature\nrefactor(behavior): refactor drag-canvas behavior\n```\n\n请确保你的提交信息符合规范，并尽量使用英文描述，这样有助于我们更好地管理代码。\n\n## PR 规范\n\n完成上述步骤后，你可以提交 PR 到 G6 仓库。请确保你的 PR 符合以下规范：\n\n- 一个 PR 只解决一个问题\n- PR 的标题简洁明了\n- PR 的描述清晰详细，涉及视图的变动请附上截图\n- PR 必需能够通过 CI 检查\n\n## 代码 Review\n\nPR 提交后，我们会对你的代码进行 Review。请耐心等待 Review 结果，如果有需要修改的地方，我们会在 PR 中提出。\n\n## 发布流程\n\n我们会定期发布新版本，如果你的 PR 是非紧急缺陷修复，我们会在下一个版本中发布。如果你的 PR 是紧急缺陷修复，我们会尽快发布新版本。\n\n本项目通过 changeset 来管理版本发布，具体的发布流程如下：\n\n1. 完成相关的开发工作\n2. 从 v5 分支创建一个分支（任意分支名均可）\n3. 根目录执行 `npm run version` 命令，根据提示填写相关信息，会自动更新版本号\n4. 将变更提交到远程仓库\n5. 在 GitHub 上创建一个 PR，并添加 `publish` 标签，将该分支合并到 v5 分支\n6. 分支合并后，会自动触发 GitHub Actions，发布到 npm\n7. 发布后，需更新 Release note，在 packages/g6 目录下执行 pnpm tag\n8. 在新打开的 Github 链接填写 tag 信息，先选择前一个 tag, 然后选择当前 tag 后得到变更，确认没有问题后发布\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/data.en.md) -->\n---\ntitle: Data\norder: 1\n---\n\n## Overview\n\nG6 is a data-driven charting library, where data is one of the most important concepts. In G6, data is the core of the chart, and both display and interaction are based on data.\n\nCommon graph data formats include:CSV, [DOT](https://graphviz.org/doc/info/lang.html), GDF, GML, [GraphML](http://graphml.graphdrawing.org/), [GEXF](https://gexf.net/) etc。\n\nG6 uses JSON format to describe the graph structure, which includes information about nodes and edges. Here is a simple JSON data example:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\" }, { \"id\": \"node2\" }],\n  \"edges\": [{ \"source\": \"node1\", \"target\": \"node2\" }]\n}\n```\n\nCompared to the other formats mentioned above, the JSON format has a more intuitive and understandable data structure. It is also more flexible, allowing for easy expansion of node and edge attributes.\n\nIt is a data exchange format widely supported by computers, so you do not have to worry about data format compatibility issues.\n\n## Data Structure\n\nIn G6, graph data consists of three parts: `nodes` (node data), `edges` (edge data), and `combos` (combo data). Each part corresponds to different elements in the graph, and their types and data determine how the graph is displayed.\n\n```ts\ninterface GraphData {\n  nodes: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data (optional)\n  combos?: ComboData[]; // Combo data (optional)\n}\n```\n\n### Node Data\n\nA node is the basic building block of a graph and represents an entity within the graph. Each node has a unique `id` used to identify it, and nodes can also have data, styles, and states.\n\n| Attribute                                 | Type               | Description                                                                                                        |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the node, used to distinguish different nodes                                                |\n| type                                      | _string_           | Node type. It can be the type of built-in Node, or the custom Node                                                 |\n| data                                      | _Object_           | Custom data for the node, such as name, description, etc. Can be accessed in style mappings via callback functions |\n| style                                     | _Object_           | Node style, including position, size, color, and other visual properties                                           |\n| states                                    | _string[]_         | Initial states for the node, such as selected, active, hover, etc.                                                 |\n| combo                                     | _string_ \\| _null_ | ID of the combo the node belongs to. Used to organize hierarchical relationships. If none, it is null              |\n| children                                  | _string[]_         | Collection of child node IDs, used only in tree diagrams                                                           |\n\n**Example:**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### Edge Data\n\nAn edge connects nodes and represents the relationship between them. Each edge is associated with two nodes (source and target), and edges themselves can have data, styles, and states. Edge data is often used to represent logical relationships, such as user connections in social networks or step flows in flowcharts.\n\n| Attribute                                     | Type       | Description                                                                                                             |\n| --------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- |\n| <Badge type=\"success\">Required</Badge> source | _string_   | Source node ID                                                                                                          |\n| <Badge type=\"success\">Required</Badge> target | _string_   | Target node ID                                                                                                          |\n| id                                            | _string_   | Unique identifier for the edge. If not specified, `id` is automatically generated with the format `${source}-${target}` |\n| type                                          | _string_   | Edge type.It can be the type of built-in Edge, or the custom Edge                                                       |\n| data                                          | _Object_   | Custom data for the edge, accessible in style mappings via callback functions                                           |\n| style                                         | _Object_   | Edge style, including stroke color, line width, arrowhead, etc.                                                         |\n| states                                        | _string[]_ | Initial states for the edge                                                                                             |\n\n**Example:**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Combo Data\n\nCombos allow you to create a logical unit for multiple nodes, used for layering, grouping, or other structural purposes. A combo can contain child nodes or other combos, forming a nested structure.\n\n| Attribute                                 | Type               | Description                                                                    |\n| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |\n| <Badge type=\"success\">Required</Badge> id | _string_           | Unique identifier for the combo                                                |\n| type                                      | _string_           | Combo type.It can be the type of built-in Combo, or the custom Combo           |\n| data                                      | _Object_           | Custom data for the combo, accessible in style mappings via callback functions |\n| style                                     | _Object_           | Combo style                                                                    |\n| states                                    | _string[]_         | Initial states for the combo                                                   |\n| combo                                     | _string_ \\| _null_ | Parent combo ID. If there is no parent combo, it is null                       |\n\n**Example:**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## Data Organization and Best Practices\n\nTo ensure correct rendering and interaction of the graph, it is recommended to organize the data according to G6's standard data structure. Each element (node, edge, combo) should contain a `data` field to store business data and custom properties.\n\n- **Avoid using identifiers that conflict with internal G6 field names**, such as `id`, `type`, `style`, etc., to prevent naming conflicts.\n- Store business data (such as user information, social network relationships, etc.) in the `data` field. This ensures flexibility and scalability of the data.\n\n**Example:**\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"node1\",\n      \"data\": { \"name\": \"Alice\", \"role\": \"Admin\" }\n    },\n    {\n      \"id\": \"node2\",\n      \"data\": { \"name\": \"Bob\", \"role\": \"User\" }\n    }\n  ],\n  \"edges\": [\n    {\n      \"source\": \"node1\",\n      \"target\": \"node2\",\n      \"data\": { \"relationship\": \"friend\" }\n    }\n  ]\n}\n```\n\n## API\n\nG6 provides a series of APIs to access and manipulate data, including:\n\n- [getData](/en/api/data#graphgetdata)\n- [setData](/en/api/data#graphsetdata)\n- [getNodeData](/en/api/data#graphgetnodedata)\n- [getEdgeData](/en/api/data#graphgetedgedata)\n- [getComboData](/en/api/data#graphgetcombodata)\n- [addData](/en/api/data#graphadddata)\n- [addNodeData](/en/api/data#graphaddnodedata)\n- [addEdgeData](/en/api/data#graphaddedgedata)\n- [addComboData](/en/api/data#graphaddcombodata)\n- [updateData](/en/api/data#graphupdatedata)\n- [updateNodeData](/en/api/data#graphupdatenodedata)\n- [updateEdgeData](/en/api/data#graphupdateedgedata)\n- [updateComboData](/en/api/data#graphupdatecombodata)\n- [removeData](/en/api/data#graphremovedata)\n- [removeNodeData](/en/api/data#graphremovenodedata)\n- [removeEdgeData](/en/api/data#graphremoveedgedata)\n- [removeComboData](/en/api/data#graphremovecombodata)\n\nThrough different APIs, you can conveniently access and manipulate graph data, performing operations such as adding, deleting, modifying, and querying the graph.\n\n## Use Remote Data\n\nG6 does not provide functionality for data retrieval and parsing. For local JSON data, you can directly import and use it as follows:\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\nFor remote data, you can use `fetch` or other networking libraries to retrieve the data:\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // Use data\n  });\n```\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/data.zh.md) -->\n---\ntitle: 数据 Data\norder: 4\n---\n\n## 概述\n\nG6 是一款数据驱动的图可视化引擎，数据是 G6 中最重要的概念之一。\n\nG6 使用标准的 JSON 格式描述图数据结构。以下是一个基础的图数据示例：\n\n```javascript {4-7}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n});\n```\n\n## 数据结构\n\n图数据包含三部分：`nodes`（节点数据）、`edges`（边数据）、`combos`（组合数据）。每一部分对应图中的不同元素，它们的类型和数据决定了图如何展示。\n\n### 图数据（GraphData）\n\n| 属性   | 描述     | 类型                              | 默认值 | 必选 |\n| ------ | -------- | --------------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#节点数据nodedata)[]   | -      |      |\n| edges  | 边数据   | [EdgeData](#边数据edgedata)[]     | -      |      |\n| combos | 组合数据 | [ComboData](#组合数据combodata)[] | -      |      |\n\n### 节点数据（NodeData）\n\n节点是图中的基本构成单元，它代表图中的实体。每个节点都有一个唯一的 `id`，用于标识节点，同时节点也可以有数据、样式和状态。\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n### 边数据（EdgeData）\n\n边是连接节点的元素，表示节点之间的关系。每条边都与两个节点（起始节点和目标节点）关联，并且边本身可以有数据、样式和状态。边的数据常用于表示节点之间的逻辑或关系，如社交网络中的用户关系、流程图中的步骤流转等。\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n**示例：**\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 组合数据（ComboData）\n\n通过组合，可以为多个节点创建一个逻辑单元，用于图形的分层、分组或其他结构化需求。组合可以包含子节点或其他组合，从而形成嵌套层次。\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n## 数据操作\n\nG6 提供了丰富的 API 来操作图数据，下面展示一些常见的数据操作示例。\n\n### 数据初始化\n\n在创建图实例时，可以直接传入数据：\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n```\n\n或者通过 `setData` 方法设置数据：\n\n```javascript\ngraph.setData({\n  nodes: [\n    { id: 'node3', data: { label: '节点3' } },\n    { id: 'node4', data: { label: '节点4' } },\n  ],\n  edges: [{ source: 'node3', target: 'node4', data: { label: '新关系' } }],\n});\n```\n\n### 数据增删改查\n\n#### 添加节点和边\n\n```javascript\n// 添加单个节点\ngraph.addNodeData([\n  {\n    id: 'node5',\n    data: {\n      label: '新节点',\n      category: 'person',\n    },\n    style: {\n      fill: '#6395F9',\n      stroke: '#5B8FF9',\n    },\n  },\n]);\n\n// 批量添加多个节点\ngraph.addNodeData([\n  { id: 'node6', data: { label: '批量节点1' } },\n  { id: 'node7', data: { label: '批量节点2' } },\n]);\n\n// 添加连接新节点的边\ngraph.addEdgeData([\n  {\n    source: 'node1',\n    target: 'node5',\n    data: {\n      label: '连接到新节点',\n      weight: 2,\n    },\n    style: {\n      stroke: '#F6BD16',\n      lineWidth: 3,\n    },\n  },\n]);\n```\n\n#### 更新数据\n\n```javascript\n// 更新单个节点\ngraph.updateNodeData([\n  {\n    id: 'node1',\n    data: {\n      label: '已更新的节点1',\n      status: 'updated',\n    },\n    style: {\n      fill: '#F6BD16',\n      stroke: '#EBEBEB',\n      lineWidth: 2,\n    },\n  },\n]);\n\n// 更新多个节点\ngraph.updateNodeData([\n  {\n    id: 'node2',\n    style: { size: 40, fill: '#5AD8A6' },\n  },\n  {\n    id: 'node3',\n    data: { importance: 'high' },\n  },\n]);\n\n// 更新边\ngraph.updateEdgeData([\n  {\n    source: 'node1',\n    target: 'node2',\n    style: {\n      stroke: '#5B8FF9',\n      lineWidth: 2,\n      lineDash: [5, 5],\n    },\n  },\n]);\n```\n\n#### 删除数据\n\n```javascript\n// 删除单个节点（以及与该节点相连的所有边）\ngraph.removeNodeData(['node7']);\n\n// 删除多个节点\ngraph.removeNodeData(['node5', 'node6']);\n\n// 删除边\ngraph.removeEdgeData(['node1-node2']);\n```\n\n#### 查询数据\n\n```javascript\n// 获取所有节点数据\nconst nodes = graph.getNodeData();\n\n// 获取所有边数据\nconst edges = graph.getEdgeData();\n\n// 获取特定节点数据\nconst node1 = graph.getNodeData('node1');\n\n// 获取特定边数据\nconst edge1 = graph.getEdgeData('node1-node2');\n```\n\n### 复杂数据结构操作\n\n#### 嵌套组合（Combo）\n\n下面是创建和操作嵌套组合的示例：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', data: { label: '节点1' }, combo: 'combo1' },\n    { id: 'node2', data: { label: '节点2' }, combo: 'combo1' },\n    { id: 'node3', data: { label: '节点3' }, combo: 'combo2' },\n    { id: 'node4', data: { label: '节点4' }, combo: 'combo2' },\n    { id: 'node5', data: { label: '节点5' }, combo: 'combo3' },\n  ],\n  edges: [\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n  combos: [\n    { id: 'combo1', data: { label: '组1' } },\n    { id: 'combo2', data: { label: '组2' } },\n    { id: 'combo3', data: { label: '组3' }, combo: 'combo1' }, // 嵌套组合\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'force',\n  },\n});\n\n// 添加新的组合\ngraph.addComboData([\n  {\n    id: 'combo4',\n    data: { label: '新组' },\n    combo: 'combo2', // 添加到现有组合中\n  },\n]);\n\n// 将节点移动到不同的组合\ngraph.updateNodeData([\n  {\n    id: 'node5',\n    combo: 'combo4', // 将节点5移动到新组合\n  },\n]);\n\n// 展开/折叠组合\ngraph.updateComboData([\n  {\n    id: 'combo1',\n    style: { collapsed: true }, // 折叠组合1\n  },\n]);\n\ngraph.render();\n```\n\n#### 树形结构数据\n\n对于树形结构，G6 支持使用 `children` 属性表示层次关系：\n\n```javascript\n// 树形结构数据\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst treeData = {\n  id: 'root',\n  children: [\n    {\n      id: 'child1',\n      children: [{ id: 'grandchild1' }],\n    },\n    {\n      id: 'child2',\n      children: [{ id: 'grandchild2' }],\n    },\n  ],\n};\n\nconst data = treeToGraphData(treeData);\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'dendrogram', // 或 'compactBox', 'mindmap' 等树布局\n    direction: 'TB', // 从上到下布局\n    nodeSep: 50, // 节点间距\n    rankSep: 100, // 层级间距\n  },\n});\n\ngraph.render();\n```\n\n通过 `treeToGraphData` 方法，可以将树形结构数据转换为 G6 的标准数据结构，实际传入到 `data` 中的数据结构如下：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"root\", \"depth\": 0, \"children\": [\"child1\", \"child2\"] },\n    { \"id\": \"child1\", \"depth\": 1, \"children\": [\"grandchild1\"] },\n    { \"id\": \"grandchild1\", \"depth\": 2 },\n    { \"id\": \"child2\", \"depth\": 1, \"children\": [\"grandchild2\"] },\n    { \"id\": \"grandchild2\", \"depth\": 2 }\n  ],\n  \"edges\": [\n    { \"source\": \"root\", \"target\": \"child1\" },\n    { \"source\": \"root\", \"target\": \"child2\" },\n    { \"source\": \"child1\", \"target\": \"grandchild1\" },\n    { \"source\": \"child2\", \"target\": \"grandchild2\" }\n  ]\n}\n```\n\n## 数据组织与最佳实践\n\n为了确保图的正确渲染和交互，建议按照 G6 标准数据结构组织数据。每个元素（节点、边、组合）应包含一个 `data` 字段，用于存放业务数据和自定义属性。\n\n- **避免使用与 G6 内部字段名称相同的标识符**，如 `id`、`type`、`style` 等，防止发生命名冲突。\n- 将业务数据（如用户信息、社交网络关系等）存储在 `data` 字段中，这样可以确保数据的灵活性和可扩展性。\n- **使用样式映射**来根据业务数据动态设置视觉属性，而不是直接修改样式对象。\n\n### 数据与样式分离\n\n良好的做法是将数据和样式分离，通过映射函数将数据属性转换为视觉属性：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 使用数据驱动样式\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', data: { value: 10, category: 'A' } },\n      { id: 'node2', data: { value: 5, category: 'B' } },\n    ],\n  },\n  node: {\n    style: {\n      // 根据数据中的 value 字段动态设置节点大小\n      size: (node) => 20 + node.data.value * 2,\n      // 根据数据中的 category 字段设置不同颜色\n      fill: (node) => {\n        const categoryColors = { A: '#F6BD16', B: '#5B8FF9' };\n        return categoryColors[node.data.category] || '#CCC';\n      },\n    },\n  },\n});\n```\n\n## API\n\nG6 提供了一系列的 API 来访问和操作数据，包括：\n\n- [getData](/api/data#graphgetdata)\n- [setData](/api/data#graphsetdata)\n- [getNodeData](/api/data#graphgetnodedata)\n- [getEdgeData](/api/data#graphgetedgedata)\n- [getComboData](/api/data#graphgetcombodata)\n- [addData](/api/data#graphadddata)\n- [addNodeData](/api/data#graphaddnodedata)\n- [addEdgeData](/api/data#graphaddedgedata)\n- [addComboData](/api/data#graphaddcombodata)\n- [updateData](/api/data#graphupdatedata)\n- [updateNodeData](/api/data#graphupdatenodedata)\n- [updateEdgeData](/api/data#graphupdateedgedata)\n- [updateComboData](/api/data#graphupdatecombodata)\n- [removeData](/api/data#graphremovedata)\n- [removeNodeData](/api/data#graphremovenodedata)\n- [removeEdgeData](/api/data#graphremoveedgedata)\n- [removeComboData](/api/data#graphremovecombodata)\n\n通过不同的 API，你可以方便地访问和操作图数据，实现图的增删改查等操作。\n\n## 使用远程数据\n\nG6 并不提供数据的获取和解析功能，对于本地 JSON 数据，你可以直接引入使用：\n\n```typescript\nimport data from './path/to/data.json' assert { type: 'json' };\n```\n\n对于远程数据，你可以使用 `fetch` 或者其他网络请求库来获取数据：\n\n```typescript\nfetch('https://path/to/data.json')\n  .then((res) => res.json())\n  .then((data) => {\n    // 使用 data\n    const graph = new Graph({\n      container: 'container',\n      data,\n    });\n    // 触发布局和渲染\n    graph.render();\n  })\n  .catch((error) => {\n    console.error('加载数据失败:', error);\n  });\n```\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/BaseCombo.en.md) -->\n---\ntitle: Combo Common Options\norder: 1\n---\n\nThis document introduces the built-in combo common property configurations.\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {}, // Combo style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                               | Type                    | Default  | Required |\n| --------- | --------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name | [Type](#type)           | `circle` |          |\n| style     | Combo style configuration, including color, size, etc.    | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                  | [State](#state)         | -        |          |\n| palette   | Define combo palette for mapping colors based on data     | [Palette](#palette)     | -        |          |\n| animation | Define combo animation effects                            | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the combo type, built-in combo type name or custom combo name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select combo types based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Combo](/en/manual/element/combo/circle)\n- `rect`: [Rect Combo](/en/manual/element/combo/rect)\n\n## Style\n\nDefines combo style, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All style properties below support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Combo: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the combo data object (`ComboData`), containing all combo data information.\n\nA complete combo consists of the following parts:\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the primary shape of the combo, such as circle, rectangle, etc.\n- `label`: Text label, usually used to display the combo's name or description\n- `halo`: Graphic displaying halo effect around the main graphic\n- `badge`: Badge displayed at the top-right corner of the combo by default\n\nThe following style configurations will be explained by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the combo, defining the basic shape and appearance of the combo. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdd transparency and shadow effects to combos:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreate combos with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                              | Type                          | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current combo is collapsed                                                                                                   | boolean                       | false     |          |\n| cursor                          | Combo mouse hover style, [options](#cursor)                                                                                              | string                        | default   |          |\n| fill                            | Combo fill color                                                                                                                         | string                        | `#99ADD1` |          |\n| fillOpacity                     | Combo fill opacity                                                                                                                       | number \\| string              | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick | number                        | 0         |          |\n| lineCap                         | Combo stroke end cap style                                                                                                               | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                  | number[]                      | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                 | number                        | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                  | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                       | number                        | 1         |          |\n| opacity                         | Combo opacity                                                                                                                            | number \\| string              | 1         |          |\n| pointerEvents                   | How combo responds to pointer events, [options](#pointerevents)                                                                          | string                        | `auto`    |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                        | number                        | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                       | string                        | -         |          |\n| shadowOffsetX                   | Combo shadow offset in x direction                                                                                                       | number \\| string              | -         |          |\n| shadowOffsetY                   | Combo shadow offset in y direction                                                                                                       | number \\| string              | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                        | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Combo size, quick setting for combo width and height, [options](#size)                                                                   | number \\| number[]            | -         |          |\n| stroke                          | Combo stroke color                                                                                                                       | string                        | `#99ADD1` |          |\n| strokeOpacity                   | Combo stroke opacity                                                                                                                     | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given combo                                                        | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                           | string                        | -         |          |\n| visibility                      | Whether combo is visible                                                                                                                 | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                       | number                        | 0         |          |\n| y                               | Combo y coordinate                                                                                                                       | number                        | 0         |          |\n| z                               | Combo z coordinate                                                                                                                       | number                        | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                    | number                        | 0         |          |\n\n#### Size\n\nCombo size, quick setting for combo width and height, supports three configuration methods:\n\n- number: Indicates that combo width and height are the same as the specified value\n- [number, number]: Indicates that combo width and height are represented by array elements in order for combo width and height\n- [number, number, number]: Indicates that combo width, height, and depth are represented by array elements in order\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be the target of responding events\n- **`visiblepainted`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the `fill` value\n- **`visiblestroke`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n- **`visible`**: Will respond to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by `fill` and `stroke` values\n- **`painted`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`fill`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the `fill` value\n  - Not affected by `visibility` value\n- **`stroke`**: Will respond to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Will respond to events as long as entering the graphic fill and stroke areas, not affected by `fill`, `stroke`, `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Does not respond to events at all\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // Combo does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Style When Expanded\n\nMain graphic style when the combo is expanded\n\n| Attribute                       | Description                                                                                                                                       | Type                                                                            | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------- | -------- |\n| collapsed                       | Whether the combo is currently collapsed                                                                                                          | boolean                                                                         | false     |          |\n| cursor                          | Combo mouse hover style, [configuration item](#cursor)                                                                                            | string                                                                          | default   |          |\n| fill                            | Combo fill color                                                                                                                                  | string                                                                          | `#99ADD1` |          |\n| fillOpacity                     | Combo fill color opacity                                                                                                                          | number  string                                                                 | 0.04      |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0         |          |\n| lineCap                         | Combo stroke end style                                                                                                                            | `round`  `square`  `butt`                                                     | `butt`    |          |\n| lineDash                        | Combo stroke dash style                                                                                                                           | number[]                                                                        | -         |          |\n| lineDashOffset                  | Combo stroke dash offset                                                                                                                          | number                                                                          | -         |          |\n| lineJoin                        | Combo stroke join style                                                                                                                           | `round`  `bevel`  `miter`                                                     | `miter`   |          |\n| lineWidth                       | Combo stroke width                                                                                                                                | number                                                                          | 1         |          |\n| opacity                         | Combo opacity                                                                                                                                     | number  string                                                                 | 1         |          |\n| shadowBlur                      | Combo shadow blur                                                                                                                                 | number                                                                          | -         |          |\n| shadowColor                     | Combo shadow color                                                                                                                                | string                                                                          | -         |          |\n| shadowOffsetX                   | Combo shadow offset in the x-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowOffsetY                   | Combo shadow offset in the y-axis direction                                                                                                       | number  string                                                                 | -         |          |\n| shadowType                      | Combo shadow type                                                                                                                                 | `inner`  `outer`                                                               | `outer`   |          |\n| stroke                          | Combo stroke color                                                                                                                                | string                                                                          | `#99add1` |          |\n| strokeOpacity                   | Combo stroke color opacity                                                                                                                        | number  string                                                                 | 1         |          |\n| visibility                      | Whether the combo is visible                                                                                                                      | `visible`  `hidden`                                                            | `visible` |          |\n| x                               | Combo x coordinate                                                                                                                                | number                                                                          | 0         |          |\n| y                               | Combo y coordinate                                                                                                                                | number                                                                          | 0         |          |\n| z                               | Combo z coordinate                                                                                                                                | number                                                                          | 0         |          |\n| zIndex                          | Combo rendering layer                                                                                                                             | number                                                                          | 0         |          |\n| `{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items         | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -         |          |\n\n#### Cursor\n\nOptional 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`\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      fill: '#1783FF', // Fill color\n      stroke: '#000', // Stroke color\n      lineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: { fill: '#1783FF', stroke: '#000', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Style When Collapsed\n\nEffective when `collapsed` is `true`\n\n| Attribute                                | Description                                                                                                                                                                  | Type                                                                            | Default                                  | Required |\n| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------- | -------- |\n| collapsedCursor                          | Mouse hover style when the combo is collapsed, [configuration item](#cursor)                                                                                                 | string                                                                          | Same as the cursor when expanded         |          |\n| collapsedFill                            | Fill color when the combo is collapsed                                                                                                                                       | string                                                                          | Same as the fill when expanded           |          |\n| collapsedFillOpacity                     | Fill color opacity when the combo is collapsed                                                                                                                               | number  string                                                                 | 1                                        |          |\n| collapsedIncreasedLineWidthForHitTesting | When the combo is collapsed, if lineWidth is small, the interactive area also becomes smaller. Sometimes we want to enlarge this area to make \"thin lines\" easier to pick up | number                                                                          | 0                                        |          |\n| collapsedLineCap                         | Stroke end style when the combo is collapsed                                                                                                                                 | `round`  `square`  `butt`                                                     | Same as the lineCap when expanded        |          |\n| collapsedLineDash                        | Stroke dash style when the combo is collapsed                                                                                                                                | number[]                                                                        | Same as the lineDash when expanded       |          |\n| collapsedLineDashOffset                  | Stroke dash offset when the combo is collapsed                                                                                                                               | number                                                                          | Same as the lineDashOffset when expanded |          |\n| collapsedLineJoin                        | Stroke join style when the combo is collapsed                                                                                                                                | `round`  `bevel`  `miter`                                                     | Same as the lineJoin when expanded       |          |\n| collapsedLineWidth                       | Stroke width when the combo is collapsed                                                                                                                                     | number                                                                          | Same as the lineWidth when expanded      |          |\n| collapsedMarker                          | Whether to display the marker when the combo is collapsed, [configuration item](#collapsedMarkerStyle)                                                                       | boolean                                                                         | true                                     |          |\n| collapsedOpacity                         | Opacity when the combo is collapsed                                                                                                                                          | number  string                                                                 | Same as the opacity when expanded        |          |\n| collapsedShadowBlur                      | Shadow blur when the combo is collapsed                                                                                                                                      | number                                                                          | Same as the shadowBlur when expanded     |          |\n| collapsedShadowColor                     | Shadow color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the shadowColor when expanded    |          |\n| collapsedShadowOffsetX                   | Shadow offset in the x-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetX when expanded  |          |\n| collapsedShadowOffsetY                   | Shadow offset in the y-axis direction when the combo is collapsed                                                                                                            | number  string                                                                 | Same as the shadowOffsetY when expanded  |          |\n| collapsedShadowType                      | Shadow type when the combo is collapsed                                                                                                                                      | `inner`  `outer`                                                               | Same as the shadowType when expanded     |          |\n| collapsedSize                            | Size when the combo is collapsed                                                                                                                                             | number &#124; [number, number] &#124; [number, number, number]                  | 32                                       |          |\n| collapsedStroke                          | Stroke color when the combo is collapsed                                                                                                                                     | string                                                                          | Same as the stroke when expanded         |          |\n| collapsedStrokeOpacity                   | Stroke color opacity when the combo is collapsed                                                                                                                             | number  string                                                                 | Same as the strokeOpacity when expanded  |          |\n| collapsedVisibility                      | Whether the combo is visible when collapsed                                                                                                                                  | `visible`  `hidden`                                                            | Same as the visibility when expanded     |          |\n| `collapsed{styleProps}`                  | More graphic configurations, refer to [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) configuration items                                    | [BaseStyleProps](https://g.antv.antgroup.com/api/basic/display-object#绘图属性) | -                                        |          |\n\n**Example:**\n\n```js {5-7}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedFill: '#1783FF', // Fill color\n      collapsedStroke: '#000', // Stroke color\n      collapsedLineWidth: 2, // Stroke width\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: { collapsedFill: '#1783FF', collapsedStroke: '#000', collapsedLineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Collapsed Marker Style\n\nEffective when `collapsedMarker` is `true`\n\n| Attribute                     | Description                                                                                                                                                                                                                                                                                                                                                         | Type                                                                                                                               | Default       | Required |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| collapsedMarkerType           | Marker type displayed when the combo is collapsed <br> - `'child-count'`: Number of child elements (including Node and Combo) <br>- `'descendant-count'`: Number of descendant elements (including Node and Combo) <br>- `'node-count'`: Number of descendant elements (only including Node) <br> - `(children: NodeLikeData[]) => string`: Custom processing logic | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string)                             | `child-count` |          |\n| collapsedMarkerFill           | Icon text color                                                                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | #fff          |          |\n| collapsedMarkerFillOpacity    | Icon text color opacity                                                                                                                                                                                                                                                                                                                                             | number                                                                                                                             | 1             |          |\n| collapsedMarkerFontSize       | Icon font size                                                                                                                                                                                                                                                                                                                                                      | number                                                                                                                             | 12            |          |\n| collapsedMarkerFontWeight     | Icon font weight                                                                                                                                                                                                                                                                                                                                                    | number \\| string                                                                                                                   | `normal`      |          |\n| collapsedMarkerRadius         | Icon corner radius                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                             | 0             |          |\n| collapsedMarkerSrc            | Image source. Its priority is higher than `collapsedMarkerText`                                                                                                                                                                                                                                                                                                     | string                                                                                                                             | -             |          |\n| collapsedMarkerText           | Icon text                                                                                                                                                                                                                                                                                                                                                           | string                                                                                                                             | -             |          |\n| collapsedMarkerTextAlign      | Icon text horizontal alignment                                                                                                                                                                                                                                                                                                                                      | `center`  `end`  `left`  `right`  `start`                                                                                      | `center`      |          |\n| collapsedMarkerTextBaseline   | Icon text alignment baseline                                                                                                                                                                                                                                                                                                                                        | `alphabetic`  `bottom`  `hanging`  `ideographic`  `middle`  `top`                                                             | `middle`      |          |\n| collapsedMarkerWidth          | Icon width                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                             | -             |          |\n| collapsedMarkerHeight         | Icon height                                                                                                                                                                                                                                                                                                                                                         | number                                                                                                                             | -             |          |\n| collapsedMarkerZIndex         | Icon rendering layer                                                                                                                                                                                                                                                                                                                                                | number                                                                                                                             | 1             |          |\n| `collapsedMarker{StyleProps}` | More icon style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text), [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) configuration items. For example, collapsedMarkerFontSize represents the font size of the text icon                                                                                           | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) &#124; [ImageStyleProps](https://g.antv.antgroup.com/api/basic/image) | -             |          |\n\n**Example:**\n\n```js {5-6}\nconst graph = new Graph({\n  // Other configurations...\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF', // Fill color\n      collapsedMarkerFontSize: 30, // Icon font size\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 30,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Label Style\n\nLabels are used to display text information for combos, supporting rich text style configuration and flexible position layout.\n\n#### Basic Label Configuration\n\nAdd basic text label to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Sales Department', // Label text content\n      labelFill: '#1A1A1A', // Label text color\n      labelFontSize: 14, // Label font size\n      labelPlacement: 'bottom', // Label position: bottom\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nConfigure labels that support multi-line display:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'This is a combo label text content that supports multi-line display',\n      labelWordWrap: true, // Enable text wrapping\n      labelMaxWidth: 100, // Maximum width 100px\n      labelMaxLines: 3, // Maximum 3 lines\n      labelTextAlign: 'center', // Center text alignment\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Style Label\n\nCreate labels with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // Red text\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // Bold\n      labelFontStyle: 'italic', // Italic\n      labelTextDecorationLine: 'underline', // Underline\n      labelLetterSpacing: 2, // Letter spacing\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label style configurations:\n\n| Property                 | Description                                                                                                                                                                | Type                                                                        | Default   | Required |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show combo label                                                                                                                                                | boolean                                                                     | true      |          |\n| labelCursor              | Cursor style when hovering over combo label, [options](#cursor)                                                                                                            | string                                                                      | `default` |          |\n| labelFill                | Combo label text color                                                                                                                                                     | string                                                                      | #000      |          |\n| labelFillOpacity         | Combo label text color opacity                                                                                                                                             | number                                                                      | 1         |          |\n| labelFontFamily          | Combo label font family                                                                                                                                                    | string                                                                      | -         |          |\n| labelFontSize            | Combo label font size                                                                                                                                                      | number                                                                      | 12        |          |\n| labelFontStyle           | Combo label font style                                                                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Combo label font variant                                                                                                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Combo label font weight                                                                                                                                                    | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |          |\n| labelLeading             | Line spacing                                                                                                                                                               | number                                                                      | 0         |          |\n| labelLetterSpacing       | Combo label letter spacing                                                                                                                                                 | number \\| string                                                            | -         |          |\n| labelLineHeight          | Combo label line height                                                                                                                                                    | number \\| string                                                            | -         |          |\n| labelMaxLines            | Combo label maximum lines                                                                                                                                                  | number                                                                      | 1         |          |\n| labelMaxWidth            | Combo label maximum width, [options](#labelmaxwidth)                                                                                                                       | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Combo label X offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelOffsetY             | Combo label Y offset                                                                                                                                                       | number                                                                      | 0         |          |\n| labelPadding             | Combo label padding                                                                                                                                                        | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Combo label position relative to combo main graphic, [options](#labelplacement)                                                                                            | string                                                                      | `bottom`  |          |\n| labelText                | Combo label text content                                                                                                                                                   | string                                                                      | -         |          |\n| labelTextAlign           | Combo label text horizontal alignment                                                                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Combo label text baseline                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Combo label text decoration color                                                                                                                                          | string                                                                      | -         |          |\n| labelTextDecorationLine  | Combo label text decoration line                                                                                                                                           | string                                                                      | -         |          |\n| labelTextDecorationStyle | Combo label text decoration style                                                                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Combo label text overflow handling                                                                                                                                         | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Combo label text path                                                                                                                                                      | Path                                                                        | -         |          |\n| labelWordWrap            | Whether combo label enables auto line wrapping. When labelWordWrap is enabled, parts exceeding labelMaxWidth automatically wrap                                            | boolean                                                                     | false     |          |\n| labelZIndex              | Combo label rendering layer                                                                                                                                                | number                                                                      | 0         |          |\n| `label{StyleProps}`      | More label style configurations, refer to [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) property values. For example, labelOpacity represents label opacity | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |          |\n\n#### LabelPlacement\n\nLabel position relative to combo main graphic, available values:\n\n- `center`: Label at combo center\n- `top`, `bottom`, `left`, `right`: Label at top, bottom, left, right of combo\n- `top-left`, `top-right`, `bottom-left`, `bottom-right`: Label at four corners of combo\n- `left-top`, `left-bottom`, `right-top`, `right-bottom`: Label at edge endpoints of combo\n\n#### LabelMaxWidth\n\nWhen auto line wrapping `labelWordWrap` is enabled, text wraps when exceeding this width:\n\n- string: Defines maximum width as percentage relative to combo element width. For example, `50%` means label width doesn't exceed half of combo width\n- number: Defines maximum width in pixels. For example, 100 means label maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background provides background decoration for label text, improving label readability and visual effects.\n\n#### Basic Background Style\n\nAdd simple background to label:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Important Combo',\n      labelFill: '#fff', // White text\n      labelBackground: true, // Enable background\n      labelBackgroundFill: '#1783FF', // Blue background\n      labelBackgroundPadding: [4, 8], // Padding: vertical 4px, horizontal 8px\n      labelBackgroundRadius: 4, // Border radius\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Gradient Background Effect\n\nCreate label background with gradient effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP Combo',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // Gradient background\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // Large border radius\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Stroke-only Background Style\n\nCreate label background with stroke only:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'Border Label',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // Transparent background\n      labelBackgroundStroke: '#1783FF', // Blue stroke\n      labelBackgroundLineWidth: 2, // Stroke width\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete label background style configurations:\n\n| Property                      | Description                                                                                                                                                                                                | Type                                                         | Default      |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | Whether to show combo label background                                                                                                                                                                     | boolean                                                      | false        |\n| labelBackgroundCursor         | Combo label background cursor style, [options](#cursor)                                                                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | Combo label background fill color                                                                                                                                                                          | string                                                       | #000         |\n| labelBackgroundFillOpacity    | Combo label background opacity                                                                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | Combo label background height                                                                                                                                                                              | string \\| number                                             | -            |\n| labelBackgroundLineDash       | Combo label background dash configuration                                                                                                                                                                  | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | Combo label background dash offset                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | Combo label background stroke line width                                                                                                                                                                   | number                                                       | -            |\n| labelBackgroundPadding        | Combo label background padding                                                                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | Combo label background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values auto-filled                                    | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | Combo label background shadow blur                                                                                                                                                                         | number                                                       | -            |\n| labelBackgroundShadowColor    | Combo label background shadow color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | Combo label background shadow X offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | Combo label background shadow Y offset                                                                                                                                                                     | number                                                       | -            |\n| labelBackgroundStroke         | Combo label background stroke color                                                                                                                                                                        | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | Combo label background stroke opacity                                                                                                                                                                      | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | Whether combo label background is visible                                                                                                                                                                  | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | Combo label background rendering layer                                                                                                                                                                     | number                                                       | 1            |\n| `labelBackground{StyleProps}` | More label background style configurations, refer to [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) property values. For example, labelBackgroundOpacity represents label background opacity | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### Badge Style\n\nBadges are small markers displayed on combos, usually used to show status, quantity, or other auxiliary information. Multiple badges can be displayed simultaneously with customizable positions.\n\n#### Single Badge\n\nAdd a simple badge to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Display at top by default\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdd multiple badges at different positions to the combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // Whether to show badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nFully customize badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete badge style configurations:\n\n| Property     | Description                    | Type                                  | Default                           |\n| ------------ | ------------------------------ | ------------------------------------- | --------------------------------- |\n| badge        | Whether to show combo badge    | boolean                               | true                              |\n| badgePalette | Combo badge background palette | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Combo badge settings           | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                            | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether to show combo badge background                                                                                                                                                                                                                                                                 | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Combo badge background cursor style, [options](#cursor)                                                                                                                                                                                                                                                | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Combo badge background fill color. If not specified, consider badgePalette for sequential allocation                                                                                                                                                                                                   | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Combo badge background fill opacity                                                                                                                                                                                                                                                                    | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Combo badge background filter                                                                                                                                                                                                                                                                          | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Combo badge background height                                                                                                                                                                                                                                                                          | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Combo badge background dash configuration                                                                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Combo badge background dash offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Combo badge background stroke line width                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Combo badge background border radius <br> - number: Set all four corner radius uniformly <br> - number[]: Set four corner radius separately, missing values will be filled <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, space-separated | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Combo badge background shadow blur                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Combo badge background shadow color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Combo badge background shadow X offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Combo badge background shadow Y offset                                                                                                                                                                                                                                                                 | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Combo badge background stroke color                                                                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Combo badge background stroke opacity                                                                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether combo badge background is visible                                                                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | Combo badge text color                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                 | -            |\n| fontFamily               | Combo badge font family                                                                                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| fontSize                 | Combo badge font size                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | Combo badge font style                                                                                                                                                                                                                                                                                 | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Combo badge font variant                                                                                                                                                                                                                                                                               | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Combo badge font weight                                                                                                                                                                                                                                                                                | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Combo badge line height                                                                                                                                                                                                                                                                                | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Combo badge line width                                                                                                                                                                                                                                                                                 | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Combo badge text maximum lines                                                                                                                                                                                                                                                                         | number                                                                                                                                                                 | 1            |\n| offsetX                  | Combo badge X offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| offsetY                  | Combo badge Y offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 0            |\n| padding                  | Combo badge padding                                                                                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Combo badge position relative to combo main graphic. If not specified, defaults to clockwise placement starting from top-right                                                                                                                                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Combo badge text content                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textAlign                | Combo badge text horizontal alignment                                                                                                                                                                                                                                                                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Combo badge text baseline                                                                                                                                                                                                                                                                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Combo badge text decoration color                                                                                                                                                                                                                                                                      | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Combo badge text decoration line                                                                                                                                                                                                                                                                       | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Combo badge text decoration style                                                                                                                                                                                                                                                                      | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Combo badge text overflow handling                                                                                                                                                                                                                                                                     | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether combo badge is visible                                                                                                                                                                                                                                                                         | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether combo badge text auto-wraps                                                                                                                                                                                                                                                                    | boolean                                                                                                                                                                | -            |\n| zIndex                   | Combo badge rendering layer                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | 3            |\n\n### Halo Style\n\nHalo effect is used to highlight combos, usually used in mouse hover, selected, or active states, adding glow effect around combos.\n\n#### Basic Halo Effect\n\nAdd simple halo effect to combo:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // Enable halo\n      haloStroke: '#1783FF', // Blue halo\n      haloLineWidth: 8, // Halo width\n      haloStrokeOpacity: 0.3, // Halo opacity\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Halo Effect\n\nCreate colorful gradient halo effect:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // Red halo\n      haloLineWidth: 12, // Thicker halo\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // Blur filter effect\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dynamic Halo Effect\n\nUse halo effect in state transitions:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // No halo in default state\n      halo: false,\n    },\n    state: {\n      // Show orange halo in hover state\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // Show green halo in selected state\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete halo style configurations:\n\n| Property           | Description                                                                                                                                                                       | Type                                                                  | Default                         | Required |\n| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------- | -------- |\n| halo               | Whether to show combo halo                                                                                                                                                        | boolean                                                               | false                           |          |\n| haloCursor         | Combo halo cursor style, [options](#cursor)                                                                                                                                       | string                                                                | `default`                       |          |\n| haloDraggable      | Whether combo halo allows dragging                                                                                                                                                | boolean                                                               | true                            |          |\n| haloDroppable      | Whether combo halo allows receiving dragged elements                                                                                                                              | boolean                                                               | false                           |          |\n| haloFill           | Halo fill color                                                                                                                                                                   | string                                                                | Same as main graphic fill color |          |\n| haloFillRule       | Combo halo fill rule                                                                                                                                                              | `nonzero` \\| `evenodd`                                                | -                               |          |\n| haloFilter         | Combo halo filter effect, such as 'blur(2px)' for blur effect                                                                                                                     | string                                                                | -                               |          |\n| haloLineWidth      | Combo halo stroke width, controls halo thickness                                                                                                                                  | number                                                                | 12                              |          |\n| haloPointerEvents  | Whether combo halo effect responds to pointer events, [options](#pointerevents)                                                                                                   | string                                                                | `none`                          |          |\n| haloStroke         | Combo halo stroke color, **this property is used to set the color of halo around combo, helping to highlight the combo**                                                          | string                                                                | `#99add1`                       |          |\n| haloStrokeOpacity  | Combo halo stroke opacity, recommended to use 0.2-0.6 values for natural halo effect                                                                                              | number                                                                | 0.25                            |          |\n| haloVisibility     | Combo halo visibility                                                                                                                                                             | `visible` \\| `hidden`                                                 | `visible`                       |          |\n| haloZIndex         | Combo halo rendering layer, usually set to negative value to ensure halo is below combo main graphic                                                                              | number                                                                | -1                              |          |\n| `halo{StyleProps}` | More halo style configurations, refer to [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) options. For example, haloFillOpacity represents halo fill opacity | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                               |          |\n\n**Halo Usage Recommendations:**\n\n1. **Performance Consideration**: Halo effects increase rendering burden, recommend enabling only when necessary\n2. **Color Matching**: Halo color should coordinate with combo main color tone, avoid being too abrupt\n3. **Opacity Setting**: Reasonable opacity (0.2-0.6) can create natural halo effect\n4. **State Application**: Halo is usually used for hover, selected, active and other interactive states\n\n### Icon Style\n\nIcons are used to display text or image content in combos, usually located at the center of the combo, can be used to represent combo type or function.\n\n#### Text Icon\n\nUse text as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // Display letter A\n      iconFill: '#1783FF', // Blue text\n      iconFontSize: 24, // Large font\n      iconFontWeight: 'bold', // Bold\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Image Icon\n\nUse image as combo icon:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Colorful Text Icon\n\nCreate text icon with special styles:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'Dept',\n      iconFill: '#FF4D4F', // Red text\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // Italic\n      iconTextDecorationLine: 'underline', // Underline\n      iconLetterSpacing: 1, // Letter spacing\n    },\n  },\n});\n\ngraph.render();\n```\n\nHere are the complete icon style configurations:\n\n| Property                | Description                                                                                                               | Type                                                                        | Default                     |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to show combo icon                                                                                                | boolean                                                                     | true                        |\n| iconCursor              | Combo icon cursor style, [options](#cursor)                                                                               | string                                                                      | `default`                   |\n| iconFill                | Combo icon text color                                                                                                     | string                                                                      | -                           |\n| iconFillOpacity         | Combo icon text color opacity                                                                                             | number                                                                      | 1                           |\n| iconFontFamily          | Combo icon font family                                                                                                    | string                                                                      | -                           |\n| iconFontSize            | Combo icon font size                                                                                                      | number                                                                      | 16                          |\n| iconFontStyle           | Combo icon font style                                                                                                     | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Combo icon font variant                                                                                                   | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Combo icon font weight                                                                                                    | number \\| string                                                            | `normal`                    |\n| iconHeight              | Combo icon height, used to control image size when using image icon                                                       | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Combo icon text letter spacing                                                                                            | number \\| string                                                            | -                           |\n| iconLineHeight          | Combo icon text line height                                                                                               | number \\| string                                                            | -                           |\n| iconMaxLines            | Combo icon text maximum lines                                                                                             | number                                                                      | 1                           |\n| iconOffsetX             | Combo icon X offset                                                                                                       | number                                                                      | 0                           |\n| iconOffsetY             | Combo icon Y offset                                                                                                       | number                                                                      | 0                           |\n| iconOpacity             | Combo icon opacity                                                                                                        | number                                                                      | 1                           |\n| iconRadius              | Combo icon border radius (only effective for rectangular icons)                                                           | number                                                                      | 0                           |\n| iconSrc                 | Combo image source. Has higher priority than iconText, supports local and network images                                  | string                                                                      | -                           |\n| iconText                | Combo icon text content, supports text, Unicode characters, etc.                                                          | string                                                                      | -                           |\n| iconTextAlign           | Combo icon text horizontal alignment                                                                                      | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`                    |\n| iconTextBaseline        | Combo icon text baseline                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`                    |\n| iconTextDecorationColor | Combo icon text decoration color                                                                                          | string                                                                      | -                           |\n| iconTextDecorationLine  | Combo icon text decoration line, such as underline, strikethrough, etc.                                                   | string                                                                      | -                           |\n| iconTextDecorationStyle | Combo icon text decoration style                                                                                          | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Combo icon text overflow handling                                                                                         | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconVisibility          | Whether combo icon is visible                                                                                             | `visible` \\| `hidden`                                                       | `visible`                   |\n| iconWidth               | Combo icon width, used to control image size when using image icon                                                        | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether combo icon text auto-wraps                                                                                        | boolean                                                                     | false                       |\n| iconZIndex              | Combo icon rendering layer                                                                                                | number                                                                      | 1                           |\n| `icon{StyleProps}`      | More icon style configurations, refer to specific icon type options. For example, iconStroke represents icon stroke color | -                                                                           | -                           |\n\n**Icon Usage Recommendations:**\n\n1. **Priority**: `iconSrc` (image) has higher priority than `iconText` (text), if both are set, image will be displayed first\n2. **Size Control**: Recommend setting icon size reasonably according to combo size, avoid icons being too large or small affecting visual effect\n3. **Performance Optimization**: Text icons have better performance, image icons require additional network requests and rendering overhead\n4. **Style Consistency**: Icon styles in the same graph should be consistent to improve overall visual effect\n5. **Accessibility**: Ensure icon color has sufficient contrast with background for easy user identification\n\n## State\n\nIn some interactive behaviors, such as clicking to select a combo or hovering to activate an edge, it is merely marking certain states on the element. To reflect these states in the visual space seen by the end user, we need to set different graphic element styles for different states to respond to changes in the element's state.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the default styles of the element.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\nFor example, when the combo is in the `focus` state, you can add a stroke with a width of 3 and a color of orange.\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n**⚠️ Dynamic Configuration**: State configuration also supports dynamic configuration, which can be used to set styles dynamically based on combo data:\n\n```js\nconst graph = new Graph({\n  combo: {\n    state: {\n      // Static configuration\n      selected: {\n        stroke: '#1783FF',\n        lineWidth: 2,\n      },\n\n      // Dynamic configuration - arrow function form\n      hover: (datum) => ({\n        fill: datum.data.isVIP ? '#FFD700' : '#1783FF',\n        fillOpacity: 0.3,\n      }),\n\n      // Dynamic configuration - regular function form (access to graph instance)\n      active: function (datum) {\n        console.log(this); // graph instance\n        return {\n          stroke: datum.data.level > 3 ? '#FF4D4F' : '#52C41A',\n          lineWidth: 3,\n        };\n      },\n    },\n  },\n});\n```\n\n**⚠️ State Priority**: When a combo has multiple states simultaneously, the style merge follows the following priority (high to low):\n\n1. Later defined states override earlier defined states\n2. More specific selectors have higher priority\n3. Dynamic configuration has higher priority than static configuration\n\nFor example, if a combo has both `selected` and `hover` states, and `hover` is defined after `selected`, then `hover` state styles will override `selected` state styles.\n\n## Animation\n\nDefines the animation effects for combos, supporting the following two configuration methods:\n\n1. Disable all combo animations\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when combos enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when combo enters the canvas\n- `update`: Animation when combo updates\n- `exit`: Animation when combo leaves the canvas\n- `show`: Animation when combo shows from hidden state\n- `hide`: Animation when combo hides\n- `collapse`: Animation when combo collapses\n- `expand`: Animation when combo expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure combos, such as:\n\n#### Enter Animation\n\nConfigure animation when combo enters the canvas:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    animation: {\n      enter: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          from: 0, // Start from 0\n          to: 1, // End at 1\n          duration: 1000, // Animation duration\n          easing: 'ease-out', // Easing function\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Update Animation\n\nConfigure animation when combo updates:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      update: [\n        {\n          fields: ['x', 'y'], // Only animate x and y properties during update\n          duration: 1000, // Animation duration\n          easing: 'linear', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Exit Animation\n\nConfigure animation when combo leaves the canvas:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      exit: [\n        {\n          fields: ['opacity'], // Animate opacity property\n          to: 0, // End at 0\n          duration: 500, // Animation duration\n          easing: 'ease-in', // Easing function\n        },\n      ],\n    },\n  },\n});\n```\n\n#### Show/Hide Animation\n\nConfigure animation when combo shows/hides:\n\n```js\nconst graph = new Graph({\n  combo: {\n    animation: {\n      show: [\n        {\n          fields: ['opacity'],\n          from: 0,\n          to: 1,\n          duration: 300,\n        },\n      ],\n      hide: [\n        {\n          fields: ['opacity'],\n          to: 0,\n          duration: 300,\n        },\n      ],\n    },\n  },\n});\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass `false` to disable specific stage animations:\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // Disable combo enter animation\n    }\n  }\n}\n```\n\n**Animation Configuration Options:**\n\n| Property  | Description                             | Type                                                        | Default  |\n| --------- | --------------------------------------- | ----------------------------------------------------------- | -------- |\n| fields    | Properties to animate                   | string[]                                                    | -        |\n| from      | Starting value                          | number \\| string                                            | -        |\n| to        | Ending value                            | number \\| string                                            | -        |\n| duration  | Animation duration (milliseconds)       | number                                                      | 1000     |\n| easing    | Easing function                         | string                                                      | 'ease'   |\n| delay     | Animation delay (milliseconds)          | number                                                      | 0        |\n| repeat    | Number of repetitions (-1 for infinite) | number                                                      | 0        |\n| direction | Animation direction                     | 'normal' \\| 'reverse' \\| 'alternate' \\| 'alternate-reverse' | 'normal' |\n\n## Palette\n\nDefines combo color palette, i.e., predefined combo color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For palette definition, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                          | Type                              | Default |\n| -------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------- |\n| type     | Specifies current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                  | `group` &#124; `value`            | `group` |\n| field    | Specifies grouping field in element data. If not specified, defaults to id as grouping field                         | string &#124; ((datum) => string) | `id`    |\n| color    | Palette colors. If palette is registered, you can directly specify its registration name, also accepts a color array | string &#124; string[]            | -       |\n| invert   | Whether to invert the palette                                                                                        | boolean                           | false   |\n\nFor example, assign combo colors to a group of data by `category` field, so that combos of the same category have the same color:\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau is palette name, defaults to assign colors by ID\n  }\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/BaseCombo.zh.md) -->\n---\ntitle: 组合通用配置项\norder: 1\n---\n\n本文介绍内置组合通用属性配置。\n\n## ComboOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {}, // 组合样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](#type)           | `circle` |      |\n| style     | 组合样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定组合类型，内置组合类型名称或自定义组合的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据组合数据动态选择组合类型：\n\n```js\nconst graph = new Graph({\n  combo: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.comboType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'rect' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形组合](/manual/element/combo/circle)\n- `rect`：[矩形组合](/manual/element/combo/rect)\n\n## Style\n\n定义组合的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  combo: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据组合数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  combo: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `组合: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为组合数据对象 (`ComboData`)，包含组合的所有数据信息。\n\n一个完整的组合由以下几部分构成：\n\n<img width=\"240\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：组合的主图形，表示组合的主要形状，例如圆形、矩形等；\n- `label` ：文本标签，通常用于展示组合的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `badge` ：默认位于组合右上角的徽标；\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是组合的核心部分，定义了组合的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置组合的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      fillOpacity: 0.2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为组合添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.15,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的组合：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#FFF1F0',\n      fillOpacity: 0.1,\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前组合是否折叠                                                                          | boolean                       | false     |      |\n| cursor                          | 组合鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 组合填充色                                                                                | string                        | `#99ADD1` |      |\n| fillOpacity                     | 组合填充色透明度                                                                          | number \\| string              | 0.04      |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 组合描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 组合描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 组合描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 组合描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 组合描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 组合透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 组合如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 组合阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 组合阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 组合阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 组合阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 组合阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 组合大小，快捷设置组合宽高，[配置项](#size)                                               | number \\| number[]            | -         |      |\n| stroke                          | 组合描边色                                                                                | string                        | `#99ADD1` |      |\n| strokeOpacity                   | 组合描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定组合                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 组合是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 组合 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 组合 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 组合 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 组合渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n组合大小，快捷设置组合宽高，支持三种配置方式：\n\n- number：表示组合宽高相同为指定值\n- [number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度\n- [number, number, number]：表示组合宽高分别为数组元素依次表示组合的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  combo: {\n    style: {\n      pointerEvents: 'none', // 组合不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 收起时样式\n\n当组合处于收起状态时（`collapsed` 为 `true`），可以为其配置特殊的样式。收起时的样式属性以 `collapsed` 为前缀。\n\n#### 基础收起样式\n\n为收起状态的组合设置不同的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedFill: '#1783FF',\n      collapsedStroke: '#000',\n      collapsedLineWidth: 2,\n      collapsedSize: 40,\n      collapsedMarkerFill: '#fff',\n      collapsedMarkerFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时样式的完整配置：\n\n| 属性                                     | 描述                                                                                                  | 类型                          | 默认值                             | 必选 |\n| ---------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------- | ---------------------------------- | ---- |\n| collapsedCursor                          | 组合收起时的鼠标移入样式，[配置项](#cursor)                                                           | string                        | 默认与展开时的 cursor 一致         |      |\n| collapsedFill                            | 组合收起时的填充色                                                                                    | string                        | 默认与展开时的 fill 一致           |      |\n| collapsedFillOpacity                     | 组合收起时的填充色透明度                                                                              | number \\| string              | 1                                  |      |\n| collapsedIncreasedLineWidthForHitTesting | 组合收起时，当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0                                  |      |\n| collapsedLineCap                         | 组合收起时的描边端点样式                                                                              | `round` \\| `square` \\| `butt` | 默认与展开时的 lineCap 一致        |      |\n| collapsedLineDash                        | 组合收起时的描边虚线样式                                                                              | number[]                      | 默认与展开时的 lineDash 一致       |      |\n| collapsedLineDashOffset                  | 组合收起时的描边虚线偏移量                                                                            | number                        | 默认与展开时的 lineDashOffset 一致 |      |\n| collapsedLineJoin                        | 组合收起时的描边连接处样式                                                                            | `round` \\| `bevel` \\| `miter` | 默认与展开时的 lineJoin 一致       |      |\n| collapsedLineWidth                       | 组合收起时的描边宽度                                                                                  | number                        | 默认与展开时的 lineWidth 一致      |      |\n| collapsedMarker                          | 组合收起时是否显示标记，[配置项](#收起时标记样式)                                                     | boolean                       | true                               |      |\n| collapsedOpacity                         | 组合收起时的透明度                                                                                    | number \\| string              | 默认与展开时的 opacity 一致        |      |\n| collapsedShadowBlur                      | 组合收起时的阴影模糊度                                                                                | number                        | 默认与展开时的 shadowBlur 一致     |      |\n| collapsedShadowColor                     | 组合收起时的阴影颜色                                                                                  | string                        | 默认与展开时的 shadowColor 一致    |      |\n| collapsedShadowOffsetX                   | 组合收起时的阴影在 x 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetX 一致  |      |\n| collapsedShadowOffsetY                   | 组合收起时的阴影在 y 轴方向上的偏移量                                                                 | number \\| string              | 默认与展开时的 shadowOffsetY 一致  |      |\n| collapsedShadowType                      | 组合收起时的阴影类型                                                                                  | `inner` \\| `outer`            | 默认与展开时的 shadowType 一致     |      |\n| collapsedSize                            | 组合收起时的大小                                                                                      | number \\| [number, number]    | 32                                 |      |\n| collapsedStroke                          | 组合收起时的描边色                                                                                    | string                        | 默认与展开时的 stroke 一致         |      |\n| collapsedStrokeOpacity                   | 组合收起时的描边色透明度                                                                              | number \\| string              | 默认与展开时的 strokeOpacity 一致  |      |\n| collapsedVisibility                      | 组合收起时是否可见                                                                                    | `visible` \\| `hidden`         | 默认与展开时的 visibility 一致     |      |\n\n### 收起时标记样式\n\n当 `collapsedMarker` 为 `true` 时显示的标记，用于显示收起组合内包含的元素数量。\n\n#### 自定义标记内容\n\n可以自定义收起标记显示的内容：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1' },\n      { id: 'node2', combo: 'combo1' },\n      { id: 'node3', combo: 'combo1' },\n    ],\n    combos: [{ id: 'combo1', style: { collapsed: true } }],\n  },\n  combo: {\n    style: {\n      collapsedMarkerType: 'child-count',\n      collapsedMarkerFill: '#1783FF',\n      collapsedMarkerFontSize: 14,\n      collapsedMarkerFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为收起时标记样式的完整配置：\n\n| 属性                        | 描述                                                                                                                                                                                                                                                          | 类型                                                                                                   | 默认值        | 必选 |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------- | ---- |\n| collapsedMarkerType         | 组合收起时显示的标记类型 <br> - `'child-count'`: 子元素数量（包括 Node 和 Combo）<br>- `'descendant-count'`: 后代元素数量（包括 Node 和 Combo）<br>- `'node-count'`: 后代元素数量（只包括 Node）<br> - `(children: NodeLikeData[]) => string`: 自定义处理逻辑 | `child-count` \\| `descendant-count` \\| `node-count` \\| ((children: NodeData \\| ComboData[]) => string) | `child-count` |      |\n| collapsedMarkerFill         | 标记文字颜色                                                                                                                                                                                                                                                  | string                                                                                                 | #fff          |      |\n| collapsedMarkerFillOpacity  | 标记文字颜色透明度                                                                                                                                                                                                                                            | number                                                                                                 | 1             |      |\n| collapsedMarkerFontSize     | 标记字体大小                                                                                                                                                                                                                                                  | number                                                                                                 | 12            |      |\n| collapsedMarkerFontWeight   | 标记字体粗细                                                                                                                                                                                                                                                  | number \\| string                                                                                       | `normal`      |      |\n| collapsedMarkerRadius       | 标记圆角半径                                                                                                                                                                                                                                                  | number                                                                                                 | 0             |      |\n| collapsedMarkerSrc          | 图片来源。其优先级高于 `collapsedMarkerText`                                                                                                                                                                                                                  | string                                                                                                 | -             |      |\n| collapsedMarkerText         | 标记文字                                                                                                                                                                                                                                                      | string                                                                                                 | -             |      |\n| collapsedMarkerTextAlign    | 标记文字水平对齐方式                                                                                                                                                                                                                                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                                                      | `center`      |      |\n| collapsedMarkerTextBaseline | 标记文字对齐基线                                                                                                                                                                                                                                              | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top`                            | `middle`      |      |\n| collapsedMarkerWidth        | 标记宽度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerHeight       | 标记高度                                                                                                                                                                                                                                                      | number                                                                                                 | -             |      |\n| collapsedMarkerZIndex       | 标记层级                                                                                                                                                                                                                                                      | number                                                                                                 | 1             |      |\n\n### 徽标样式\n\n徽标是组合上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为组合添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为组合添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 组合是否显示徽标   | boolean                               | true                              |\n| badgePalette | 组合徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 组合徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 组合徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 组合徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 组合徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 组合徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 组合徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 组合徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 组合徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 组合徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 组合徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 组合徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 组合徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 组合徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 组合徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 组合徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 组合徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 组合徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 组合徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| fill                     | 组合徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 组合徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 组合徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 组合徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 组合徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 组合徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 组合徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 组合徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 组合徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 组合徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 组合徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 组合徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 组合徽标相对于组合主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 组合徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 组合徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 组合徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 组合徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 组合徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 组合徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 组合徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 组合徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 组合徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 组合徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 标签样式\n\n标签用于显示组合的文本信息，支持丰富的文本样式配置和灵活的位置布局。\n\n#### 基础标签配置\n\n为组合添加基本的文本标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '销售部门', // 标签文字内容\n      labelFill: '#1A1A1A', // 标签文字颜色\n      labelFontSize: 14, // 标签字体大小\n      labelPlacement: 'bottom', // 标签位置：底部\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n配置支持多行显示的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '这是一个支持多行显示的组合标签文本内容',\n      labelWordWrap: true, // 开启文本换行\n      labelMaxWidth: 100, // 最大宽度 100px\n      labelMaxLines: 3, // 最多显示 3 行\n      labelTextAlign: 'center', // 文本居中对齐\n      labelFontSize: 12,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义样式标签\n\n创建具有特殊样式的标签：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'IMPORTANT',\n      labelFill: '#FF4D4F', // 红色文字\n      labelFontSize: 16,\n      labelFontWeight: 'bold', // 粗体\n      labelFontStyle: 'italic', // 斜体\n      labelTextDecorationLine: 'underline', // 下划线\n      labelLetterSpacing: 2, // 字间距\n      labelPlacement: 'top',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                                                                         | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示组合标签                                                                                                             | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入组合标签时显示的样式，[配置项](#cursor)                                                                              | string                                                                      | `default` |      |\n| labelFill                | 组合标签文字颜色                                                                                                             | string                                                                      | #000      |      |\n| labelFillOpacity         | 组合标签文字颜色的透明度                                                                                                     | number                                                                      | 1         |      |\n| labelFontFamily          | 组合标签字体族                                                                                                               | string                                                                      | -         |      |\n| labelFontSize            | 组合标签字体大小                                                                                                             | number                                                                      | 12        |      |\n| labelFontStyle           | 组合标签字体样式                                                                                                             | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 组合标签字体变种                                                                                                             | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 组合标签字体粗细                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | 400       |      |\n| labelLeading             | 行间距                                                                                                                       | number                                                                      | 0         |      |\n| labelLetterSpacing       | 组合标签字间距                                                                                                               | number \\| string                                                            | -         |      |\n| labelLineHeight          | 组合标签行高                                                                                                                 | number \\| string                                                            | -         |      |\n| labelMaxLines            | 组合标签最大行数                                                                                                             | number                                                                      | 1         |      |\n| labelMaxWidth            | 组合标签最大宽度，[配置项](#labelmaxwidth)                                                                                   | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 组合标签在 x 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelOffsetY             | 组合标签在 y 轴方向上的偏移量                                                                                                | number                                                                      | 0         |      |\n| labelPadding             | 组合标签内边距                                                                                                               | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 组合标签相对于组合主图形的位置，[配置项](#labelplacement)                                                                    | string                                                                      | `bottom`  |      |\n| labelText                | 组合标签文字内容                                                                                                             | string                                                                      | -         |      |\n| labelTextAlign           | 组合标签文本水平对齐方式                                                                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 组合标签文本基线                                                                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 组合标签文本装饰线颜色                                                                                                       | string                                                                      | -         |      |\n| labelTextDecorationLine  | 组合标签文本装饰线                                                                                                           | string                                                                      | -         |      |\n| labelTextDecorationStyle | 组合标签文本装饰线样式                                                                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 组合标签文本溢出处理方式                                                                                                     | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 组合标签文本路径                                                                                                             | Path                                                                        | -         |      |\n| labelWordWrap            | 组合标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行                                           | boolean                                                                     | false     |      |\n| labelZIndex              | 组合标签渲染层级                                                                                                             | number                                                                      | 0         |      |\n| `label{StyleProps}`      | 更多标签样式配置，参考 [TextStyleProps](https://g.antv.antgroup.com/api/basic/text) 属性值。比如 labelOpacity 代表标签透明度 | [TextStyleProps](https://g.antv.antgroup.com/api/basic/text)                | -         |      |\n\n#### LabelPlacement\n\n标签相对于组合主图形的位置，可选值有：\n\n- `center`：标签位于组合中心\n- `top`、`bottom`、`left`、`right`：标签位于组合的上、下、左、右方\n- `top-left`、`top-right`、`bottom-left`、`bottom-right`：标签位于组合的四个角\n- `left-top`、`left-bottom`、`right-top`、`right-bottom`：标签位于组合边的端点\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于组合元素宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过组合宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景为标签文字提供背景装饰，可以提升标签的可读性和视觉效果。\n\n#### 基础背景样式\n\n为标签添加简单的背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '重要组合',\n      labelFill: '#fff', // 白色文字\n      labelBackground: true, // 启用背景\n      labelBackgroundFill: '#1783FF', // 蓝色背景\n      labelBackgroundPadding: [4, 8], // 内边距：垂直4px，水平8px\n      labelBackgroundRadius: 4, // 圆角半径\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 渐变背景效果\n\n创建带渐变效果的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: 'VIP组合',\n      labelFill: '#fff',\n      labelFontWeight: 'bold',\n      labelBackground: true,\n      labelBackgroundFill: 'linear-gradient(45deg, #FF6B6B, #4ECDC4)', // 渐变背景\n      labelBackgroundPadding: [6, 12],\n      labelBackgroundRadius: 20, // 大圆角\n      labelBackgroundShadowColor: 'rgba(0,0,0,0.2)',\n      labelBackgroundShadowBlur: 4,\n      labelBackgroundShadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 描边背景样式\n\n创建只有描边的标签背景：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      labelText: '边框标签',\n      labelFill: '#1783FF',\n      labelBackground: true,\n      labelBackgroundFill: 'transparent', // 透明背景\n      labelBackgroundStroke: '#1783FF', // 蓝色描边\n      labelBackgroundLineWidth: 2, // 描边宽度\n      labelBackgroundPadding: [4, 8],\n      labelBackgroundRadius: 8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签背景样式配置：\n\n| 属性                          | 描述                                                                                                                                           | 类型                                                         | 默认值       |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------ |\n| labelBackground               | 组合标签背景是否显示                                                                                                                           | boolean                                                      | false        |\n| labelBackgroundCursor         | 组合标签背景鼠标移入样式，[配置项](#cursor)                                                                                                    | string                                                       | `default`    |\n| labelBackgroundFill           | 组合标签背景填充色                                                                                                                             | string                                                       | #000         |\n| labelBackgroundFillOpacity    | 组合标签背景透明度                                                                                                                             | number                                                       | 0.75         |\n| labelBackgroundHeight         | 组合标签背景高度                                                                                                                               | string \\| number                                             | -            |\n| labelBackgroundLineDash       | 组合标签背景虚线配置                                                                                                                           | number \\| string \\|(number \\| string )[]                     | -            |\n| labelBackgroundLineDashOffset | 组合标签背景虚线偏移量                                                                                                                         | number                                                       | -            |\n| labelBackgroundLineWidth      | 组合标签背景描边线宽                                                                                                                           | number                                                       | -            |\n| labelBackgroundPadding        | 组合标签背景内间距                                                                                                                             | number \\| number[]                                           | [2, 4, 2, 4] |\n| labelBackgroundRadius         | 组合标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充                                 | number \\| number[]                                           | 0            |\n| labelBackgroundShadowBlur     | 组合标签背景阴影模糊程度                                                                                                                       | number                                                       | -            |\n| labelBackgroundShadowColor    | 组合标签背景阴影颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundShadowOffsetX  | 组合标签背景阴影 X 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundShadowOffsetY  | 组合标签背景阴影 Y 方向偏移                                                                                                                    | number                                                       | -            |\n| labelBackgroundStroke         | 组合标签背景描边颜色                                                                                                                           | string                                                       | -            |\n| labelBackgroundStrokeOpacity  | 组合标签背景描边透明度                                                                                                                         | number \\| string                                             | 1            |\n| labelBackgroundVisibility     | 组合标签背景是否可见                                                                                                                           | `visible` \\| `hidden`                                        | -            |\n| labelBackgroundZIndex         | 组合标签背景渲染层级                                                                                                                           | number                                                       | 1            |\n| `labelBackground{StyleProps}` | 更多标签背景样式配置，参考 [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) 属性值。例如 labelBackgroundOpacity 代表标签背景透明度 | [RectStyleProps](https://g.antv.antgroup.com/api/basic/rect) | -            |\n\n### 光晕样式\n\n光晕效果用于突出显示组合，通常在鼠标悬停、选中或激活状态下使用，为组合周围添加发光效果。\n\n#### 基础光晕效果\n\n为组合添加简单的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true, // 启用光晕\n      haloStroke: '#1783FF', // 蓝色光晕\n      haloLineWidth: 8, // 光晕宽度\n      haloStrokeOpacity: 0.3, // 光晕透明度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色光晕效果\n\n创建彩色渐变的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      halo: true,\n      haloStroke: '#FF4D4F', // 红色光晕\n      haloLineWidth: 12, // 较粗的光晕\n      haloStrokeOpacity: 0.5,\n      haloFilter: 'blur(2px)', // 模糊滤镜效果\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 动态光晕效果\n\n在状态切换时使用光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      // 默认状态下不显示光晕\n      halo: false,\n    },\n    state: {\n      // 悬停状态显示橙色光晕\n      hover: {\n        halo: true,\n        haloStroke: '#FF7A00',\n        haloLineWidth: 10,\n        haloStrokeOpacity: 0.4,\n      },\n      // 选中状态显示绿色光晕\n      selected: {\n        halo: true,\n        haloStroke: '#52C41A',\n        haloLineWidth: 6,\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性               | 描述                                                                                                                                           | 类型                                                                  | 默认值                       | 必选 |\n| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------------------- | ---- |\n| halo               | 是否显示组合光晕                                                                                                                               | boolean                                                               | false                        |      |\n| haloCursor         | 组合光晕鼠标移入样式，[配置项](#cursor)                                                                                                        | string                                                                | `default`                    |      |\n| haloDraggable      | 组合光晕是否允许拖拽                                                                                                                           | boolean                                                               | true                         |      |\n| haloDroppable      | 组合光晕是否允许接收被拖拽的元素                                                                                                               | boolean                                                               | false                        |      |\n| haloFill           | 光晕填充色                                                                                                                                     | string                                                                | 与主图形的填充色 `fill` 一致 |      |\n| haloFillRule       | 组合光晕填充规则                                                                                                                               | `nonzero` \\| `evenodd`                                                | -                            |      |\n| haloFilter         | 组合光晕滤镜效果，如 'blur(2px)' 可创建模糊效果                                                                                                | string                                                                | -                            |      |\n| haloLineWidth      | 组合光晕描边宽度，控制光晕的粗细程度                                                                                                           | number                                                                | 12                           |      |\n| haloPointerEvents  | 组合光晕效果是否响应指针事件，[配置项](#pointerevents)                                                                                         | string                                                                | `none`                       |      |\n| haloStroke         | 组合光晕描边色，**此属性用于设置组合周围光晕的颜色，帮助突出显示组合**                                                                         | string                                                                | `#99add1`                    |      |\n| haloStrokeOpacity  | 组合光晕描边色透明度，建议使用 0.2-0.6 的值以获得自然的光晕效果                                                                                | number                                                                | 0.25                         |      |\n| haloVisibility     | 组合光晕可见性                                                                                                                                 | `visible` \\| `hidden`                                                 | `visible`                    |      |\n| haloZIndex         | 组合光晕渲染层级，通常设置为负值以确保光晕在组合主图形下方                                                                                     | number                                                                | -1                           |      |\n| `halo{StyleProps}` | 更多光晕样式配置，参考 [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) 配置项。例如 haloFillOpacity 代表光晕填充色透明度 | [DisplayObject](https://g.antv.antgroup.com/api/basic/display-object) | -                            |      |\n\n**光晕使用建议：**\n\n1. **性能考虑**：光晕效果会增加渲染负担，建议在必要时才启用\n2. **颜色搭配**：光晕颜色应与组合主色调协调，避免过于突兀\n3. **透明度设置**：合理的透明度（0.2-0.6）可以创造自然的光晕效果\n4. **状态应用**：光晕通常用于 hover、selected、active 等交互状态\n\n### 图标样式\n\n图标用于在组合中显示文字或图片内容，通常位于组合的中心位置，可以用来表示组合的类型或功能。\n\n#### 文字图标\n\n使用文字作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: 'A', // 显示字母 A\n      iconFill: '#1783FF', // 蓝色文字\n      iconFontSize: 24, // 大字体\n      iconFontWeight: 'bold', // 粗体\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 图片图标\n\n使用图片作为组合的图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      fill: '#1890FF',\n      iconSrc: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg',\n      iconWidth: 32,\n      iconHeight: 32,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 彩色文字图标\n\n创建带有特殊样式的文字图标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    combos: [{ id: 'combo1' }],\n  },\n  combo: {\n    style: {\n      iconText: '部门',\n      iconFill: '#FF4D4F', // 红色文字\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n      iconFontStyle: 'italic', // 斜体\n      iconTextDecorationLine: 'underline', // 下划线\n      iconLetterSpacing: 1, // 字间距\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                                                         | 类型                                                                        | 默认值           |\n| ----------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示组合图标                                                             | boolean                                                                     | true             |\n| iconCursor              | 组合图标鼠标移入样式，[配置项](#cursor)                                      | string                                                                      | `default`        |\n| iconFill                | 组合图标文字颜色                                                             | string                                                                      | -                |\n| iconFillOpacity         | 组合图标文字颜色透明度                                                       | number                                                                      | 1                |\n| iconFontFamily          | 组合图标字体族                                                               | string                                                                      | -                |\n| iconFontSize            | 组合图标字体大小                                                             | number                                                                      | 16               |\n| iconFontStyle           | 组合图标字体样式                                                             | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 组合图标字体变种                                                             | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 组合图标字体粗细                                                             | number \\| string                                                            | `normal`         |\n| iconHeight              | 组合图标高度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 组合图标文本字间距                                                           | number \\| string                                                            | -                |\n| iconLineHeight          | 组合图标文本行高                                                             | number \\| string                                                            | -                |\n| iconMaxLines            | 组合图标文本最大行数                                                         | number                                                                      | 1                |\n| iconOffsetX             | 组合图标在 x 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOffsetY             | 组合图标在 y 轴方向上的偏移量                                                | number                                                                      | 0                |\n| iconOpacity             | 组合图标透明度                                                               | number                                                                      | 1                |\n| iconRadius              | 组合图标圆角半径（仅对矩形图标有效）                                         | number                                                                      | 0                |\n| iconSrc                 | 组合图片来源。其优先级高于 iconText，支持本地图片和网络图片                  | string                                                                      | -                |\n| iconText                | 组合图标文字内容，支持文字、Unicode 字符等                                   | string                                                                      | -                |\n| iconTextAlign           | 组合图标文本水平对齐方式                                                     | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `center`         |\n| iconTextBaseline        | 组合图标文本基线                                                             | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `middle`         |\n| iconTextDecorationColor | 组合图标文本装饰线颜色                                                       | string                                                                      | -                |\n| iconTextDecorationLine  | 组合图标文本装饰线，如下划线、删除线等                                       | string                                                                      | -                |\n| iconTextDecorationStyle | 组合图标文本装饰线样式                                                       | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 组合图标文本溢出处理方式                                                     | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconVisibility          | 组合图标是否可见                                                             | `visible` \\| `hidden`                                                       | `visible`        |\n| iconWidth               | 组合图标宽度，当使用图片图标时用于控制图片尺寸                               | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 组合图标文本是否自动换行                                                     | boolean                                                                     | false            |\n| iconZIndex              | 组合图标渲染层级                                                             | number                                                                      | 1                |\n| `icon{StyleProps}`      | 更多图标样式配置，参考图标的具体类型配置项。例如 iconStroke 代表图标描边颜色 | -                                                                           | -                |\n\n**图标使用建议：**\n\n1. **优先级**：`iconSrc`（图片）的优先级高于 `iconText`（文字），如果同时设置，会优先显示图片\n2. **尺寸控制**：建议根据组合大小合理设置图标尺寸，避免图标过大或过小影响视觉效果\n3. **性能优化**：使用文字图标性能更好，图片图标需要额外的网络请求和渲染开销\n4. **样式一致性**：在同一个图中的组合图标样式应保持一致，提升整体视觉效果\n5. **可访问性**：确保图标颜色与背景有足够的对比度，便于用户识别\n\n## State\n\n在一些交互行为中，比如点击选中一个组合或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Iv_dS5XR2TcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype ComboState = {\n  [state: string]: ComboStyle;\n};\n```\n\n例如，当组合处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', combo: 'combo1' }],\n    combos: [{ id: 'combo1', states: ['focus'] }],\n  },\n  combo: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n        fill: 'orange',\n        fillOpacity: 0.2,\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义组合的动画效果，支持下列两种配置方式：\n\n1. 关闭组合全部动画\n\n```json\n{\n  \"combo\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指组合在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 组合进入画布时的动画\n- `update`: 组合更新时的动画\n- `exit`: 组合离开画布时的动画\n- `show`: 组合从隐藏状态显示时的动画\n- `hide`: 组合隐藏时的动画\n- `collapse`: 组合收起时的动画\n- `expand`: 组合展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置组合，如：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"combo\": {\n    \"animation\": {\n      \"enter\": false // 关闭组合入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义组合的色板，即预定义组合颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                              | 默认值  |\n| ------ | ------------------------------------------------------------------- | --------------------------------- | ------- |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` &#124; `value`            | `group` |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string &#124; ((datum) => string) | `id`    |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string &#124; string[]            | -       |\n| invert | 是否反转色板                                                        | boolean                           | false   |\n\n如将一组数据按 `category` 字段分配组合颜色，使得同类别的组合颜色相同：\n\n```json\n{\n  \"combo\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"combo\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    combos: new Array(8)\n      .fill(0)\n      .map((_, i) => ({ id: `combo-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 8 },\n  combo: {\n    style: { fillOpacity: 0.4 },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/CircleCombo.en.md) -->\n---\ntitle: Circle Combo\norder: 2\n---\n\n## Overview\n\nThe circular combo wraps child nodes or child combos with a circular boundary, suitable for representing equal or non-hierarchical group relationships.\n\nApplicable scenarios:\n\n- Suitable for representing node groups without a clear hierarchical relationship. The circular combo can reflect the equality of members, such as user groups in social networks or decentralized team structures (highlighting collaboration).\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example shows the distribution of interest group members:\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/CircleCombo.zh.md) -->\n---\ntitle: 圆形组合 Circle\norder: 2\n---\n\n## 概述\n\n圆形组合以圆形边界包裹子节点或子组合，适合表示平等或非层级化的群组关系。\n\n适用场景：\n\n- 适合表示无明确层级关系的节点群组，圆形组合能体现成员的平等性，如社交网络中的用户群体、分散式团队结构（突出协作性）。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/circle-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为兴趣小组人员分布：\n\n<embed src=\"@/common/api/elements/combos/circle-combo-interest.md\"></embed>\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/custom-combo.en.md) -->\n---\ntitle: Custom Combo\norder: 4\n---\n\nG6 provides two types of [built-in combos](/en/manual/element/combo/base-combo): circular combos and rectangular combos. However, in complex business scenarios, you may need to create custom combos with specific styles, interactive effects, or behavior logic.\n\n## Before You Start: Understanding the Basic Composition of Combos\n\nIn G6, a complete combo typically consists of the following parts:\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the combo, representing the main shape of the combo, such as a circle, rectangle, etc.\n- `label`: Text label, usually used to display the name or description of the combo.\n- `halo`: A graphic that displays a halo effect around the main graphic.\n\n### Special Characteristics of Combos\n\nCombos differ from ordinary nodes and have the following characteristics:\n\n1. **Containment**: Combos can contain nodes and other combos, forming a hierarchical structure.\n2. **Two States**: Expanded and Collapsed states.\n3. **Adaptive Size**: Automatically adjusts size based on internal elements.\n4. **Drag Behavior**: Supports overall dragging and dragging elements in/out.\n\n## Ways to Customize Combos <Badge type=\"warning\">Choose the Right Way</Badge>\n\nThere are two ways to create custom combos:\n\n### 1. Inherit Existing Combo Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most common way, and you can choose to inherit one of the following types:\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - The most basic combo class, providing core functionality for combos.\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - Circular combo.\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - Rectangular combo.\n\n**Why choose this way?**\n\n- 📌 **Less Code**: Reuse existing combo properties and methods, focusing only on new features.\n- 📌 **Fast Development**: Suitable for most project needs, quickly achieving business goals.\n- 📌 **Easy Maintenance**: Clear code structure and clear inheritance relationships.\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing combo types (recommended), you can jump directly to [Create Your First Custom Combo in Three Steps](#create-your-first-custom-combo-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Develop from Scratch Based on the G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing combo types do not meet your needs, you can create combos from scratch based on the underlying graphics system of G.\n\n**Why choose this way?**\n\n- 📌 **Maximum Freedom**: Full control over every detail of the combo, achieving any complex effect.\n- 📌 **Special Needs**: Highly customized scenarios that existing combo types cannot meet.\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios.\n\n:::warning{title=Note}\nDeveloping custom combos from scratch requires handling all details yourself, including graphic drawing, event response, state changes, expand/collapse logic, etc., which is quite challenging. You can directly refer to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) for implementation.\n:::\n\n## Create Your First Custom Combo in Three Steps\n\nLet's start by inheriting `BaseCombo` to implement a custom hexagon combo:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// Define the path for the collapsed state button\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// Define the path for the expanded state button\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the expand/collapse button, using paths for finer control\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Override the render method to add more custom graphics\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // Use lifecycle hooks to add event listeners\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// Register the custom combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// Create a graph instance and use the custom combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Step 1: Write the Custom Combo Class\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// Define button path generation functions\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // Get the path of the hexagon\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // Calculate the vertices of the hexagon\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // Construct the SVG path\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // Get the style of the main graphic, directly using path data\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // Draw the main graphic, using path type to directly pass in style objects\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // Draw the collapse/expand button, using SVG paths for finer control\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // Create the clickable area and button graphic\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // Use lifecycle hook methods to bind events\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### Step 2: Register the Custom Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### Step 3: Apply the Custom Combo\n\n```js\nconst graph = new Graph({\n  // ...other configurations\n  combo: {\n    type: 'hexagon-combo', // Use the name registered\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // Since we implemented the collapse/expand feature ourselves, only drag behavior is needed here\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 Congratulations! You have created your first custom combo.\n\n## Going Further: Understanding the Principles of Combo Drawing\n\n### Differences Between Combos and Nodes\n\nAlthough Combos inherit from `BaseNode`, there are some key differences:\n\n1. **Adaptive Size**: Combos automatically calculate the appropriate size based on internal elements.\n2. **Expand/Collapse States**: Combos have two display states and need to handle state transitions.\n3. **Hierarchical Structure**: Combos can be nested, forming hierarchical relationships.\n4. **Internal Element Management**: Combos need to manage the nodes and sub-combos they contain.\n\n### Atomic Graphics\n\nG6's Combos are drawn using atomic graphic units provided by the [G Graphics System](https://g.antv.antgroup.com/). For an introduction to atomic graphics, please refer to the [Element - Shape (Optional)](/en/manual/element/shape/overview) documentation.\n\nAll these graphics can be dynamically created or updated using `upsert()` and automatically manage graphic states and lifecycles.\n\n### Element Base Class\n\nBefore customizing Combos, you need to understand some important properties and methods in the G6 element base class:\n\n#### Properties\n\n| Property   | Type                          | Description                                               |\n| ---------- | ----------------------------- | --------------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under the current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under the current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom Combos, you will frequently use the `upsert` method. It is short for \"update or insert\" and is responsible for adding or updating graphics in the element:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| key       | string                                  | Key of the graphic, corresponding to the key in `shapeMap`. Built-in keys include `'key'`, `'label'`, `'halo'`, `'icon'`, `'port'`, `'badge'`<br/> Keys should not use special symbols, and will be converted to camel case to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                  |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                 |\n\nFor example, insert a fixed-position purple circle:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics with `container.appendChild()`? Because:\n\n1. **Better Performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and recreating them, greatly improving rendering performance.\n2. **Simpler Code**: No need to manually check if elements exist.\n3. **Easy Management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, and you can easily access them with `this.getShape(key)`.\n\n#### `render(attributes, container)`: Main Entry for Rendering Combos\n\nEvery custom combo class must implement the `render(attributes, container)` method, which defines how the combo is \"drawn\". You can use various atomic graphics here to create the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation or have interactions between sub-graphics. In this case, the `getShape` method can help you access any graphics previously created with `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, make sure A is created first.\n\n### Element Conventions\n\n- **Use Convention Properties**\n\nThe convention properties in combos include:\n\n- Use `this.getKeySize(attributes)` to get the size of the combo, considering the collapsed state and sub-elements.\n- Use `this.getContentBBox(attributes)` to get the bounding box of the content area.\n- Use `this.getComboPosition(attributes)` to get the current position of the combo, based on state and sub-elements.\n\n- **Use `getXxxStyle` and `drawXxxShape` Pairing for Graphic Drawing**\n\n`getXxxStyle` is used to get the graphic style, and `drawXxxShape` is used to draw the graphic. Graphics created this way support automatic animation execution.\n\n> `Xxx` is the camel case form of the key passed to the [upsert](#methods) method.\n\n- **Access Graph Context via `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, and you can override these methods in custom combos to execute specific logic at key moments:\n\n| Hook Function | Trigger Timing                                                     | Typical Use Cases                                                                |\n| ------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| `onCreate`    | After the combo is created and the entrance animation is completed | Bind interactive events, initialize combo state, add external listeners          |\n| `onUpdate`    | After the combo is updated and the update animation is completed   | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | After the combo is destroyed and the exit animation is completed   | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"drawing logic\"**.\n\nYou can define styles for each state in the combo configuration:\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\nThis state will be passed into the `render()` method's `attributes` and automatically applied to the graphics as a result of the internal system merging.\n\nYou can also customize rendering logic based on the state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/custom-combo.zh.md) -->\n---\ntitle: 自定义 Combo\norder: 4\n---\n\nG6 提供了两种 [内置组合](/manual/element/combo/base-combo) 类型：圆形组合和矩形 Combo 。但在复杂的业务场景中，你可能需要创建具有特定样式、交互效果或行为逻辑的自定义 Combo 。\n\n## 开始之前：了解 Combo 的基本构成\n\n在 G6 中，一个完整的 Combo 通常由以下几个部分组成：\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*z-OxR4MAdUwAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ： Combo 的主图形，表示 Combo 的主要形状，如圆形、矩形等；\n- `label` ：文本标签，通常用于展示 Combo 的名称或描述；\n- `halo` ：主图形周围展示的光晕效果的图形；\n\n### Combo 的特殊性\n\nCombo 不同于普通节点，它具有以下特性：\n\n1. **包含性**： Combo 可以包含节点和其他 Combo ，形成层级结构\n2. **两种状态**：展开(Expanded)和收起(Collapsed)状态\n3. **自适应大小**：根据内部元素动态调整大小\n4. **拖拽行为**：支持整体拖拽及内部元素拖入/拖出\n\n## 自定义 Combo 的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义 Combo 的方式有两种途径：\n\n### 1. 继承现有 Combo 类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseCombo`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) - 最基础的 Combo 类，提供 Combo 的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/circle.ts) - 圆形 Combo\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/rect.ts) - 矩形 Combo\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有 Combo 的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有组合类型（推荐），可以直接跳到 [三步创建你的第一个自定义 Combo](#三步创建你的第一个自定义-combo) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有 Combo 类型都不满足需求，你可以基于 G 的底层图形系统从零创建 Combo。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制 Combo 的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有 Combo 类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义 Combo 需要自行处理所有细节，包括图形绘制、事件响应、状态变化、展开/收起逻辑等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/combos/base-combo.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义 Combo\n\n让我们从继承 `BaseCombo` 开始，实现一个自定义六边形 Combo ：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseCombo, ExtensionCategory } from '@antv/g6';\n\n// 定义收起状态的按钮路径\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\n// 定义展开状态的按钮路径\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  getKeyPath(attributes) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建SVG路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式\n  getKeyStyle(attributes) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形\n  drawKeyShape(attributes, container) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制展开/收起按钮，使用路径实现更精细的控制\n  drawCollapseButton(attributes) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 重写render方法，添加更多自定义图形\n  render(attributes, container) {\n    super.render(attributes, container);\n    this.drawCollapseButton(attributes, container);\n  }\n\n  // 使用生命周期钩子添加事件监听\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n\n// 注册自定义 Combo\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n\n// 创建图实例并使用自定义 Combo\nconst graph = new Graph({\n  container: 'container',\n  height: 250,\n  data: {\n    nodes: [\n      { id: 'node1', combo: 'combo1', style: { x: 100, y: 100 } },\n      { id: 'node2', combo: 'combo1', style: { x: 150, y: 150 } },\n      { id: 'node3', combo: 'combo2', style: { x: 300, y: 100 } },\n      { id: 'node4', combo: 'combo2', style: { x: 350, y: 150 } },\n    ],\n    combos: [\n      { id: 'combo1', data: { label: 'Hexagon 1' } },\n      { id: 'combo2', data: { label: 'Hexagon 2' }, style: { collapsed: true } },\n    ],\n  },\n  node: {\n    style: {\n      fill: '#91d5ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n    },\n  },\n  combo: {\n    type: 'hexagon-combo',\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义 Combo 类\n\n```typescript\nimport { BaseCombo } from '@antv/g6';\nimport type { BaseComboStyleProps } from '@antv/g6';\n\n// 定义按钮路径生成函数\nconst collapse = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x + r - 4, y],\n  ];\n};\n\nconst expand = (x, y, r) => {\n  return [\n    ['M', x - r, y],\n    ['a', r, r, 0, 1, 0, r * 2, 0],\n    ['a', r, r, 0, 1, 0, -r * 2, 0],\n    ['M', x - r + 4, y],\n    ['L', x - r + 2 * r - 4, y],\n    ['M', x - r + r, y - r + 4],\n    ['L', x, y + r - 4],\n  ];\n};\n\nclass HexagonCombo extends BaseCombo {\n  // 获取六边形的路径\n  protected getKeyPath(attributes: Required<BaseComboStyleProps>) {\n    const [width, height] = this.getKeySize(attributes);\n    const padding = 10;\n    const size = Math.min(width, height) + padding;\n\n    // 计算六边形的顶点\n    const points = [];\n    for (let i = 0; i < 6; i++) {\n      const angle = (Math.PI / 3) * i;\n      const x = (size / 2) * Math.cos(angle);\n      const y = (size / 2) * Math.sin(angle);\n      points.push([x, y]);\n    }\n\n    // 构建 SVG 路径\n    const path = [['M', points[0][0], points[0][1]]];\n    for (let i = 1; i < 6; i++) {\n      path.push(['L', points[i][0], points[i][1]]);\n    }\n    path.push(['Z']);\n\n    return path;\n  }\n\n  // 获取主图形样式，直接使用路径数据\n  protected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n    const style = super.getKeyStyle(attributes);\n\n    return {\n      ...style,\n      d: this.getKeyPath(attributes),\n      fill: attributes.collapsed ? '#FF9900' : '#F04864',\n      fillOpacity: attributes.collapsed ? 0.5 : 0.2,\n      stroke: '#54BECC',\n      lineWidth: 2,\n    };\n  }\n\n  // 绘制主图形，使用 path 类型直接传入样式对象\n  protected drawKeyShape(attributes: Required<BaseComboStyleProps>, container: Group) {\n    return this.upsert('key', 'path', this.getKeyStyle(attributes), container);\n  }\n\n  // 绘制收起/展开按钮，使用 SVG 路径实现更精细的控制\n  protected drawCollapseButton(attributes: Required<BaseComboStyleProps>) {\n    const { collapsed } = attributes;\n    const [width] = this.getKeySize(attributes);\n    const btnR = 8;\n    const x = width / 2 + btnR;\n    const d = collapsed ? expand(x, 0, btnR) : collapse(x, 0, btnR);\n\n    // 创建点击区域和按钮图形\n    const hitArea = this.upsert('hit-area', 'circle', { cx: x, r: 8, fill: '#fff', cursor: 'pointer' }, this);\n    this.upsert('button', 'path', { stroke: '#54BECC', d, cursor: 'pointer', lineWidth: 1.4 }, hitArea);\n  }\n\n  // 使用生命周期钩子方法绑定事件\n  onCreate() {\n    this.shapeMap['hit-area'].addEventListener('click', () => {\n      const id = this.id;\n      const collapsed = !this.attributes.collapsed;\n      const { graph } = this.context;\n      if (collapsed) graph.collapseElement(id);\n      else graph.expandElement(id);\n    });\n  }\n}\n```\n\n### 第二步：注册自定义 Combo\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.COMBO, 'hexagon-combo', HexagonCombo);\n```\n\n### 第三步：应用自定义 Combo\n\n```js\nconst graph = new Graph({\n  // ...其他配置\n  combo: {\n    type: 'hexagon-combo', // 使用注册时的名称\n    style: {\n      padding: 20,\n      showCollapseButton: true,\n      labelText: (d) => d.data?.label,\n      labelPlacement: 'top',\n    },\n  },\n  // 由于我们自己实现了折叠展开功能，这里只需要拖拽行为\n  behaviors: ['drag-element'],\n});\n```\n\n🎉 恭喜！你已经创建了第一个自定义 Combo 。\n\n## 更进一步：理解 Combo 绘制的原理\n\n### Combo 与节点的区别\n\n虽然 Combo 继承自 `BaseNode`，但有一些关键区别：\n\n1. **自适应大小**： Combo 会根据内部元素自动计算合适的大小\n2. **展开/收起状态**： Combo 有两种显示状态，并需要处理状态切换\n3. **层级结构**： Combo 可以嵌套，形成层级关系\n4. **内部元素管理**： Combo 需要管理其包含的节点和子 Combo\n\n### 原子图形\n\nG6 的 Combo 是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。原子图形的介绍请参考 [元素 - 图形（可选）](/manual/element/shape/overview) 文档。\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义 Combo 之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义 Combo 时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                    |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见 [元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                  |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                                |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                          |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染组合的主入口\n\n每个自定义 Combo 类都必须实现 `render(attributes, container)` 方法，它定义了该组合如何被\"绘制\"出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n组合中约定的元素属性包括：\n\n- 通过 `this.getKeySize(attributes)` 获取组合的尺寸，考虑折叠状态和子元素\n- 通过 `this.getContentBBox(attributes)` 获取内容区域的边界盒\n- 通过 `this.getComboPosition(attributes)` 获取组合的当前位置，基于状态和子元素\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义 Combo 中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                   | 典型用途                                     |\n| ----------- | -------------------------- | -------------------------------------------- |\n| `onCreate`  | 当组合创建后完成入场动画时 | 绑定交互事件、初始化组合状态、添加外部监听器 |\n| `onUpdate`  | 当组合更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果     |\n| `onDestroy` | 当组合完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知       |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **\"状态响应\"** 与 **\"绘制逻辑\"** 分离。\n\n你可以在组合配置中定义每种状态下的样式：\n\n```js\ncombo: {\n  type: 'custom-combo',\n  style: {\n    fill: '#f0f2f5',\n    stroke: '#d9d9d9'\n  },\n  state: {\n    selected: {\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    },\n    hover: {\n      fill: '#e6f7ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(comboId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseComboStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/overview.en.md) -->\n---\ntitle: Combo Overview\norder: 0\n---\n\n## What is a Combo\n\nA Combo, short for Combination, is a special type of graph element in G6 that can contain nodes and sub-combos, similar to the concept of \"groups\" or \"containers.\" It is typically used to represent set relationships, such as a department containing multiple employees or a city containing multiple regions.\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=Note}\nIt is not recommended to use Combos in **tree graphs**. The layout mechanism of tree graphs is incompatible with that of Combos, which can lead to node misalignment or style confusion.\n:::\n\nG6 has built-in Combos including `circle` (circular combo) and `rect` (rectangular combo), as shown in the images below:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## Data Structure\n\nWhen defining a Combo, you need to add a `combos` field to the graph's data object. Each Combo is an object with the following structure:\n\n| Attribute | Description                                                                                            | Type           | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------ | -------------- | ------- | -------- |\n| id        | Unique identifier of the combo                                                                         | string         | -       | ✓        |\n| type      | Combo type, name of built-in combo type or custom combo name, such as `circle` or `rect`               | string         | -       |          |\n| data      | Combo data, used to store custom data of the combo, accessible via callback functions in style mapping | object         | -       |          |\n| style     | Combo style                                                                                            | object         | -       |          |\n| states    | Initial states of the combo                                                                            | string[]       | -       |          |\n| combo     | Parent combo ID. If there is no parent combo, it is null                                               | string \\| null | -       |          |\n\nAn example of a data item in the `combos` array:\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\nTo assign a node to a Combo, you can add a `combo` field to the node data:\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 belongs to comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // define comboA\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure Combos, listed in order of priority from highest to lowest:\n\n- Use `graph.setCombo()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setCombo()`\n\nYou can dynamically set the style mapping logic of Combos using `graph.setCombo()` after the graph instance is created.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nYou can configure Combo style mapping globally during graph instantiation. This configuration will apply to all Combos.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Specify combo type and combo style type in the combo configuration\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different Combos, you can write the configuration into the Combo data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\n// Specify combo type and combo style type in the data\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## Example\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo Interaction\n\nSimply rendering a Combo does not provide much practical value; it is only when a series of interactive operations are supported that the value of Combos can be maximized.\n\nIn G6, we have built-in interactions such as `drag-element` and `collapse-expand`.\n\n#### drag-element\n\nSupports dragging nodes and Combos. During the dragging of a Combo, the positions of nodes and edges within the Combo will dynamically change. After dragging is complete, the relative positions of the Combo and nodes remain unchanged. You can also change the affiliation of the Combo during dragging by setting `dropEffect: 'link'`.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\nSupports double-clicking a Combo to collapse and expand it. After collapsing a Combo, all nodes within the Combo are hidden. If there are connections between external nodes and nodes within the Combo, all connections will connect to the Combo.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## Custom Combos\n\nWhen built-in Combos cannot meet your needs, G6 provides powerful customization capabilities:\n\n- Extend built-in Combos\n- Create new Combo types\n\nUnlike Combos, custom Combos need to be registered before use. For detailed tutorials, please refer to the [Custom Combo](/en/manual/element/combo/custom-combo) documentation.\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/overview.zh.md) -->\n---\ntitle: 组合总览\norder: 0\n---\n\n## 什么是组合\n\n组合(Combo) 全称为 Combination，是 G6 中的一种特殊的图元素，它可以包含节点和子组合，类似“群组”或“容器”的概念。它通常用于表示集合关系，例如一个部门包含多个员工，一个城市包含多个区域等。\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n:::warning{title=注意}\n不推荐在**树图**中使用 Combo。因为树图的布局与 Combo 的布局机制不兼容，容易导致节点错位或样式混乱。\n:::\n\nG6 的内置 Combo 包括 `circle`（圆形组合）和 `rect` (矩形组合) 两种类型，分别如下图所示：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kbk1S5pzSY0AAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PKtgSZzmb3YAAAAAAAAAAAAADmJ7AQ/original\" width=\"200\" />\n\n## 数据结构\n\n定义 Combo 时，需要在图的数据对象中添加 `combos` 字段，每个 Combo 是一个对象，结构如下：\n\n| 属性   | 描述                                                                    | 类型           | 默认值 | 必选 |\n| ------ | ----------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                        | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称，比如 `circle` 或者 `rect` | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取    | object         | -      |      |\n| style  | 组合样式                                                                | object         | -      |      |\n| states | 组合初始状态                                                            | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                              | string \\| null | -      |      |\n\n`combos` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"combo1\",\n  \"type\": \"circle\",\n  \"data\": { \"groupName\": \"Group A\" },\n  \"style\": { \"fill\": \"lightblue\", \"stroke\": \"blue\", \"collapsed\": true },\n  \"states\": [],\n  \"combo\": null\n}\n```\n\n要将节点归属到某个 Combo，可以在节点数据中添加 `combo` 字段：\n\n```json\n{\n  \"nodes\": [{ \"id\": \"node1\", \"combo\": \"comboA\" }], // node1 属于 comboA\n  \"combos\": [{ \"id\": \"comboA\" }] // 定义 comboA\n}\n```\n\n## 配置方法\n\n配置 Combo 的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setCombo()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setCombo()`\n\n可在图实例创建后，使用 `graph.setCombo()` 动态设置 Combo 的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setCombo({\n  style: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `combo` 配置 Combo 样式映射，这里的配置是全局的配置，将会在所有 Combo 上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 在组合配置中指定组合类型以及组合样式类型\n  combo: {\n    type: 'circle',\n    style: { fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同 Combo 进行不同的配置，可以将配置写入到 Combo 数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\n// 在数据中指定组合类型以及组合样式类型\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  combos: [\n    {\n      id: 'combo-1',\n      type: 'circle',\n      style: { size: 100, stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  combo: {\n    type: (d) => d.type || 'rect',\n    style: {\n      stroke: (d) => d.style.stroke || 'blue',\n    },\n  },\n});\n```\n\n## 示例\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      combo: 'combo1',\n      style: { x: 245, y: 200 },\n    },\n    {\n      id: 'node2',\n      combo: 'combo1',\n      style: { x: 210, y: 250 },\n    },\n    {\n      id: 'node3',\n      combo: 'combo1',\n      style: { x: 280, y: 245 },\n    },\n    {\n      id: 'node4',\n      combo: 'combo2',\n      style: { x: 400, y: 165 },\n    },\n    {\n      id: 'node5',\n      combo: 'combo2',\n      style: { x: 450, y: 162 },\n    },\n    {\n      id: 'node6',\n      combo: 'combo3',\n      style: { x: 425, y: 300 },\n    },\n    {\n      id: 'node7',\n      combo: 'combo3',\n      style: { x: 360, y: 332 },\n    },\n  ],\n  edges: [],\n  combos: [\n    {\n      id: 'combo1',\n      combo: 'combo3',\n      data: { label: 'Combo A' },\n    },\n    {\n      id: 'combo2',\n      combo: 'combo3',\n      data: { label: 'Combo B' },\n    },\n    {\n      id: 'combo3',\n      data: { label: 'Combo C' },\n    },\n    {\n      id: 'combo4',\n      data: { label: 'Combo D' },\n      style: { x: 58, y: 248 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  height: 450,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n      labelFontSize: 10,\n    },\n  },\n  combo: {\n    type: 'circle',\n    style: {\n      padding: 2,\n      labelText: (d) => d.data.label,\n      labelPlacement: 'top',\n    },\n  },\n  behaviors: [\n    'collapse-expand',\n    {\n      type: 'drag-element',\n      dropEffect: 'link',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Combo 交互\n\n只是简单地将 Combo 渲染出来，并没有多大的实用价值，只有支持一系列的交互操作后，才能最大程度地体现 Combo 的价值。\n\n在 G6 中，我们内置了 `drag-element`、`collapse-expand` 三个交互。\n\n#### drag-element\n\n支持拖动节点和 Combo。拖动 Combo 过程中，会动态改变 Combo 中节点和边的位置，在拖拽完成以后，保持 Combo 和节点的相对位置不变。还可以通过设置 `dropEffect: 'link'` 在拖拽时改变 Combo 的从属关系。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rJiHQahxgj4AAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n#### collapse-expand\n\n支持双击 Combo 收起和展开 Combo ，收起 Combo 以后，隐藏 Combo 中的所有节点，外部节点和 Combo 中节点有连线的情况下，所有连接会连接到 Combo 上面。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*PfnsSZSkRagAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" />\n\n## 自定义组合\n\n当内置组合无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置组合进行扩展\n- 创建全新的组合类型\n\n与组合不同，自定义组合需要先注册后使用。详细教程请参考 [自定义组合](/manual/element/combo/custom-combo) 文档。\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/RectCombo.en.md) -->\n---\ntitle: Rect Combo\norder: 3\n---\n\n## Overview\n\nThe rectangular combo organizes content with right-angle boundaries, supporting strict hierarchical structures.\n\nApplicable scenarios:\n\n- **System Architecture Diagrams**: Such as service layering within system architecture, and subdivisions within each layer.\n- **Geographical Area Division**: Such as cities containing multiple areas, where the rectangular combo can intuitively display administrative boundaries or functional divisions.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## Style Configuration\n\n> If the element has its specific attributes, we will list them below. For all general style attributes, see [BaseCombo](/en/manual/element/combo/base-combo)\n\n## Example\n\nThe following example is a simple microservice architecture service layer:\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n\n\n<!-- Skill/Rule: Combo Skill (packages/site/docs/manual/element/combo/RectCombo.zh.md) -->\n---\ntitle: 矩形组合 Rect\norder: 3\n---\n\n## 概述\n\n矩形组合以直角边界组织内容，支持严格的层级结构。\n\n适用场景：\n\n- **系统架构图**：如系统架构里面的服务分层，以及每层服务里面的细分等。\n- **地理区域划分**：如城市包含多个区域，矩形组合能直观展示行政边界或功能分区。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/combos/rect-combo.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseCombo](/manual/element/combo/base-combo)\n\n## 示例\n\n以下示例为简单的微服务架构服务层：\n\n<embed src=\"@/common/api/elements/combos/rect-combo-architecture.md\"></embed>\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/BaseEdge.en.md) -->\n---\ntitle: Edge Common Configuration\norder: 1\n---\n\nThis document introduces the built-in edge common property configurations.\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // Edge type\n    style: {}, // Edge style\n    state: {}, // State styles\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name         | [Type](#type)           | `line`  |          |\n| style     | Edge style configuration, including color, thickness, etc.     | [Style](#style)         | -       |          |\n| state     | Style configuration for different states                       | [State](#state)         | -       |          |\n| palette   | Define edge palette for mapping colors based on different data | [Palette](#palette)     | -       |          |\n| animation | Define edge animation effects                                  | [Animation](#animation) | -       |          |\n\n## Type\n\nSpecify the edge type, built-in edge type name or custom edge name. Default is `line` (straight line edge). **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: The `type` property also supports dynamic configuration, allowing you to dynamically select edge types based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    // Static configuration\n    type: 'line',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `line`: [Straight line edge](/en/manual/element/edge/line)\n- `polyline`: [Polyline edge](/en/manual/element/edge/polyline)\n- `cubic`: [Cubic Bezier curve edge](/en/manual/element/edge/cubic)\n- `cubic-horizontal`: [Horizontal cubic Bezier curve edge](/en/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`: [Vertical cubic Bezier curve edge](/en/manual/element/edge/cubic-vertical)\n- `quadratic`: [Quadratic Bezier curve edge](/en/manual/element/edge/quadratic)\n\n## Style\n\nDefine edge styles, including color, thickness, etc.\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration Note**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on edge data:\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // Static configuration\n      stroke: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineDash: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Edge: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the edge data object (`EdgeData`), containing all data information of the edge.\n\nA complete edge consists of the following parts:\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the main path of the edge, such as straight lines, curves, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `badge`: Badge on the edge\n- `halo`: The halo effect graphic displayed around the main graphic\n- `startArrow`: Arrow at the starting end of the edge\n- `endArrow`: Arrow at the ending end of the edge\n\nThe following style configurations will be explained by atomic graphics in order:\n\n### Main Graphic Styles\n\nThe main graphic is the core part of the edge, defining the basic path and appearance of the edge. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSet the basic appearance of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // Blue edge\n      lineWidth: 2, // Edge width\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Line Style\n\nCreate edges with dashed line style:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // Dashed line style\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Shadow Effect\n\nAdd shadow effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete main graphic style configuration:\n\n| Property                        | Description                                                                                                                        | Type                  | Default   | Required |\n| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------- | -------- |\n| cursor                          | Mouse cursor style when hovering over edge, [options](#cursor)                                                                     | string                | `default` |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. We can increase this area to make \"thin lines\" easier to pick up | number                | 0         |          |\n| lineDash                        | Edge dash line style                                                                                                               | number[]              | -         |          |\n| lineDashOffset                  | Edge dash line offset                                                                                                              | number                | 0         |          |\n| lineWidth                       | Edge width                                                                                                                         | number                | 1         |          |\n| opacity                         | Edge opacity                                                                                                                       | number \\| string      | 1         |          |\n| pointerEvents                   | How edge responds to pointer events, [options](#pointerevents)                                                                     | string                | `auto`    |          |\n| shadowBlur                      | Edge shadow blur                                                                                                                   | number                | -         |          |\n| shadowColor                     | Edge shadow color                                                                                                                  | string                | -         |          |\n| shadowOffsetX                   | Edge shadow offset in x direction                                                                                                  | number \\| string      | -         |          |\n| shadowOffsetY                   | Edge shadow offset in y direction                                                                                                  | number \\| string      | -         |          |\n| shadowType                      | Edge shadow type                                                                                                                   | `inner` \\| `outer`    | `outer`   |          |\n| sourcePort                      | Connection port at the source end of the edge                                                                                      | string                | -         |          |\n| stroke                          | Edge color                                                                                                                         | string                | `#000`    |          |\n| strokeOpacity                   | Edge color opacity                                                                                                                 | number \\| string      | 1         |          |\n| targetPort                      | Connection port at the target end of the edge                                                                                      | string                | -         |          |\n| transform                       | Transform property allows you to rotate, scale, skew, or translate the given edge                                                  | string                | -         |          |\n| transformOrigin                 | The center of rotation and scaling, also known as the transform center                                                             | string                | -         |          |\n| visibility                      | Whether the edge is visible                                                                                                        | `visible` \\| `hidden` | `visible` |          |\n| zIndex                          | Edge rendering layer                                                                                                               | number                | 1         |          |\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. Refer to [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, both `stroke` and `visibility` can independently or in combination affect hit testing behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Never becomes a target for responding to events\n- **`visiblepainted`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n- **`visiblestroke`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`visible`**: Responds to events only when the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n- **`painted`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area while `stroke` takes a non-`none` value\n  - Not affected by `visibility` value\n- **`stroke`**: Responds to events only when the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by `stroke` value\n  - Not affected by `visibility` value\n- **`all`**: Responds to events as long as entering the graphic stroke area, not affected by `stroke` or `visibility` values\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely non-responsive to events\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // Edge does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Styles\n\nLabels are used to display text information for edges, supporting various style configurations and layout options. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Edge Label',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'This is a very long edge label that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdd background to labels for better readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Important Connection',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Auto-rotating Label\n\nLabels can automatically rotate to align with edge direction:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: 'Auto Rotate',\n      labelAutoRotate: true, // Auto rotate\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete label style configuration:\n\n| Property                 | Description                                                                                                     | Type                                                                        | Default   | Required |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to show edge label                                                                                      | boolean                                                                     | true      |          |\n| labelAutoRotate          | Whether edge label automatically rotates to align with edge direction                                           | boolean                                                                     | true      |          |\n| labelCursor              | Mouse cursor style when hovering over edge label, [options](#cursor)                                            | string                                                                      | `default` |          |\n| labelFill                | Edge label text color                                                                                           | string                                                                      | -         |          |\n| labelFontFamily          | Edge label font family                                                                                          | string                                                                      | -         |          |\n| labelFontSize            | Edge label font size                                                                                            | number                                                                      | 12        |          |\n| labelFontStyle           | Edge label font style                                                                                           | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Edge label font variant                                                                                         | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Edge label font weight                                                                                          | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                    | number                                                                      | 0         |          |\n| labelLetterSpacing       | Edge label letter spacing                                                                                       | number \\| string                                                            | -         |          |\n| labelLineHeight          | Edge label line height                                                                                          | number \\| string                                                            | -         |          |\n| labelMaxLines            | Edge label maximum lines                                                                                        | number                                                                      | 1         |          |\n| labelMaxWidth            | Edge label maximum width, [options](#labelmaxwidth)                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Edge label offset in x direction                                                                                | number                                                                      | 0         |          |\n| labelOffsetY             | Edge label offset in y direction                                                                                | number                                                                      | 0         |          |\n| labelPadding             | Edge label padding                                                                                              | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Edge label position relative to edge, [options](#labelplacement)                                                | string \\| number                                                            | `center`  |          |\n| labelText                | Edge label text content                                                                                         | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Edge label text horizontal alignment                                                                            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Edge label text baseline                                                                                        | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Edge label text decoration line color                                                                           | string                                                                      | -         |          |\n| labelTextDecorationLine  | Edge label text decoration line                                                                                 | string                                                                      | -         |          |\n| labelTextDecorationStyle | Edge label text decoration line style                                                                           | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Edge label text overflow handling                                                                               | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Edge label text path                                                                                            | Path                                                                        | -         |          |\n| labelWordWrap            | Whether to enable automatic line wrapping for edge labels. When enabled, text exceeding labelMaxWidth will wrap | boolean                                                                     | false     |          |\n| labelZIndex              | Edge label rendering layer                                                                                      | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nEdge label position relative to the edge, can be set to:\n\n- `start`: Label positioned at the starting point of the edge\n- `center`: Label positioned at the center of the edge (default)\n- `end`: Label positioned at the ending point of the edge\n- `number`: Value range 0-1, representing the specific position ratio of the label on the edge, 0 for start position, 1 for end position\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text exceeding this width will wrap:\n\n- string: Represents the maximum width defined as a percentage relative to the edge length. For example, `50%` means the label width does not exceed half the edge length\n- number: Represents the maximum width defined in pixels. For example, 100 means the label's maximum width is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Styles\n\nLabel background is used to display the background of edge labels:\n\n| Property                      | Description                                                                                                                                                       | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to show edge label background                                                                                                                             | boolean                                  | false     |\n| labelBackgroundCursor         | Edge label background mouse cursor style, [options](#cursor)                                                                                                      | string                                   | `default` |\n| labelBackgroundFill           | Edge label background fill color                                                                                                                                  | string                                   | -         |\n| labelBackgroundFillOpacity    | Edge label background opacity                                                                                                                                     | number                                   | 1         |\n| labelBackgroundHeight         | Edge label background height                                                                                                                                      | string \\| number                         | -         |\n| labelBackgroundLineDash       | Edge label background dash line configuration                                                                                                                     | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Edge label background dash line offset                                                                                                                            | number                                   | -         |\n| labelBackgroundLineWidth      | Edge label background stroke line width                                                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | Edge label background border radius <br> - number: Uniform radius for all corners <br> - number[]: Individual radius for each corner, auto-filled if insufficient | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Edge label background shadow blur                                                                                                                                 | number                                   | -         |\n| labelBackgroundShadowColor    | Edge label background shadow color                                                                                                                                | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Edge label background shadow X offset                                                                                                                             | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Edge label background shadow Y offset                                                                                                                             | number                                   | -         |\n| labelBackgroundStroke         | Edge label background stroke color                                                                                                                                | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Edge label background stroke opacity                                                                                                                              | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Edge label background visibility                                                                                                                                  | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Edge label background rendering layer                                                                                                                             | number                                   | 1         |\n\n### Halo Styles\n\nHalo is an effect displayed around the edge main graphic, usually used for highlighting or indicating special states of the edge.\n\n#### Basic Halo Effect\n\nAdd basic halo effect to edges:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete halo style configuration:\n\n| Property          | Description                                                                          | Type                   | Default                                   | Required |\n| ----------------- | ------------------------------------------------------------------------------------ | ---------------------- | ----------------------------------------- | -------- |\n| halo              | Whether to show edge halo                                                            | boolean                | false                                     |          |\n| haloCursor        | Edge halo mouse cursor style, [options](#cursor)                                     | string                 | `default`                                 |          |\n| haloDraggable     | Whether edge halo allows dragging                                                    | boolean                | true                                      |          |\n| haloDroppable     | Whether edge halo allows receiving dragged elements                                  | boolean                | true                                      |          |\n| haloFillRule      | Edge halo fill rule                                                                  | `nonzero` \\| `evenodd` | -                                         |          |\n| haloFilter        | Edge halo filter                                                                     | string                 | -                                         |          |\n| haloLineWidth     | Edge halo stroke width                                                               | number                 | 3                                         |          |\n| haloPointerEvents | Whether edge halo responds to pointer events, [options](#pointerevents)              | string                 | `none`                                    |          |\n| haloStroke        | Edge halo stroke color, **this property sets the color of the halo around the edge** | string                 | Consistent with main graphic stroke color |          |\n| haloStrokeOpacity | Edge halo stroke opacity                                                             | number                 | 0.25                                      |          |\n| haloVisibility    | Edge halo visibility                                                                 | `visible` \\| `hidden`  | `visible`                                 |          |\n| haloZIndex        | Edge halo rendering layer                                                            | number                 | -1                                        |          |\n\n### Arrow Styles\n\nEdges support adding arrows at the start and end points to indicate the directionality of the edge.\n\n#### Basic Arrow\n\nAdd basic arrow to the end of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // End arrow\n      endArrowType: 'vee', // Arrow type\n      endArrowSize: 10, // Arrow size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Bidirectional Arrows\n\nAdd arrows to both ends of the edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // Start arrow\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // End arrow\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Arrow Style\n\nCustomize arrow color and type:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // Diamond arrow\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // Red arrow fill\n      endArrowStroke: '#722ED1', // Arrow stroke color\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Start Arrow Style Configuration\n\n| Property                | Description                                             | Type                                                                                 | Default                            | Required |\n| ----------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| startArrow              | Whether to show edge start arrow                        | boolean                                                                              | false                              |          |\n| startArrowCursor        | Edge start arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| startArrowFill          | Edge start arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| startArrowFillOpacity   | Edge start arrow fill opacity                           | number                                                                               | 1                                  |          |\n| startArrowOffset        | Edge start arrow offset                                 | number                                                                               | 0                                  |          |\n| startArrowSize          | Edge start arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| startArrowStroke        | Edge start arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| startArrowStrokeOpacity | Edge start arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| startArrowType          | Edge start arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n#### End Arrow Style Configuration\n\n| Property              | Description                                           | Type                                                                                 | Default                            | Required |\n| --------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- | -------- |\n| endArrow              | Whether to show edge end arrow                        | boolean                                                                              | false                              |          |\n| endArrowCursor        | Edge end arrow mouse cursor style, [options](#cursor) | string                                                                               | `default`                          |          |\n| endArrowFill          | Edge end arrow fill color                             | string                                                                               | Default consistent with edge color |          |\n| endArrowFillOpacity   | Edge end arrow fill opacity                           | number                                                                               | 1                                  |          |\n| endArrowOffset        | Edge end arrow offset                                 | number                                                                               | 0                                  |          |\n| endArrowSize          | Edge end arrow size                                   | number \\| [number, number]                                                           | 10                                 |          |\n| endArrowStroke        | Edge end arrow stroke color                           | string                                                                               | Default consistent with edge color |          |\n| endArrowStrokeOpacity | Edge end arrow stroke opacity                         | number                                                                               | 1                                  |          |\n| endArrowType          | Edge end arrow type                                   | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`                              |          |\n\n### Loop Edge Styles\n\nLoop edges are special edges where the start and end nodes are the same node.\n\n#### Basic Loop Edge\n\nCreate a basic loop edge:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // Loop position\n      loopDist: 30, // Loop size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Loop Edges\n\nCreate multiple loop edges at different positions for the same node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe following is the complete loop edge style configuration:\n\n| Property      | Description                                                         | Type                                                                                                                                                                   | Default                  | Required |\n| ------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -------- |\n| loop          | Whether to enable loop edges                                        | boolean                                                                                                                                                                | true                     |          |\n| loopClockwise | Whether to draw the loop clockwise                                  | boolean                                                                                                                                                                | true                     |          |\n| loopDist      | Distance from node edge to loop top, used to specify loop curvature | number                                                                                                                                                                 | Default to max node size |          |\n| loopPlacement | Loop edge position                                                  | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                    |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select an edge or hovering to activate an edge, it's simply marking certain states on that element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of that graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. Additionally, it supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\nFor example, when an edge is in the `focus` state, you can add a halo with a width of 6 and orange color.\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefine edge animation effects. Supports the following two configuration methods:\n\n1. Disable all edge animations\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to the animation effects when edges enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when edge enters the canvas\n- `update`: Animation when edge updates\n- `exit`: Animation when edge leaves the canvas\n- `show`: Animation when edge shows from hidden state\n- `hide`: Animation when edge hides\n- `collapse`: Animation when edge collapses\n- `expand`: Animation when edge expands\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#动画范式) to use animation syntax to configure edges, such as:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // Only animate stroke property during update\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"path-in\", // Use path animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable specific stage animations:\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // Disable edge entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefine the edge palette, which is a predefined edge color pool that is allocated according to rules and maps colors to the `stroke` property.\n\n> For palette definitions, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to using id as grouping field                  | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                     | `group` \\| `value`            | `group` |\n\nFor example, to assign edge colors to a group of data by the `direction` field, making edges of the same category have the same color:\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau is the palette name, colors assigned by ID by default\n  }\n}\n```\n\nThe effect is shown in the following image:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/BaseEdge.zh.md) -->\n---\ntitle: 边通用配置项\norder: 1\n---\n\n本文介绍内置边通用属性配置。\n\n## EdgeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line', // 边类型\n    style: {}, // 边样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                   | 类型                    | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](#type)           | `line` |      |\n| style     | 边样式配置，包括颜色、粗细等           | [Style](#style)         | -      |      |\n| state     | 不同状态下的样式配置                   | [State](#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](#animation) | -      |      |\n\n## Type\n\n指定边类型，内置边类型名称或自定义边的名称。默认为 `line`（直线边）。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    type: 'polyline',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据边数据动态选择边类型：\n\n```js\nconst graph = new Graph({\n  edge: {\n    // 静态配置\n    type: 'line',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.edgeType || 'line',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.importance > 5 ? 'polyline' : 'line';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `line`：[直线边](/manual/element/edge/line)\n- `polyline`：[折线边](/manual/element/edge/polyline)\n- `cubic`：[三次贝塞尔曲线边](/manual/element/edge/cubic)\n- `cubic-horizontal`：[水平三次贝塞尔曲线边](/manual/element/edge/cubic-horizontal)\n- `cubic-vertical`：[垂直三次贝塞尔曲线边](/manual/element/edge/cubic-vertical)\n- `quadratic`：[二次贝塞尔曲线边](/manual/element/edge/quadratic)\n\n## Style\n\n定义边的样式，包括颜色、粗细等。\n\n```js {3}\nconst graph = new Graph({\n  edge: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据边数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  edge: {\n    style: {\n      // 静态配置\n      stroke: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      lineWidth: (datum) => (datum.data.isImportant ? 3 : 1),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineDash: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.type === 'dashed' ? [5, 5] : [];\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `边: ${datum.id}`,\n      endArrow: (datum) => datum.data.hasArrow,\n    },\n  },\n});\n```\n\n其中 `datum` 参数为边数据对象 (`EdgeData`)，包含边的所有数据信息。\n\n一个完整的边由以下几部分构成：\n\n<img width=\"320\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*cVHVQJKLOlgAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要路径，例如直线、曲线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `badge` ：边上的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `startArrow` ：边起始端的箭头；\n- `endArrow` ：边结束端的箭头。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是边的核心部分，定义了边的基本路径和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置边的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#5B8FF9', // 蓝色边\n      lineWidth: 2, // 边宽度\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线样式\n\n创建带虚线样式的边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4], // 虚线样式\n      lineDashOffset: 0,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 阴影效果\n\n为边添加阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 40 } },\n      { id: 'node2', style: { x: 180, y: 40 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      shadowColor: 'rgba(114, 46, 209, 0.3)',\n      shadowBlur: 8,\n      shadowOffsetX: 2,\n      shadowOffsetY: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                  | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | --------------------- | --------- | ---- |\n| cursor                          | 边鼠标移入样式，[配置项](#cursor)                                                         | string                | `default` |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                | 0         |      |\n| lineDash                        | 边虚线样式                                                                                | number[]              | -         |      |\n| lineDashOffset                  | 边虚线偏移量                                                                              | number                | 0         |      |\n| lineWidth                       | 边宽度                                                                                    | number                | 1         |      |\n| opacity                         | 边透明度                                                                                  | number \\| string      | 1         |      |\n| pointerEvents                   | 边如何响应指针事件，[配置项](#pointerevents)                                              | string                | `auto`    |      |\n| shadowBlur                      | 边阴影模糊度                                                                              | number                | -         |      |\n| shadowColor                     | 边阴影颜色                                                                                | string                | -         |      |\n| shadowOffsetX                   | 边阴影在 x 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowOffsetY                   | 边阴影在 y 轴方向上的偏移量                                                               | number \\| string      | -         |      |\n| shadowType                      | 边阴影类型                                                                                | `inner` \\| `outer`    | `outer`   |      |\n| sourcePort                      | 边起始连接的连接桩                                                                        | string                | -         |      |\n| stroke                          | 边颜色                                                                                    | string                | `#000`    |      |\n| strokeOpacity                   | 边颜色透明度                                                                              | number \\| string      | 1         |      |\n| targetPort                      | 边终点连接的连接桩                                                                        | string                | -         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定边                                          | string                | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                | -         |      |\n| visibility                      | 边是否可见                                                                                | `visible` \\| `hidden` | `visible` |      |\n| zIndex                          | 边渲染层级                                                                                | number                | 1         |      |\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的描边区域就会响应事件，不会受 `stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  edge: {\n    style: {\n      pointerEvents: 'none', // 边不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示边的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '边标签',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '这是一个很长的边标签需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '200%',\n      labelMaxLines: 2,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'center',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 60 } },\n      { id: 'node2', style: { x: 180, y: 60 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '重要连接',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [4, 8],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自动旋转标签\n\n标签可以自动旋转以保持与边方向一致：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 120,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 30 } },\n      { id: 'node2', style: { x: 180, y: 90 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      labelText: '自动旋转',\n      labelAutoRotate: true, // 自动旋转\n      labelFill: '#1890FF',\n      labelFontWeight: 'bold',\n      labelPlacement: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                             | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 边标签是否显示                                                                   | boolean                                                                     | true      |      |\n| labelAutoRotate          | 边标签是否自动旋转，保持与边的方向一致                                           | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入边标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 边标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 边标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 边标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 边标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 边标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 边标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                           | number                                                                      | 0         |      |\n| labelLetterSpacing       | 边标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 边标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 边标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 边标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 边标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 边标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 边标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 边标签相对于边的位置，[配置项](#labelplacement)                                  | string \\| number                                                            | `center`  |      |\n| labelText                | 边标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 边标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 边标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 边标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 边标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 边标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 边标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 边标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 边标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 边标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n边标签相对于边的位置，可以设置为：\n\n- `start`：标签位于边的起始位置\n- `center`：标签位于边的中心位置（默认）\n- `end`：标签位于边的结束位置\n- `number`：取值范围为 0-1，表示标签在边上的具体位置比例，0 为起始位置，1 为结束位置\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于边长度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过边长度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示边标签的背景：\n\n| 属性                          | 描述                                                                                                         | 类型                                     | 默认值    |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | --------- |\n| labelBackground               | 边标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 边标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 边标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 边标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 边标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 边标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 边标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 边标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 边标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 边标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 边标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 边标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 边标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 边标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 边标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 边标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 边标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕边主图形显示的效果，通常用于高亮显示或表示边的特殊状态。\n\n#### 基础光晕效果\n\n为边添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                 | 类型                   | 默认值                         | 必选 |\n| ----------------- | ---------------------------------------------------- | ---------------------- | ------------------------------ | ---- |\n| halo              | 边光晕是否显示                                       | boolean                | false                          |      |\n| haloCursor        | 边光晕鼠标移入样式，[配置项](#cursor)                | string                 | `default`                      |      |\n| haloDraggable     | 边光晕是否允许拖拽                                   | boolean                | true                           |      |\n| haloDroppable     | 边光晕是否允许接收被拖拽的元素                       | boolean                | true                           |      |\n| haloFillRule      | 边光晕填充规则                                       | `nonzero` \\| `evenodd` | -                              |      |\n| haloFilter        | 边光晕滤镜                                           | string                 | -                              |      |\n| haloLineWidth     | 边光晕描边宽度                                       | number                 | 3                              |      |\n| haloPointerEvents | 边光晕效果是否响应指针事件，[配置项](#pointerevents) | string                 | `none`                         |      |\n| haloStroke        | 边光晕描边色，**此属性用于设置边周围光晕的颜色**     | string                 | 与主图形的描边色 `stroke` 一致 |      |\n| haloStrokeOpacity | 边光晕描边色透明度                                   | number                 | 0.25                           |      |\n| haloVisibility    | 边光晕可见性                                         | `visible` \\| `hidden`  | `visible`                      |      |\n| haloZIndex        | 边光晕渲染层级                                       | number                 | -1                             |      |\n\n### 箭头样式\n\n边支持在起始端和结束端添加箭头，用于表示边的方向性。\n\n#### 基础箭头\n\n为边的结束端添加基本箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'vee', // 箭头类型\n      endArrowSize: 10, // 箭头大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 双向箭头\n\n为边的两端都添加箭头：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#52C41A',\n      lineWidth: 2,\n      startArrow: true, // 起始端箭头\n      startArrowType: 'circle',\n      startArrowSize: 8,\n      endArrow: true, // 结束端箭头\n      endArrowType: 'triangle',\n      endArrowSize: 10,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义箭头样式\n\n自定义箭头的颜色和类型：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 240,\n  height: 100,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 60, y: 50 } },\n      { id: 'node2', style: { x: 180, y: 50 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  edge: {\n    style: {\n      stroke: '#722ED1',\n      lineWidth: 3,\n      endArrow: true,\n      endArrowType: 'diamond', // 菱形箭头\n      endArrowSize: 12,\n      endArrowFill: '#FF4D4F', // 红色箭头填充\n      endArrowStroke: '#722ED1', // 箭头描边颜色\n      endArrowStrokeOpacity: 0.8,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 起始箭头样式配置\n\n| 属性                    | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| ----------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| startArrow              | 边起始箭头是否显示                        | boolean                                                                              | false              |      |\n| startArrowCursor        | 边起始箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| startArrowFill          | 边起始箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowFillOpacity   | 边起始箭头填充透明度                      | number                                                                               | 1                  |      |\n| startArrowOffset        | 边起始箭头的偏移量                        | number                                                                               | 0                  |      |\n| startArrowSize          | 边起始箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| startArrowStroke        | 边起始箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| startArrowStrokeOpacity | 边起始箭头描边透明度                      | number                                                                               | 1                  |      |\n| startArrowType          | 边起始箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n#### 结束箭头样式配置\n\n| 属性                  | 描述                                      | 类型                                                                                 | 默认值             | 必选 |\n| --------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | ------------------ | ---- |\n| endArrow              | 边结束箭头是否显示                        | boolean                                                                              | false              |      |\n| endArrowCursor        | 边结束箭头鼠标移入样式，[配置项](#cursor) | string                                                                               | `default`          |      |\n| endArrowFill          | 边结束箭头填充颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowFillOpacity   | 边结束箭头填充透明度                      | number                                                                               | 1                  |      |\n| endArrowOffset        | 边结束箭头的偏移量                        | number                                                                               | 0                  |      |\n| endArrowSize          | 边结束箭头大小                            | number \\| [number, number]                                                           | 10                 |      |\n| endArrowStroke        | 边结束箭头描边颜色                        | string                                                                               | 默认与边的颜色一致 |      |\n| endArrowStrokeOpacity | 边结束箭头描边透明度                      | number                                                                               | 1                  |      |\n| endArrowType          | 边结束箭头类型                            | `triangle` \\| `circle` \\| `diamond` \\| `vee` \\| `rect` \\| `triangleRect` \\| `simple` | `vee`              |      |\n\n### 自环边样式\n\n自环边是指起始节点和结束节点为同一个节点的特殊边。\n\n#### 基础自环边\n\n创建基本的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 50 } }],\n    edges: [{ source: 'node1', target: 'node1' }],\n  },\n  edge: {\n    style: {\n      stroke: '#1890FF',\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: 'top', // 自环位置\n      loopDist: 30, // 自环大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个自环边\n\n为同一节点创建多个不同位置的自环边：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  data: {\n    nodes: [{ id: 'node1', style: { x: 100, y: 60 } }],\n    edges: [\n      { id: 'edge1', source: 'node1', target: 'node1' },\n      { id: 'edge2', source: 'node1', target: 'node1' },\n      { id: 'edge3', source: 'node1', target: 'node1' },\n    ],\n  },\n  edge: {\n    style: {\n      lineWidth: 2,\n      endArrow: true,\n      loopPlacement: (datum) => {\n        const placements = ['top', 'right', 'bottom'];\n        return placements[parseInt(datum.id.slice(-1)) - 1];\n      },\n      loopDist: 25,\n      stroke: (datum) => {\n        const colors = ['#1890FF', '#52C41A', '#722ED1'];\n        return colors[parseInt(datum.id.slice(-1)) - 1];\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的自环边样式配置：\n\n| 属性          | 描述                                           | 类型                                                                                                                                                                   | 默认值                 | 必选 |\n| ------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| loop          | 是否启用自环边                                 | boolean                                                                                                                                                                | true                   |      |\n| loopClockwise | 指定是否顺时针绘制环                           | boolean                                                                                                                                                                | true                   |      |\n| loopDist      | 从节点边缘到自环顶部的距离，用于指定自环的曲率 | number                                                                                                                                                                 | 默认为节点尺寸的最大值 |      |\n| loopPlacement | 自环边的位置                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | `top`                  |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个边或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ebBlTpKu2WUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype EdgeState = {\n  [state: string]: EdgeStyle;\n};\n```\n\n例如，当边处于 `focus` 状态时，可以为其添加一个宽度为 6 且颜色为橙色的光晕。\n\n```js {4-9}\nconst graph = new Graph({\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n        haloStrokeOpacity: 0.6,\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 100,\n  data: {\n    nodes: [{ id: 'node1' }, { id: 'node2' }],\n    edges: [{ source: 'node1', target: 'node2', states: ['focus'] }],\n  },\n  edge: {\n    state: {\n      focus: {\n        halo: true,\n        haloLineWidth: 6,\n        haloStroke: 'orange',\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义边的动画效果，支持下列两种配置方式：\n\n1. 关闭边全部动画\n\n```json\n{\n  \"edge\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指边在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 边进入画布时的动画\n- `update`: 边更新时的动画\n- `exit`: 边离开画布时的动画\n- `show`: 边从隐藏状态显示时的动画\n- `hide`: 边隐藏时的动画\n- `collapse`: 边收起时的动画\n- `expand`: 边展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置边，如：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"stroke\"], // 更新时只对 stroke 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ]\n    }\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"path-in\", // 使用路径动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"edge\": {\n    \"animation\": {\n      \"enter\": false // 关闭边入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义边的色板，即预定义边颜色池，并根据规则进行分配，将颜色映射到 `stroke` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `direction` 字段分配边颜色，使得同类别的边颜色相同：\n\n```json\n{\n  \"edge\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"direction\",\n      \"color\": [\"#F08F56\", \"#00C9C9\", \"#D580FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: {\n      type: 'group',\n      field: 'direction',\n      color: ['#F08F56', '#00C9C9'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"edge\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: new Array(6).fill(0).map((_, i) => ({ id: `node-${i + 1}` })),\n    edges: [\n      { source: 'node-1', target: 'node-2', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-3', data: { direction: 'out' } },\n      { source: 'node-1', target: 'node-4', data: { direction: 'out' } },\n      { source: 'node-5', target: 'node-1', data: { direction: 'in' } },\n      { source: 'node-6', target: 'node-1', data: { direction: 'in' } },\n    ],\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 120,\n    linkDistance: 120,\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Cubic.en.md) -->\n---\ntitle: Cubic Bezier Curve Edge\norder: 2\n---\n\n## Overview\n\nA cubic Bezier curve is a versatile smooth curve with control points that can be freely distributed, suitable for connecting nodes in any direction.\n\nUse cases:\n\n- Suitable for graphs with any layout, such as network graphs and relationship graphs.\n\n- Use when smooth node connections are needed without specific directional requirements.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type                               | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [[Point](#point), [Point](#point)] | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number &#124; number[]             | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number &#124; number[]             | 20      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Cubic.zh.md) -->\n---\ntitle: 三次贝塞尔曲线边 Cubic\norder: 2\n---\n\n## 概述\n\n三次贝塞尔曲线是一种通用的平滑曲线，其控制点可以自由分布，适合连接任意方向的节点。\n\n使用场景：\n\n- 适用于任意布局的图，如网络图、关系图。\n\n- 当需要平滑连接节点且无特定方向要求时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型                               | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [[Point](#point), [Point](#point)] | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number &#124; number[]             | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number &#124; number[]             | 20     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'cubic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/CubicHorizontal.en.md) -->\n---\ntitle: CubicHorizontal Bezier Curve Edge\norder: 3\n---\n\n## Overview\n\nThe horizontal cubic Bezier curve is a smooth curve with control points primarily distributed along the horizontal direction, suitable for connecting nodes horizontally.\n\nUse cases:\n\n- Suitable for horizontally laid-out graphs, such as flowcharts and hierarchical diagrams.\n\n- Use when emphasizing horizontal connections is needed.\n\n> Note: When calculating control points, the distance on the x-axis is primarily considered, ignoring changes on the y-axis.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Horizontal Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/CubicHorizontal.zh.md) -->\n---\ntitle: 水平三次贝塞尔曲线边 CubicHorizontal\norder: 3\n---\n\n## 概述\n\n水平三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿水平方向分布，适合在水平方向上连接节点。\n\n使用场景：\n\n- 适用于水平布局的图，如流程图、层次结构图。\n\n- 当需要强调水平方向的连接关系时使用。\n\n> 特别注意，计算控制点时主要考虑 x 轴上的距离，忽略 y 轴的变化\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-horizontal.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置水平三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'right' }, { placement: 'left' }],\n    },\n  },\n  edge: {\n    type: 'cubic-horizontal',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'LR',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/CubicVertical.en.md) -->\n---\ntitle: CubicVertical Bezier Curve Edge\norder: 4\n---\n\n## Overview\n\nThe vertical cubic Bezier curve is a smooth curve with control points primarily distributed along the vertical direction, suitable for connecting nodes vertically.\n\nUse cases:\n\n- Suitable for vertically laid-out graphs, such as organizational charts and tree diagrams.\n\n- Use when emphasizing vertical connections is needed.\n\n**Note: When calculating control points, the distance on the y-axis is primarily considered, ignoring changes on the x-axis.**\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                          | Type                   | Default   | Required |\n| ------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------- | -------- |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                 | number &#124; number[] | [0.5,0.5] |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending. | number &#124; number[] | [0,0]     |          |\n\n## Example\n\n### Built-in Vertical Cubic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/CubicVertical.zh.md) -->\n---\ntitle: 垂直三次贝塞尔曲线边 CubicVertical\norder: 4\n---\n\n## 概述\n\n垂直三次贝塞尔曲线是一种平滑的曲线，其控制点主要沿垂直方向分布，适合在垂直方向上连接节点。\n\n使用场景：\n\n- 适用于垂直布局的图，如组织结构图、树状图。\n\n- 当需要强调垂直方向的连接关系时使用。\n\n**特别注意，计算控制点时主要考虑 y 轴上的距离，忽略 x 轴的变化**\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/cubic-vertical.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                 | 类型                   | 默认值    | 必选 |\n| ------------- | ---------------------------------------------------- | ---------------------- | --------- | ---- |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`          | number &#124; number[] | [0.5,0.5] |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度 | number &#124; number[] | [0,0]     |      |\n\n## 示例\n\n### 内置垂直三次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      port: true,\n      ports: [{ placement: 'top' }, { placement: 'bottom' }],\n    },\n  },\n  edge: {\n    type: 'cubic-vertical',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'antv-dagre',\n    begin: [50, 50],\n    rankdir: 'TB',\n    nodesep: 20,\n    ranksep: 120,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/custom-edge.en.md) -->\n---\ntitle: Custom Edge\norder: 7\n---\n\nG6 provides multiple [built-in edge](/en/manual/element/edge/base-edge) types, including [line](/en/manual/element/edge/line), [polyline](/en/manual/element/edge/polyline), [quadratic (quadratic Bézier curve edge)](/en/manual/element/edge/quadratic), [cubic (cubic Bézier curve edge)](/en/manual/element/edge/cubic), [cubic-horizontal](/en/manual/element/edge/cubic-horizontal), [cubic-vertical](/en/manual/element/edge/cubic-vertical), and more. These built-in edges can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter requirements that these basic edges cannot satisfy. In such cases, you need to create custom edges. Don't worry, it's simpler than you think!\n\n## Before Starting: Understanding the Basic Components of an Edge\n\nIn G6, a complete edge typically consists of the following parts:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the edge, representing the primary shape of the edge, such as straight lines, polylines, etc.\n- `label`: Text label, usually used to display the name or description of the edge\n- `arrow`: Arrow, used to indicate the direction of the edge\n- `halo`: Graphic displaying halo effects around the main graphic\n\n## Ways to Create Custom Edges <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are two main ways to create custom edges:\n\n### 1. Inherit from Existing Edge Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach. You can choose to inherit from one of the following types:\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - The most basic edge class, providing core edge functionality\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - Straight line edge\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - Polyline edge\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - Quadratic Bézier curve edge\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - Cubic Bézier curve edge\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - Vertical cubic Bézier curve edge\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - Horizontal cubic Bézier curve edge\n\n**Why choose this approach?**\n\n- 📌 **Less code**: Reuse existing edge properties and methods, only focus on new functionality\n- 📌 **Fast development**: Suitable for most project requirements, quickly achieve business goals\n- 📌 **Easy maintenance**: Clear code structure, clear inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing edge types (recommended), you can jump directly to [Create Your First Custom Edge in Three Steps](#create-your-first-custom-edge-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing edge types don't meet your requirements, you can create edges from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum freedom**: Complete control over every detail of the edge, achieving any complex effects\n- 📌 **Special requirements**: Highly customized scenarios that existing edge types cannot satisfy\n- 📌 **Performance optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom edges built from scratch need to handle all details by themselves, including graphic rendering, event response, state changes, etc., which is more challenging to develop. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) for implementation.\n:::\n\n## Create Your First Custom Edge in Three Steps\n\nLet's start with the most basic `BaseEdge` to implement a custom straight line edge:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Edge Class\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // Define edge style, can add or override default styles\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // Call parent class method to get basic style, then add custom styles\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // Implement abstract method: define edge path\n  // This is an abstract method of BaseEdge, all subclasses must implement it\n  protected getKeyPath(attributes) {\n    // Get source node and target node\n    const { sourceNode, targetNode } = this;\n\n    // Get node position coordinates\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // Return SVG path array, defining a straight line from start to end\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=Key Method Analysis}\n\n- `getKeyStyle`: Defines the basic style of the edge, such as line width, color, etc.\n- `getKeyPath`: An abstract method in `BaseEdge` that **must be implemented**, it defines the path shape of the edge\n  :::\n\n### Step 2: Register Custom Edge\n\nUse the `register` method to register the edge type so that G6 can recognize your custom edge:\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.EDGE` indicates this is an edge type\n- Type name: `my-line-edge` is the name we give to this custom edge, which will be used in configuration later\n- Class definition: `MyLineEdge` is the edge class we just created\n\n### Step 3: Apply Custom Edge\n\nIn the graph configuration, use our custom edge by setting `edge.type`:\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom edge.\n\n## Going Further: Understanding the Principles of Edge Rendering\n\n### Atomic Graphics\n\nG6 nodes are drawn using atomic graphic units provided by the [G graphics system](https://g.antv.antgroup.com/). Here are common graphic elements and their uses:\n\n| Graphic Element | Type       | Description                                                                                                                                                                                                                                                                 |\n| --------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Circle          | `circle`   | Suitable for representing states, avatars, circular buttons, etc. Refer to SVG's [\\<circle\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/circle) element                                                                                            |\n| Ellipse         | `ellipse`  | Similar to circle, but supports scenarios with different horizontal and vertical axes. Refer to SVG's [\\<ellipse\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/ellipse) element                                                                     |\n| Image           | `image`    | Used to display icons, user avatars, LOGOs, etc. Refer to SVG's [\\<image\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image) element                                                                                                                         |\n| Line            | `line`     | Used for decoration, auxiliary connections, etc. Refer to SVG's [\\<line\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) element                                                                                                                           |\n| Path            | `path`     | Supports complex graphics such as arrows, arcs, curves, Bézier paths, etc. The path contains a set of commands and parameters with different semantics, [specific usage](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths)                                   |\n| Polygon         | `polygon`  | Supports custom graphics such as pentagrams, arrows. Refer to SVG's [\\<polygon\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon) element                                                                                                                 |\n| Polyline        | `polyline` | Multi-point polyline, suitable for complex connection structures. Refer to SVG's [\\<polyline\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline) element                                                                                                  |\n| Rectangle       | `rect`     | Most commonly used graphic, suitable as containers, cards, buttons, and other basic structures. Refer to SVG's [\\<rect\\>](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect) element                                                                            |\n| Text            | `text`     | Displays names, descriptions, labels, and other content. Provides simple single-line/multi-line text layout capabilities, single-line supports horizontal alignment, character spacing; multi-line supports explicit line breaks and automatic wrapping, vertical alignment |\n\n> For more atomic graphics and detailed properties, please refer to [Element - Shape (Optional)](/en/manual/element/shape/overview)\n\nAll these graphics can be dynamically created or updated through `upsert()`, automatically managing graphic state and lifecycle.\n\n### Element Base Class\n\nBefore starting to customize elements, you need to understand some important properties and methods in G6 element base classes:\n\n#### Properties\n\n| Property   | Type                          | Description                                           |\n| ---------- | ----------------------------- | ----------------------------------------------------- |\n| shapeMap   | Record<string, DisplayObject> | Mapping table of all graphics under current element   |\n| animateMap | Record<string, IAnimation>    | Mapping table of all animations under current element |\n\n#### Methods\n\n#### `upsert(name, Ctor, style, container, hooks)`: Graphic Creation/Update\n\nWhen creating custom elements, you will frequently use the `upsert` method. It's short for \"update or insert\", responsible for adding or updating graphics in elements:\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| Parameter | Type                                    | Description                                                                                                                                                                                                                                                                                                                       |\n| --------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | The key of the graphic, i.e., the corresponding key in `shapeMap`. Built-in keys include `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> The key should not use special symbols, it will be converted to camelCase to call `getXxxStyle` and `drawXxxShape` methods (see [Element Conventions](#element-conventions)) |\n| Ctor      | { new (...args: any[]): DisplayObject } | Graphic class                                                                                                                                                                                                                                                                                                                     |\n| style     | Record<string, any>                     | Graphic style                                                                                                                                                                                                                                                                                                                     |\n| container | DisplayObject                           | Container to mount the graphic                                                                                                                                                                                                                                                                                                    |\n\nFor example, inserting a purple circle at a fixed position:\n\n```js\nthis.upsert(\n  'element-key', // Unique identifier of the element\n  'circle', // Graphic type, such as 'rect', 'circle', etc.\n  { x: 100, y: 100, fill: '#a975f3' }, // Style configuration object\n  container, // Parent container\n);\n```\n\nWhy use `upsert` instead of directly creating graphics through `container.appendChild()`? Because:\n\n1. **Better performance**: When state changes or data updates, it intelligently reuses existing graphics instead of deleting and rebuilding, greatly improving rendering performance\n2. **Simpler code**: No need to manually check if elements exist\n3. **Easy management**: All graphics created through `upsert` are recorded in the node's `shapeMap`, you can easily get them through `this.getShape(key)`\n\n#### `render(attributes, container)`: Main Entry Point for Rendering Edges\n\nEvery custom edge class must implement the `render(attributes, container)` method, which defines how the edge is \"drawn\". You can use various atomic graphics here to compose the structure you want.\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| Parameter | Type                | Description   |\n| --------- | ------------------- | ------------- |\n| style     | Record<string, any> | Element style |\n| container | Group               | Container     |\n\n#### `getShape(name)`: Get Created Graphics\n\nSometimes, you need to modify the properties of a sub-graphic after creation, or make sub-graphics interact with each other. In this case, the `getShape` method can help you get any graphic previously created through `upsert`:\n\n**⚠️ Note**: The order of graphics is important. If graphic B depends on the position of graphic A, you must ensure A is created first\n\n### Element Conventions\n\n- **Use Conventional Properties**\n\nCurrently conventional element properties include:\n\n- Get element size through `this.getSize()`\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` (simple mode - doesn't consider node shape, directly returns node center or nearest port center position)\n- Get edge start and end points through `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` (optimized mode - default is true, considers node shape, returns connection points on node boundary)\n\n- **Use Paired `getXxxStyle` and `drawXxxShape` Methods for Graphic Drawing**\n\n`getXxxStyle` is used to get graphic styles, `drawXxxShape` is used to draw graphics. Graphics created this way support automatic animation execution.\n\n> Where `Xxx` is the camelCase form of the key passed when calling the [upsert](#methods) method.\n\n- **Access Graph Context through `this.context`**\n\n### Lifecycle Hooks\n\nThe following lifecycle hook functions are provided, which you can override in custom edges to execute specific logic at key moments:\n\n| Hook Function | Trigger Time                                            | Typical Usage                                                                    |\n| ------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------- |\n| `onCreate`    | When edge creation is completed with entrance animation | Bind interaction events, initialize edge state, add external listeners           |\n| `onUpdate`    | When edge update is completed with update animation     | Update dependent data, adjust related elements, trigger linkage effects          |\n| `onDestroy`   | When edge completes exit animation and is destroyed     | Clean up resources, remove external listeners, execute destruction notifications |\n\n### State Response\n\nOne of the most powerful aspects of G6 element design is the ability to separate **\"state response\"** from **\"rendering logic\"**.\n\nYou can define styles for each state in edge configuration:\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\nMethod to switch states:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\nThis state will be passed to the `render()` method's `attributes`, and the merged result by the internal system will be automatically applied to the graphics.\n\nYou can also customize rendering logic based on state:\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // Adjust style based on state\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## From Simple to Complex\n\n### Custom Path Polyline Edge\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### Additional Labels\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/custom-edge.zh.md) -->\n---\ntitle: 自定义边\norder: 7\n---\n\nG6 提供了多种[内置边](/manual/element/edge/base-edge)类型，包含 [line（直线边）](/manual/element/edge/line)、[polyline（折线边）](/manual/element/edge/polyline)、[quadratic（二次贝塞尔曲线边）](/manual/element/edge/quadratic)、[cubic（三次贝塞尔曲线边）](/manual/element/edge/cubic)、[cubic-horizontal（水平三次贝塞尔曲线边）](/manual/element/edge/cubic-horizontal)、[cubic-vertical（垂直三次贝塞尔曲线边）](/manual/element/edge/cubic-vertical) 等。这些内置边能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础边无法满足的需求。这时，你需要创建自定义边。别担心，这比你想象的要简单！\n\n## 开始之前：了解边的基本构成\n\n在 G6 中，一条完整的边通常由以下几个部分组成：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：边的主图形，表示边的主要形状，例如直线、折线等；\n- `label` ：文本标签，通常用于展示边的名称或描述；\n- `arrow` ：箭头，用于表示边的方向；\n- `halo` ：主图形周围展示的光晕效果的图形。\n\n## 自定义边的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义边的方式主要有两种途径：\n\n### 1. 继承现有边类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseEdge`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) - 最基础的边类，提供边的核心功能\n- [`Line`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/line.ts) - 直线边\n- [`Polyline`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/polyline.ts) - 折线边\n- [`Quadratic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/quadratic.ts) - 二次贝塞尔曲线边\n- [`Cubic`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic.ts) - 三次贝塞尔曲线边\n- [`CubicVertical`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-vertical.ts) - 垂直三次贝塞尔曲线边\n- [`CubicHorizontal`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/cubic-horizontal.ts) - 水平三次贝塞尔曲线边\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有边的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有边类型（推荐），可以直接跳到 [三步创建你的第一个自定义边](#三步创建你的第一个自定义边) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有边类型都不满足需求，你可以基于 G 的底层图形系统从零创建边。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制边的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有边类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义边需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/edges/base-edge.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义边\n\n让我们从最基础的 `BaseEdge` 开始，实现一个自定义直线边：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  getKeyStyle(attributes) {\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  getKeyPath(attributes) {\n    const { sourceNode, targetNode } = this;\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 50 } },\n      { id: 'node2', style: { x: 300, y: 120 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义边类\n\n```typescript\nimport { BaseEdge } from '@antv/g6';\nimport type { BaseEdgeStyleProps } from '@antv/g6';\n\nclass MyLineEdge extends BaseEdge {\n  // 定义边的样式，可以添加或覆盖默认样式\n  protected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n    // 调用父类方法获取基础样式，然后添加自定义样式\n    return { ...super.getKeyStyle(attributes), lineWidth: 2, stroke: '#A4D3EE' };\n  }\n\n  // 实现抽象方法：定义边的路径\n  // 这是 BaseEdge 的抽象方法，所有子类必须实现\n  protected getKeyPath(attributes) {\n    // 获取源节点和目标节点\n    const { sourceNode, targetNode } = this;\n\n    // 获取节点的位置坐标\n    const [x1, y1] = sourceNode.getPosition();\n    const [x2, y2] = targetNode.getPosition();\n\n    // 返回SVG路径数组，定义从起点到终点的直线\n    return [\n      ['M', x1, y1],\n      ['L', x2, y2],\n    ];\n  }\n}\n```\n\n:::success{title=关键方法解析}\n\n- `getKeyStyle`: 定义边的基本样式，如线宽、颜色等\n- `getKeyPath`: 是 `BaseEdge` 中的抽象方法，**必须实现**，它定义了边的路径形状\n  :::\n\n### 第二步：注册自定义边\n\n使用 `register` 方法注册边类型，这样 G6 才能识别你的自定义边：\n\n```js\nimport { ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.EDGE` 表示这是一个边类型\n- 类型名称：`my-line-edge` 是我们给这个自定义边起的名字，后续会在配置中使用\n- 类定义：`MyLineEdge` 是我们刚刚创建的边类\n\n### 第三步：应用自定义边\n\n在图的配置中，通过设置 `edge.type` 来使用我们的自定义边：\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 300, y: 150 } },\n    ],\n    edges: [{ source: 'node1', target: 'node2' }],\n  },\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n  edge: {\n    type: 'my-line-edge',\n    style: {\n      zIndex: 3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义边。\n\n## 更进一步：理解边绘制的原理\n\n### 原子图形\n\nG6 的节点是由 [G 图形系统](https://g.antv.antgroup.com/) 提供的图形原子单元绘制而成。以下是常见图形元素及其用途：\n\n| 图形元素 | 类型       | 描述                                                                                                                                                                        |\n| -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 圆形     | `circle`   | 适合表示状态、头像、圆形按钮等。可以参考 SVG 的 [\\<circle\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/circle) 元素                                |\n| 椭圆     | `ellipse`  | 与 circle 类似，但支持横纵轴不同的场景。可以参考 SVG 的 [\\<ellipse\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Reference/Element/ellipse) 元素                      |\n| 图片     | `image`    | 用于展示图标、用户头像、LOGO 等。可以参考 SVG 的 [\\<image\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/image) 元素                                           |\n| 直线     | `line`     | 用于装饰、辅助连接等。可以参考 SVG 的 [\\<line\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/line) 元素                                                        |\n| 路径     | `path`     | 支持复杂图形，如箭头、圆弧、曲线、贝塞尔路径等。路径中包含一组命令与参数，这些命令有不同的语义，[具体用法](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths) |\n| 多边形   | `polygon`  | 支持自定义图形，如五角星、箭头。可以参考 SVG 的 [\\<polygon\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polygon) 元素                                        |\n| 折线     | `polyline` | 多点折线，适合复杂的连线结构。可以参考 SVG 的 [\\<polyline\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/polyline) 元素                                        |\n| 矩形     | `rect`     | 最常用图形，适合作为容器、卡片、按钮等基础结构。可以参考 SVG 的 [\\<rect\\>](https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/rect) 元素                              |\n| 文本     | `text`     | 显示名称、描述、标签等内容。提供简单的单行/多行文本排版能力，单行支持水平对齐、字符间距；多行支持显式换行符以及自动换行，垂直对齐                                           |\n\n> 更多原子图形和详细的属性请参考 [元素 - 图形（可选）](/manual/element/shape/overview)\n\n所有这些图形都可通过 `upsert()` 动态创建或更新，并自动管理图形状态和生命周期。\n\n### 元素基类\n\n开始自定义元素之前，你需要了解 G6 元素基类中的一些重要属性和方法：\n\n#### 属性\n\n| 属性       | 类型                          | 描述                       |\n| ---------- | ----------------------------- | -------------------------- |\n| shapeMap   | Record<string, DisplayObject> | 当前元素下所有图形的映射表 |\n| animateMap | Record<string, IAnimation>    | 当前元素下所有动画的映射表 |\n\n#### 方法\n\n#### `upsert(name, Ctor, style, container, hooks)`: 图形创建/更新\n\n在创建自定义元素时，你会频繁用到 `upsert` 方法。它是 \"update or insert\" 的缩写，负责添加或更新元素中的图形：\n\n```typescript\nupsert(key: string, Ctor: { new (...args: any[]): DisplayObject }, style: Record<string, any>, container: DisplayObject);\n```\n\n| 参数      | 类型                                    | 描述                                                                                                                                                                                                                                   |\n| --------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| key       | string                                  | 图形的 key，即 `shapeMap` 中对应的 key。内置的 key 包括 `'key'` `'label'` `'halo'` `'icon'` `'port'` `'badge'`<br/> key 不应使用特殊符号，会基于该值转化为驼峰形式调用 `getXxxStyle` 和 `drawXxxShape` 方法（见[元素约定](#元素约定)） |\n| Ctor      | { new (...args: any[]): DisplayObject } | 图形类                                                                                                                                                                                                                                 |\n| style     | Record<string, any>                     | 图形样式                                                                                                                                                                                                                               |\n| container | DisplayObject                           | 挂载图形的容器                                                                                                                                                                                                                         |\n\n例如，插入一个固定位置的紫色圆形：\n\n```js\nthis.upsert(\n  'element-key', // 元素的唯一标识\n  'circle', // 图形类型，如 'rect', 'circle' 等\n  { x: 100, y: 100, fill: '#a975f3' }, // 样式配置对象\n  container, // 父容器\n);\n```\n\n为什么要使用 `upsert` 而不直接通过 `container.appendChild()` 创建图形？因为：\n\n1. **性能更好**：当状态变化或数据更新时，会智能地复用已有图形，而不是删除再重建，大大提高了渲染性能\n2. **代码更简洁**：不需要手动判断元素是否存在\n3. **便于管理**：所有通过 `upsert` 创建的图形都会被记录在节点的 `shapeMap` 中，你可以通过 `this.getShape(key)` 轻松获取\n\n#### `render(attributes, container)`: 渲染边的主入口\n\n每个自定义边类都必须实现 `render(attributes, container)` 方法，它定义了该边如何被“绘制”出来。你可以在这里使用各种原子图形，组合出你想要的结构。\n\n```typescript\nrender(style: Record<string, any>, container: Group): void;\n```\n\n| 参数      | 类型                | 描述     |\n| --------- | ------------------- | -------- |\n| style     | Record<string, any> | 元素样式 |\n| container | Group               | 容器     |\n\n#### `getShape(name)`: 获取已创建的图形\n\n有时，你需要在创建后修改某个子图形的属性，或者让子图形之间有交互关联。这时，`getShape` 方法可以帮你获取之前通过 `upsert` 创建的任何图形：\n\n**⚠️ 注意**：图形的顺序很重要，如果图形 B 依赖图形 A 的位置，必须确保 A 先创建\n\n### 元素约定\n\n- **使用约定属性**\n\n目前约定的元素属性包括：\n\n- 通过 `this.getSize()` 获取元素的尺寸\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false)` 获取边的起点和终点（简单模式 - 不考虑节点形状，直接返回节点中心点或最近连接桩中心˝位置）\n- 通过 `const [sourcePoint, targetPoint] = this.getEndpoints(attributes)` 获取边的起点和终点（优化模式 - 默认为 true，考虑节点形状，返回节点边界上的连接点）\n\n- **采用 `getXxxStyle` 和 `drawXxxShape` 配对的方式进行图形绘制**\n\n`getXxxStyle` 用于获取图形样式，`drawXxxShape` 用于绘制图形。通过该方式创建的图形支持自动执行动画。\n\n> 其中 `Xxx` 是调用 [upsert](#方法) 方法时传入的 key 的驼峰形式。\n\n- **可通过 `this.context` 访问 Graph 上下文**\n\n### 生命周期钩子\n\n提供了以下生命周期钩子函数，你可以在自定义边中重写这些方法，在关键时刻执行特定逻辑：\n\n| 钩子函数    | 触发时机                 | 典型用途                                   |\n| ----------- | ------------------------ | ------------------------------------------ |\n| `onCreate`  | 当边创建后完成入场动画时 | 绑定交互事件、初始化边状态、添加外部监听器 |\n| `onUpdate`  | 当边更新后完成更新动画时 | 更新依赖数据、调整相关元素、触发联动效果   |\n| `onDestroy` | 当边完成退场动画并销毁后 | 清理资源、移除外部监听器、执行销毁通知     |\n\n### 状态响应\n\nG6 元素设计中最强大的一点，是可以将 **“状态响应”** 与 **“绘制逻辑”** 分离。\n\n你可以在边配置中定义每种状态下的样式：\n\n```js\nedge: {\n  type: 'custom-edge',\n  style: { stroke: '#eee' },\n  state: {\n    selected: {\n      stroke: '#f00',\n    },\n    hover: {\n      lineWidth: 3,\n      stroke: '#1890ff',\n    },\n  },\n}\n```\n\n切换状态的方法:\n\n```js\ngraph.setElementState(edgeId, ['selected']);\n```\n\n这个状态会传入到 `render()` 方法的 `attributes` 中，由内部系统合并后的结果自动应用在图形上。\n\n也可以根据状态自定义渲染逻辑：\n\n```typescript\nprotected getKeyStyle(attributes: Required<BaseEdgeStyleProps>) {\n  const style = super.getKeyStyle(attributes);\n\n  // 根据状态调整样式\n  if (attributes.states?.includes('selected')) {\n    return {\n      ...style,\n      stroke: '#1890ff',\n      lineWidth: 2,\n      shadowColor: 'rgba(24,144,255,0.2)',\n      shadowBlur: 15,\n    };\n  }\n\n  return style;\n}\n```\n\n## 从简单到复杂\n\n### 自定义路径的折线边\n\n```js | ob { inject: true }\nimport { Graph, register, BaseEdge, ExtensionCategory } from '@antv/g6';\n\nclass MyPolylineEdge extends BaseEdge {\n  getKeyPath(attributes) {\n    const [sourcePoint, targetPoint] = this.getEndpoints(attributes);\n\n    return [\n      ['M', sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], sourcePoint[1]],\n      ['L', targetPoint[0] / 2 + (1 / 2) * sourcePoint[0], targetPoint[1]],\n      ['L', targetPoint[0], targetPoint[1]],\n    ];\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'my-polyline-edge', MyPolylineEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 50, ports: [{ key: 'right', placement: [1, 0.5] }] } },\n      { id: 'node-1', style: { x: 250, y: 150, ports: [{ key: 'left', placement: [0, 0.5] }] } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'my-polyline-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n### 额外标签\n\n```js | ob { inject: true }\nimport { Graph, Line, register, BaseEdge, ExtensionCategory, subStyleProps } from '@antv/g6';\n\nclass LabelEdge extends Line {\n  render(attributes, container) {\n    super.render(attributes);\n    this.drawEndLabel(attributes, container, 'start');\n    this.drawEndLabel(attributes, container, 'end');\n  }\n\n  drawEndLabel(attributes, container, type) {\n    const key = type === 'start' ? 'startLabel' : 'endLabel';\n    const [x, y] = this.getEndpoints(attributes)[type === 'start' ? 0 : 1];\n\n    const fontStyle = {\n      x,\n      y,\n      dx: type === 'start' ? 15 : -15,\n      fontSize: 16,\n      fill: 'gray',\n      textBaseline: 'middle',\n      textAlign: type,\n    };\n    const style = subStyleProps(attributes, key);\n    const text = style.text;\n    this.upsert(`label-${type}`, 'text', text ? { ...fontStyle, ...style } : false, container);\n  }\n}\n\nregister(ExtensionCategory.EDGE, 'extra-label-edge', LabelEdge);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      { id: 'node-0', style: { x: 100, y: 100 } },\n      { id: 'node-1', style: { x: 300, y: 100 } },\n    ],\n    edges: [{ source: 'node-0', target: 'node-1' }],\n  },\n  edge: {\n    type: 'extra-label-edge',\n    style: {\n      startArrow: true,\n      endArrow: true,\n      stroke: '#F6BD16',\n      startLabelText: 'start',\n      endLabelText: 'end',\n    },\n  },\n  behaviors: ['drag-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Line.en.md) -->\n---\ntitle: Line Edge\norder: 5\n---\n\n## Overview\n\nA line is the simplest type of edge, directly connecting two nodes without any curvature.\n\nUse cases:\n\n- Suitable for simple graphs, such as topology diagrams and flowcharts.\n\n- Use when quick drawing is needed without complex visual effects.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n## Example\n\n### Built-in Line Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Line.zh.md) -->\n---\ntitle: 直线边 Line\norder: 5\n---\n\n## 概述\n\n直线是最简单的边类型，直接连接两个节点，没有任何弯曲。\n\n使用场景：\n\n- 适用于简单的图，如拓扑图、流程图。\n\n- 当需要快速绘制且无需复杂视觉效果时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/line.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n## 示例\n\n### 内置直线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'line',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/overview.en.md) -->\n---\ntitle: Edge Overview\norder: 0\n---\n\n## What is an Edge\n\nAn edge is one of the basic elements in a graph, used to connect two nodes or combos, representing the relationship between them. In G6, edges are directional, pointing from `source` to `target`, but you can configure them to hide the arrow to represent undirected connections.\n\nYou can create edges between any two nodes, combos, or between a node and a combo, and you can express different types of relationships by creating multiple edges.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 provides the following built-in edges:\n\n- `line` Straight line edge\n- `polyline` Polyline edge\n- `quadratic` Quadratic Bezier curve edge\n- `cubic` Cubic Bezier curve edge\n- `cubicVertical` Vertical cubic Bezier curve edge\n- `cubicHorizontal` Horizontal cubic Bezier curve edge\n\n### Data Structure\n\nWhen defining an edge, you need to add an `edges` field to the graph's data object. Each edge is an object with the following structure:\n\n| Attribute | Description                                                                                                   | Type     | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source    | ID of the starting node of the edge                                                                           | string   | -       | ✓        |\n| target    | ID of the target node of the edge                                                                             | string   | -       | ✓        |\n| id        | Unique identifier of the edge                                                                                 | string   | -       |          |\n| type      | Type of edge, name of built-in edge type or custom edge, such as `line` or `polyline`                         | string   | -       |          |\n| data      | Edge data, used to store custom data of the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style     | Edge style, including visual attributes like line color, width, arrow, etc.                                   | object   | -       |          |\n| states    | Initial states of the edge                                                                                    | string[] | -       |          |\n\nAn example of a data item in the `edges` array:\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### Configuration Methods\n\nThere are three ways to configure edges, listed in order of priority from high to low:\n\n- Use `graph.setEdge()` for dynamic configuration\n- Global configuration when instantiating the graph\n- Dynamic attributes in data\n\nThese configuration methods can be used simultaneously. When there are the same configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setEdge()`\n\nYou can dynamically set the style mapping logic of edges using `graph.setEdge()` after the graph instance is created.\n\nThis method needs to be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration When Instantiating the Graph\n\nYou can configure edge style mapping globally when instantiating the graph, and this configuration will take effect on all edges.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different edges, you can write the configuration into the edge data. This configuration method can be directly written into the data in the form of the following code:\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can take the following approach:\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## Custom Edges\n\nWhen built-in edges cannot meet the requirements, G6 provides powerful customization capabilities:\n\n- Extend built-in edges\n- Create entirely new edge types\n\nUnlike combos, custom edges need to be registered before use. For detailed tutorials, please refer to the [Custom Edge](/manual/element/edge/custom-edge) documentation.\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/overview.zh.md) -->\n---\ntitle: 边总览\norder: 0\n---\n\n## 什么是边\n\n边（Edge）是图中的基本元素之一，用于连接两个节点或组合，表示它们之间的关系。在 G6 中，边具有方向性，从 `source` 指向 `target`，也可以通过配置隐藏箭头以表示无方向连接。\n\n你可以在任意两个节点、组合，或节点与组合之间创建边，还可以通过创建多条边来表达不同的关系类型。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 提供了以下内置边：\n\n- `line` 直线边\n- `polyline` 折线边\n- `quadratic` 二次贝塞尔曲线边\n- `cubic` 三次贝塞尔曲线边\n- `cubicVertical` 垂直三次贝塞尔曲线边\n- `cubicHorizontal` 水平三次贝塞尔曲线边\n\n### 数据结构\n\n定义边时，需要在图的数据对象中添加 `edges` 字段。每条边是一个对象，结构如下：\n\n| 属性   | 描述                                                                  | 类型     | 默认值 | 必选 |\n| ------ | --------------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                         | string   | -      | ✓    |\n| target | 边目标节点 ID                                                         | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                        | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称，比如 `line` 或者 `polyline` | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取      | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                            | object   | -      |      |\n| states | 边初始状态                                                            | string[] | -      |      |\n\n`edges` 数组中一个数据项的示例：\n\n```json\n{\n  \"source\": \"alice\",\n  \"target\": \"bob\",\n  \"type\": \"line\",\n  \"data\": { \"relationship\": \"friend\", \"strength\": 5 },\n  \"style\": { \"stroke\": \"green\", \"lineWidth\": 2 },\n  \"states\": [\"hover\"]\n}\n```\n\n### 配置方法\n\n配置边的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setEdge()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setEdge()`\n\n可在图实例创建后，使用 `graph.setEdge()` 动态设置边的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setEdge({\n  style: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `edge` 配置边样式映射，这里的配置是全局的配置，将会在所有边上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: { stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同边进行不同的配置，可以将配置写入到边数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  edges: [\n    {\n      source: 'node-1',\n      target: 'node-2',\n      type: 'line',\n      style: { stroke: 'orange' },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  edge: {\n    type: 'line',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n## 自定义边\n\n当内置边无法满足需求时，G6 提供了强大的自定义能力：\n\n- 继承内置边进行扩展\n- 创建全新的边类型\n\n与组合不同，自定义边需要先注册后使用。详细教程请参考 [自定义边](/manual/element/edge/custom-edge) 文档。\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Polyline.en.md) -->\n---\ntitle: Polyline Edge\norder: 6\n---\n\n## Overview\n\nA polyline is an edge composed of multiple straight line segments, suitable for connecting nodes by bypassing obstacles in complex layouts.\n\nUse cases:\n\n- Suitable for graphs with complex layouts, such as circuit diagrams and pipeline diagrams.\n\n- Use when you need to bypass other nodes or obstacles.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                | Type                                                                                    | Default | Required |\n| ------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the turning points of the polyline. | [Point](#point)[]                                                                       | []      |          |\n| radius        | Corner radius of the turning points.                                       | number                                                                                  | 0       |          |\n| router        | Whether to enable routing.                                                 | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false   |          |\n\n### OrthRouter\n\n| Attribute | Description                                                                                              | Type                | Default |\n| --------- | -------------------------------------------------------------------------------------------------------- | ------------------- | ------- |\n| type      | Orthogonal routing, adding extra control points on the path to keep each segment horizontal or vertical. | `'orth'`            | -       |\n| padding   | Minimum distance between the node connection point and the corner.                                       | [Padding](#padding) | `0`     |\n\n### ShortestPathRouter\n\n| Attribute                 | Description                                                                                                                                                                                                                                                                          | Type                                                                   | Default |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------- |\n| type                      | Shortest path routing, an intelligent version of orthogonal routing `'orth'`. This routing consists of horizontal or vertical orthogonal segments. It uses the A\\* algorithm to calculate the shortest path and supports automatic avoidance of other nodes (obstacles) on the path. | `'shortest-path'`                                                      | -       |\n| offset                    | Minimum distance between the node anchor point and the corner.                                                                                                                                                                                                                       | [Padding](#padding)                                                    | 0       |\n| gridSize                  | Grid cell size.                                                                                                                                                                                                                                                                      | number                                                                 | 0       |\n| maxAllowedDirectionChange | Maximum allowed rotation angle (radians).                                                                                                                                                                                                                                            | number                                                                 | 0       |\n| startDirections           | Possible starting directions of the node.                                                                                                                                                                                                                                            | [Direction](#direction)[]                                              | 0       |\n| endDirections             | Possible ending directions of the node.                                                                                                                                                                                                                                              | [Direction](#direction)[]                                              | 0       |\n| directionMap              | Specifies the movable directions.                                                                                                                                                                                                                                                    | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0       |\n| penalties                 | Represents additional costs for certain paths during path searching. The key is the radian value, and the value is the cost.                                                                                                                                                         | { [key: string]: number }                                              | 0       |\n| distFunc                  | Specifies the function to calculate the distance between two points.                                                                                                                                                                                                                 | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0       |\n| maximumLoops              | Maximum number of iterations.                                                                                                                                                                                                                                                        | number                                                                 | 0       |\n| enableObstacleAvoidance   | Whether to enable obstacle avoidance.                                                                                                                                                                                                                                                | boolean                                                                | false   |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## Example\n\n### Built-in Polyline Edge Effect\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Polyline.zh.md) -->\n---\ntitle: 折线边 Polyline\norder: 6\n---\n\n## 概述\n\n折线是由多条直线段组成的边，适合在复杂布局中绕过障碍物连接节点。\n\n使用场景：\n\n- 适用于复杂布局的图，如电路图、管道图。\n\n- 当需要绕过其他节点或障碍物时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/polyline.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                             | 类型                                                                                    | 默认值 | 必选 |\n| ------------- | -------------------------------- | --------------------------------------------------------------------------------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义折线的转折点 | [Point](#point)[]                                                                       | []     |      |\n| radius        | 转折点圆角半径                   | number                                                                                  | 0      |      |\n| router        | 是否启用路由                     | false &#124; [OrthRouter](#orthrouter) &#124; [ShortestPathRouter](#shortestpathrouter) | false  |      |\n\n### OrthRouter\n\n| 属性    | 描述                                                                   | 类型                | 默认值 |\n| ------- | ---------------------------------------------------------------------- | ------------------- | ------ |\n| type    | 正交路由，通过在路径上添加额外的控制点，使得边的每一段都保持水平或垂直 | `'orth'`            | -      |\n| padding | 节点连接点与转角的最小距离                                             | [Padding](#padding) | `0`    |\n\n### ShortestPathRouter\n\n| 属性                      | 描述                                                                                                                                              | 类型                                                                   | 默认值 |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------ |\n| type                      | 最短路径路由，是正交路由 `'orth'` 的智能版本。该路由由水平或垂直的正交线段组成。采用 A\\* 算法计算最短路径，并支持自动避开路径上的其他节点（障碍） | `'shortest-path'`                                                      | -      |\n| offset                    | 节点锚点与转角的最小距离                                                                                                                          | [Padding](#padding)                                                    | 0      |\n| gridSize                  | grid 格子大小                                                                                                                                     | number                                                                 | 0      |\n| maxAllowedDirectionChange | 支持的最大旋转角度（弧度）                                                                                                                        | number                                                                 | 0      |\n| startDirections           | 节点的可能起始方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| endDirections             | 节点的可能结束方向                                                                                                                                | [Direction](#direction)[]                                              | 0      |\n| directionMap              | 指定可移动的方向                                                                                                                                  | { [key in [Direction](#direction)]: { stepX: number; stepY: number } } | 0      |\n| penalties                 | 表示在路径搜索过程中某些路径的额外代价。key 为弧度值，value 为代价                                                                                | { [key: string]: number }                                              | 0      |\n| distFunc                  | 指定计算两点之间距离的函数                                                                                                                        | (p1: [Point](#point), p2: [Point](#point)) => number                   | 0      |\n| maximumLoops              | 最大迭代次数                                                                                                                                      | number                                                                 | 0      |\n| enableObstacleAvoidance   | 是否开启避障                                                                                                                                      | boolean                                                                | false  |\n\n#### Direction\n\n```typescript\ntype Direction = 'left' | 'right' | 'top' | 'bottom';\n```\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n#### Padding\n\n```typescript\ntype Padding = number | [number, number] | [number, number, number, number];\n```\n\n## 示例\n\n### 内置折线边效果\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 200, y: 200 } },\n    { id: 'node-2', style: { x: 350, y: 120 } },\n  ],\n  edges: [\n    {\n      id: 'edge-1',\n      source: 'node-1',\n      target: 'node-2',\n      controlPoints: [[300, 190]],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'polyline',\n    style: {\n      controlPoints: (d) => d.controlPoints,\n    },\n  },\n  behaviors: [{ type: 'drag-element' }],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Quadratic.en.md) -->\n---\ntitle: Quadratic Bezier Curve Edge\norder: 6\n---\n\n## Overview\n\nA quadratic Bezier curve is a smooth curve whose shape is determined by a start point, an end point, and a control point.\n\nUse cases:\n\n- Suitable for moderately complex graphs, such as relationship graphs and network graphs.\n\n- Use when smooth node connections are needed with limited computational resources.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseEdge](/en/manual/element/edge/base-edge)\n\n| Attribute     | Description                                                                                                                                                 | Type            | Default | Required |\n| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | -------- |\n| controlPoints | Array of control points used to define the shape of the curve. If not specified, control points will be calculated using `curveOffset` and `curvePosition`. | [Point](#point) | -       |          |\n| curvePosition | Relative position of the control point on the line connecting the two endpoints, ranging from `0-1`.                                                        | number          | 0.5     |          |\n| curveOffset   | Distance of the control point from the line connecting the two endpoints, understood as the degree of curve bending.                                        | number          | 30      |          |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## Example\n\n### Built-in Quadratic Bezier Curve Edge Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Edge Skill (packages/site/docs/manual/element/edge/Quadratic.zh.md) -->\n---\ntitle: 二次贝塞尔曲线边 Quadratic\norder: 6\n---\n\n## 概述\n\n二次贝塞尔曲线是一种平滑的曲线，其形状由起点、终点和一个控制点决定。\n\n使用场景：\n\n- 适用于中等复杂度的图，如关系图、网络图。\n\n- 当需要平滑连接节点且计算资源有限时使用。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/edges/quadratic.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseEdge](/manual/element/edge/base-edge)\n\n| 属性          | 描述                                                                                               | 类型            | 默认值 | 必选 |\n| ------------- | -------------------------------------------------------------------------------------------------- | --------------- | ------ | ---- |\n| controlPoints | 控制点数组，用于定义曲线的形状。如果不指定，将会通过 `curveOffset` 和 `curvePosition` 来计算控制点 | [Point](#point) | -      |      |\n| curvePosition | 控制点在两端点连线上的相对位置，范围为`0-1`                                                        | number          | 0.5    |      |\n| curveOffset   | 控制点距离两端点连线的距离，可理解为控制边的弯曲程度                                               | number          | 30     |      |\n\n#### Point\n\n```typescript\ntype Point = [number, number] | [number, number, number] | Float32Array;\n```\n\n## 示例\n\n### 内置二次贝塞尔曲线边效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n    },\n    {\n      id: 'node2',\n    },\n    {\n      id: 'node3',\n    },\n    {\n      id: 'node4',\n    },\n    {\n      id: 'node5',\n    },\n    {\n      id: 'node6',\n    },\n  ],\n  edges: [\n    {\n      id: 'line-default',\n      source: 'node1',\n      target: 'node2',\n    },\n    {\n      id: 'line-active',\n      source: 'node1',\n      target: 'node3',\n      states: ['active'],\n    },\n    {\n      id: 'line-selected',\n      source: 'node1',\n      target: 'node4',\n      states: ['selected'],\n    },\n    {\n      id: 'line-highlight',\n      source: 'node1',\n      target: 'node5',\n      states: ['highlight'],\n    },\n    {\n      id: 'line-inactive',\n      source: 'node1',\n      target: 'node6',\n      states: ['inactive'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  edge: {\n    type: 'quadratic',\n    style: {\n      labelText: (d) => d.id,\n      labelBackground: true,\n      endArrow: true,\n      badge: true,\n      badgeText: '\\ue603',\n      badgeFontFamily: 'iconfont',\n      badgeBackgroundWidth: 12,\n      badgeBackgroundHeight: 12,\n    },\n  },\n  layout: {\n    type: 'radial',\n    unitRadius: 220,\n    linkDistance: 220,\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/BaseNode.en.md) -->\n---\ntitle: Common Node Configuration\norder: 1\n---\n\nThis document introduces the common configuration properties for built-in nodes.\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {}, // Node style\n    state: {}, // State style\n    palette: {}, // Palette configuration\n    animation: {}, // Animation configuration\n  },\n});\n```\n\n| Property  | Description                                                    | Type                    | Default  | Required |\n| --------- | -------------------------------------------------------------- | ----------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name         | [Type](#type)           | `circle` |          |\n| style     | Node style configuration, including color, size, etc.          | [Style](#style)         | -        |          |\n| state     | Style configuration for different states                       | [State](#state)         | -        |          |\n| palette   | Define node palette for mapping colors based on different data | [Palette](#palette)     | -        |          |\n| animation | Define animation effects for nodes                             | [Animation](#animation) | -        |          |\n\n## Type\n\nSpecifies the node type, built-in node type name or custom node name. Default is `circle`. **⚠️ Note**: This determines the shape of the main graphic.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: The `type` property also supports dynamic configuration, allowing you to dynamically select node types based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    // Static configuration\n    type: 'circle',\n\n    // Dynamic configuration - arrow function form\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // Dynamic configuration - regular function form (can access graph instance)\n    type: function (datum) {\n      console.log(this); // graph instance\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\nAvailable values:\n\n- `circle`: [Circle Node](/en/manual/element/node/circle)\n- `diamond`: [Diamond Node](/en/manual/element/node/diamond)\n- `donut`: [Donut Node](/en/manual/element/node/donut)\n- `ellipse`: [Ellipse Node](/en/manual/element/node/ellipse)\n- `hexagon`: [Hexagon Node](/en/manual/element/node/hexagon)\n- `html`: [HTML Node](/en/manual/element/node/html)\n- `image`: [Image Node](/en/manual/element/node/image)\n- `rect`: [Rectangle Node](/en/manual/element/node/rect)\n- `star`: [Star Node](/en/manual/element/node/star)\n- `triangle`: [Triangle Node](/en/manual/element/node/triangle)\n\n## Style\n\nDefines the style of nodes, including color, size, etc.\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ Dynamic Configuration**: All the following style properties support dynamic configuration, meaning you can pass functions to dynamically calculate property values based on node data:\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // Static configuration\n      fill: '#1783FF',\n\n      // Dynamic configuration - arrow function form\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // Dynamic configuration - regular function form (can access graph instance)\n      lineWidth: function (datum) {\n        console.log(this); // graph instance\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // Nested properties also support dynamic configuration\n      labelText: (datum) => `Node: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\nWhere the `datum` parameter is the node data object (`NodeData`), containing all data information of the node.\n\nA complete node consists of the following parts:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key`: The main graphic of the node, representing the primary shape of the node, such as rectangle, circle, etc.\n- `label`: Text label, usually used to display the name or description of the node\n- `icon`: Icon graphic, usually used to display node icons, can be images or text icons\n- `badge`: Badge, by default located at the top-right corner of the node\n- `halo`: Graphic showing halo effect around the main graphic\n- `port`: Connection points on the node, used to connect edges\n\nThe following style configurations are explained in order by atomic graphics:\n\n### Main Graphic Style\n\nThe main graphic is the core part of the node, defining the basic shape and appearance of the node. Here are common configuration scenarios:\n\n#### Basic Style Configuration\n\nSetting the basic appearance of nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // Blue fill\n      stroke: '#1A1A1A', // Dark stroke\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Transparency and Shadow Effects\n\nAdding transparency and shadow effects to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Dashed Border Style\n\nCreating nodes with dashed borders:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete main graphic style configuration is as follows:\n\n| Property                        | Description                                                                                                                                      | Type                          | Default   | Required |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- | --------- | -------- |\n| collapsed                       | Whether the current node/combo is collapsed                                                                                                      | boolean                       | false     |          |\n| cursor                          | Node mouse hover style, [options](#cursor)                                                                                                       | string                        | default   |          |\n| fill                            | Node fill color                                                                                                                                  | string                        | `#1783FF` |          |\n| fillOpacity                     | Node fill color transparency                                                                                                                     | number \\| string              | 1         |          |\n| increasedLineWidthForHitTesting | When lineWidth is small, the interactive area also becomes small. Sometimes we want to increase this area to make \"thin lines\" easier to pick up | number                        | 0         |          |\n| lineCap                         | Node stroke end style                                                                                                                            | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash                        | Node stroke dash style                                                                                                                           | number[]                      | -         |          |\n| lineDashOffset                  | Node stroke dash offset                                                                                                                          | number                        | -         |          |\n| lineJoin                        | Node stroke join style                                                                                                                           | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth                       | Node stroke width                                                                                                                                | number                        | 1         |          |\n| opacity                         | Node transparency                                                                                                                                | number \\| string              | 1         |          |\n| pointerEvents                   | How the node responds to pointer events, [options](#pointerevents)                                                                               | string                        | `auto`    |          |\n| shadowBlur                      | Node shadow blur                                                                                                                                 | number                        | -         |          |\n| shadowColor                     | Node shadow color                                                                                                                                | string                        | -         |          |\n| shadowOffsetX                   | Node shadow offset in x-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowOffsetY                   | Node shadow offset in y-axis direction                                                                                                           | number \\| string              | -         |          |\n| shadowType                      | Node shadow type                                                                                                                                 | `inner` \\| `outer`            | `outer`   |          |\n| size                            | Node size, quick setting for node width and height, [options](#size)                                                                             | number \\| number[]            | 32        |          |\n| stroke                          | Node stroke color                                                                                                                                | string                        | `#000`    |          |\n| strokeOpacity                   | Node stroke color transparency                                                                                                                   | number \\| string              | 1         |          |\n| transform                       | Transform property allows you to rotate, scale, skew or translate the given node                                                                 | string                        | -         |          |\n| transformOrigin                 | Rotation and scaling center, also called transformation center                                                                                   | string                        | -         |          |\n| visibility                      | Whether the node is visible                                                                                                                      | `visible` \\| `hidden`         | `visible` |          |\n| x                               | Node x coordinate                                                                                                                                | number                        | 0         |          |\n| y                               | Node y coordinate                                                                                                                                | number                        | 0         |          |\n| z                               | Node z coordinate                                                                                                                                | number                        | 0         |          |\n| zIndex                          | Node rendering level                                                                                                                             | number                        | 0         |          |\n\n#### Size\n\nNode size, quick setting for node width and height, supports three configuration methods:\n\n- number: Indicates that the node width and height are the same as the specified value\n- [number, number]: Indicates that the node width and height are represented by array elements indicating the node's width and height respectively\n- [number, number, number]: Indicates that the node width, height, and depth are represented by array elements\n\n#### PointerEvents\n\nThe `pointerEvents` property controls how graphics respond to interaction events. You can refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events).\n\nAvailable values: `visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\nIn short, `fill`, `stroke`, and `visibility` can independently or in combination affect pick behavior. Currently supports the following keywords:\n\n- **`auto`**: Default value, equivalent to `visiblepainted`\n- **`none`**: Will never be a target for responding to events\n- **`visiblepainted`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n- **`visiblefill`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n- **`visiblestroke`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n- **`visible`**: Will respond to events only if the following conditions are met:\n  - `visibility` is set to `visible`, i.e., the graphic is visible\n  - Triggered in the graphic fill or stroke area, not affected by the values of `fill` and `stroke`\n- **`painted`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area and `fill` takes a non-`none` value; or triggered in the graphic stroke area and `stroke` takes a non-`none` value\n  - Not affected by the value of `visibility`\n- **`fill`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic fill area, not affected by the value of `fill`\n  - Not affected by the value of `visibility`\n- **`stroke`**: Will respond to events only if the following conditions are met:\n  - Triggered in the graphic stroke area, not affected by the value of `stroke`\n  - Not affected by the value of `visibility`\n- **`all`**: Will respond to events as long as entering the fill and stroke areas of the graphic, not affected by the values of `fill`, `stroke`, and `visibility`\n\n**Usage Examples:**\n\n```js\n// Example 1: Only stroke area responds to events\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // Only stroke responds to events\n    },\n  },\n});\n\n// Example 2: Completely unresponsive to events\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // Node does not respond to any events\n    },\n  },\n});\n```\n\n#### Cursor\n\nAvailable values: `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`\n\n### Label Style\n\nLabels are used to display text information of nodes, supporting various style configurations and layout methods. Here are common usage scenarios:\n\n#### Basic Text Label\n\nThe simplest text label configuration:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Node Name',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multi-line Text Label\n\nWhen text is long, you can set automatic line wrapping:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'This is a very long node name that needs line wrapping',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Label with Background\n\nAdding background to labels to improve readability:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: 'Important Node',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete label style configuration is as follows:\n\n| Property                 | Description                                                                                                                        | Type                                                                        | Default   | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | -------- |\n| label                    | Whether to display node label                                                                                                      | boolean                                                                     | true      |          |\n| labelCursor              | Style displayed when mouse hovers over node label, [options](#cursor)                                                              | string                                                                      | `default` |          |\n| labelFill                | Node label text color                                                                                                              | string                                                                      | -         |          |\n| labelFontFamily          | Node label font family                                                                                                             | string                                                                      | -         |          |\n| labelFontSize            | Node label font size                                                                                                               | number                                                                      | 12        |          |\n| labelFontStyle           | Node label font style                                                                                                              | `normal` \\| `italic` \\| `oblique`                                           | -         |          |\n| labelFontVariant         | Node label font variant                                                                                                            | `normal` \\| `small-caps` \\| string                                          | -         |          |\n| labelFontWeight          | Node label font weight                                                                                                             | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |          |\n| labelLeading             | Line spacing                                                                                                                       | number                                                                      | 0         |          |\n| labelLetterSpacing       | Node label letter spacing                                                                                                          | number \\| string                                                            | -         |          |\n| labelLineHeight          | Node label line height                                                                                                             | number \\| string                                                            | -         |          |\n| labelMaxLines            | Maximum number of lines for node label                                                                                             | number                                                                      | 1         |          |\n| labelMaxWidth            | Maximum width of node label, [options](#labelmaxwidth)                                                                             | number \\| string                                                            | `200%`    |          |\n| labelOffsetX             | Node label offset in x-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelOffsetY             | Node label offset in y-axis direction                                                                                              | number                                                                      | 0         |          |\n| labelPadding             | Node label padding                                                                                                                 | number \\| number[]                                                          | 0         |          |\n| labelPlacement           | Position of node label relative to node main graphic, [options](#labelplacement)                                                   | string                                                                      | `bottom`  |          |\n| labelText                | Node label text content                                                                                                            | `string` \\| `(datum) => string`                                             | -         |          |\n| labelTextAlign           | Node label text horizontal alignment                                                                                               | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |          |\n| labelTextBaseline        | Node label text baseline                                                                                                           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |          |\n| labelTextDecorationColor | Node label text decoration line color                                                                                              | string                                                                      | -         |          |\n| labelTextDecorationLine  | Node label text decoration line                                                                                                    | string                                                                      | -         |          |\n| labelTextDecorationStyle | Node label text decoration line style                                                                                              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |          |\n| labelTextOverflow        | Node label text overflow handling                                                                                                  | `clip` \\| `ellipsis` \\| string                                              | -         |          |\n| labelTextPath            | Node label text path                                                                                                               | Path                                                                        | -         |          |\n| labelWordWrap            | Whether node label enables automatic line wrapping. After enabling labelWordWrap, parts exceeding labelMaxWidth wrap automatically | boolean                                                                     | false     |          |\n| labelZIndex              | Node label rendering level                                                                                                         | number                                                                      | 0         |          |\n\n#### LabelPlacement\n\nAvailable values: `left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\nAfter enabling automatic line wrapping `labelWordWrap`, text wraps when exceeding this width:\n\n- string: Defines maximum width as a percentage relative to node width. For example, `50%` means label width does not exceed half of the node width\n- number: Defines maximum width in pixels. For example, 100 means the maximum width of the label is 100 pixels\n\nFor example, setting multi-line label text:\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### Label Background Style\n\nLabel background is used to display the background of node labels:\n\n| Property                      | Description                                                                                                                                                                         | Type                                     | Default   |\n| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | Whether to display node label background                                                                                                                                            | boolean                                  | false     |\n| labelBackgroundCursor         | Node label background mouse hover style, [options](#cursor)                                                                                                                         | string                                   | `default` |\n| labelBackgroundFill           | Node label background fill color                                                                                                                                                    | string                                   | -         |\n| labelBackgroundFillOpacity    | Node label background transparency                                                                                                                                                  | number                                   | 1         |\n| labelBackgroundHeight         | Node label background height                                                                                                                                                        | string \\| number                         | -         |\n| labelBackgroundLineDash       | Node label background dash configuration                                                                                                                                            | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | Node label background dash offset                                                                                                                                                   | number                                   | -         |\n| labelBackgroundLineWidth      | Node label background stroke line width                                                                                                                                             | number                                   | -         |\n| labelBackgroundRadius         | Node label background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | Node label background shadow blur degree                                                                                                                                            | number                                   | -         |\n| labelBackgroundShadowColor    | Node label background shadow color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundShadowOffsetX  | Node label background shadow X direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundShadowOffsetY  | Node label background shadow Y direction offset                                                                                                                                     | number                                   | -         |\n| labelBackgroundStroke         | Node label background stroke color                                                                                                                                                  | string                                   | -         |\n| labelBackgroundStrokeOpacity  | Node label background stroke transparency                                                                                                                                           | number \\| string                         | 1         |\n| labelBackgroundVisibility     | Whether node label background is visible                                                                                                                                            | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | Node label background rendering level                                                                                                                                               | number                                   | 1         |\n\n### Halo Style\n\nHalo is an effect displayed around the node's main graphic, usually used for highlighting or indicating special states of nodes.\n\n#### Basic Halo Effect\n\nAdding basic halo effect to nodes:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete halo style configuration is as follows:\n\n| Property          | Description                                                                                                                   | Type                   | Default                                 | Required |\n| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------------------------------------- | -------- |\n| halo              | Whether to display node halo                                                                                                  | boolean                | false                                   |          |\n| haloCursor        | Node halo mouse hover style, [options](#cursor)                                                                               | string                 | `default`                               |          |\n| haloDraggable     | Whether node halo allows dragging                                                                                             | boolean                | true                                    |          |\n| haloDroppable     | Whether node halo allows receiving dragged elements                                                                           | boolean                | true                                    |          |\n| haloFillRule      | Node halo fill rule                                                                                                           | `nonzero` \\| `evenodd` | -                                       |          |\n| haloFilter        | Node halo filter                                                                                                              | string                 | -                                       |          |\n| haloLineWidth     | Node halo stroke width                                                                                                        | number                 | 3                                       |          |\n| haloPointerEvents | Whether node halo effect responds to pointer events, [options](#pointerevents)                                                | string                 | `none`                                  |          |\n| haloStroke        | Node halo stroke color, **this property is used to set the color of the halo around the node, helping to highlight the node** | string                 | Consistent with main graphic fill color |          |\n| haloStrokeOpacity | Node halo stroke color transparency                                                                                           | number                 | 0.25                                    |          |\n| haloVisibility    | Node halo visibility                                                                                                          | `visible` \\| `hidden`  | `visible`                               |          |\n| haloZIndex        | Node halo rendering level                                                                                                     | number                 | -1                                      |          |\n\n### Icon Style\n\nNode icons support three common usage methods: text icons, image icons, and IconFont icons. The configurations for these three methods are shown below:\n\n#### 1. Text Icons\n\nUsing text directly as icons, suitable for simple identifiers:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // Icon text content\n      iconFill: '#C41D7F', // Deep pink icon\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. Image Icons\n\nUsing images as icons, supporting various image formats:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont Icons\n\nUsing IconFont font icons, you need to import the corresponding font files first:\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // Light blue background\n      stroke: '#1890FF', // Blue border\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete icon style configuration is as follows:\n\n| Property                | Description                                          | Type                                                                        | Default                     |\n| ----------------------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------- |\n| icon                    | Whether to display node icon                         | boolean                                                                     | true                        |\n| iconFill                | Node icon text color                                 | string                                                                      | -                           |\n| iconFontFamily          | Node icon font family                                | string                                                                      | -                           |\n| iconFontSize            | Node icon font size                                  | number                                                                      | 16                          |\n| iconFontStyle           | Node icon font style                                 | `normal` \\| `italic` \\| `oblique`                                           | `normal`                    |\n| iconFontVariant         | Node icon font variant                               | `normal` \\| `small-caps` \\| string                                          | `normal`                    |\n| iconFontWeight          | Node icon font weight                                | number \\| string                                                            | `normal`                    |\n| iconHeight              | Node icon height                                     | number                                                                      | Half of main graphic height |\n| iconLetterSpacing       | Node icon text letter spacing                        | number \\| string                                                            | -                           |\n| iconLineHeight          | Node icon text line height                           | number \\| string                                                            | -                           |\n| iconMaxLines            | Maximum lines for node icon text                     | number                                                                      | 1                           |\n| iconRadius              | Node icon border radius                              | number                                                                      | 0                           |\n| iconSrc                 | Node image source. Has higher priority than iconText | string                                                                      | -                           |\n| iconText                | Node icon text                                       | string                                                                      | -                           |\n| iconTextAlign           | Node icon text horizontal alignment                  | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`                      |\n| iconTextBaseline        | Node icon text baseline                              | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`                |\n| iconTextDecorationColor | Node icon text decoration line color                 | string                                                                      | -                           |\n| iconTextDecorationLine  | Node icon text decoration line                       | string                                                                      | -                           |\n| iconTextDecorationStyle | Node icon text decoration line style                 | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`                     |\n| iconTextOverflow        | Node icon text overflow handling                     | `clip` \\| `ellipsis` \\| string                                              | `clip`                      |\n| iconWidth               | Node icon width                                      | number                                                                      | Half of main graphic width  |\n| iconWordWrap            | Whether node icon text automatically wraps           | boolean                                                                     | -                           |\n\n### Badge Style\n\nBadges are small markers displayed on nodes, usually used to show status, quantity, or other auxiliary information. Supports displaying multiple badges simultaneously with customizable positions.\n\n#### Single Badge\n\nAdding a simple badge to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // Default display at the top\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Multiple Badges\n\nAdding multiple badges at different positions to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // Whether to display badges\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // Badge background color palette\n      badgeFontSize: 7, // Badge font size\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Badge Style\n\nCompletely customizing badge appearance:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // Red background\n          fill: '#fff', // White text\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete badge style configuration is as follows:\n\n| Property     | Description                      | Type                                  | Default                           |\n| ------------ | -------------------------------- | ------------------------------------- | --------------------------------- |\n| badge        | Whether the node displays badges | boolean                               | true                              |\n| badgePalette | Badge background color palette   | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | Node badge settings              | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| Property                 | Description                                                                                                                                                                                                                                                                                                         | Type                                                                                                                                                                   | Default      |\n| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | Whether node badge displays background                                                                                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | Node badge background mouse hover style, [options](#cursor)                                                                                                                                                                                                                                                         | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | Node badge background fill color. If not specified, badgePalette is considered for allocation in order                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | Node badge background fill transparency                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | Node badge background filter                                                                                                                                                                                                                                                                                        | string                                                                                                                                                                 | -            |\n| backgroundHeight         | Node badge background height                                                                                                                                                                                                                                                                                        | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | Node badge background dash configuration                                                                                                                                                                                                                                                                            | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | Node badge background dash offset                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | Node badge background stroke line width                                                                                                                                                                                                                                                                             | number                                                                                                                                                                 | -            |\n| backgroundRadius         | Node badge background border radius <br> - number: Uniform setting for four border radii <br> - number[]: Set four border radii separately, automatically supplement missing values <br> - string: Similar to [CSS padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) property, separated by spaces | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | Node badge background shadow blur degree                                                                                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | Node badge background shadow color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | Node badge background shadow X direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | Node badge background shadow Y direction offset                                                                                                                                                                                                                                                                     | number                                                                                                                                                                 | -            |\n| backgroundStroke         | Node badge background stroke color                                                                                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | Node badge background stroke transparency                                                                                                                                                                                                                                                                           | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | Whether node badge background is visible                                                                                                                                                                                                                                                                            | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | Node badge background rendering level                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | -            |\n| fill                     | Node badge text color                                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| fontFamily               | Node badge font family                                                                                                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| fontSize                 | Node badge font size                                                                                                                                                                                                                                                                                                | number                                                                                                                                                                 | 8            |\n| fontStyle                | Node badge font style                                                                                                                                                                                                                                                                                               | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | Node badge font variant                                                                                                                                                                                                                                                                                             | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | Node badge font weight                                                                                                                                                                                                                                                                                              | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | Node badge line height                                                                                                                                                                                                                                                                                              | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | Node badge line width                                                                                                                                                                                                                                                                                               | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | Maximum lines for node badge text                                                                                                                                                                                                                                                                                   | number                                                                                                                                                                 | 1            |\n| offsetX                  | Node badge offset in x-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| offsetY                  | Node badge offset in y-axis direction                                                                                                                                                                                                                                                                               | number                                                                                                                                                                 | 0            |\n| padding                  | Node badge padding                                                                                                                                                                                                                                                                                                  | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | Position of node badge relative to node main graphic. If not specified, defaults to clockwise arrangement starting from top-right corner                                                                                                                                                                            | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | Node badge text content                                                                                                                                                                                                                                                                                             | string                                                                                                                                                                 | -            |\n| textAlign                | Node badge text horizontal alignment                                                                                                                                                                                                                                                                                | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | Node badge text baseline                                                                                                                                                                                                                                                                                            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | Node badge text decoration line color                                                                                                                                                                                                                                                                               | string                                                                                                                                                                 | -            |\n| textDecorationLine       | Node badge text decoration line                                                                                                                                                                                                                                                                                     | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | Node badge text decoration line style                                                                                                                                                                                                                                                                               | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | Node badge text overflow handling                                                                                                                                                                                                                                                                                   | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | Whether node badge is visible                                                                                                                                                                                                                                                                                       | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | Whether node badge text automatically wraps                                                                                                                                                                                                                                                                         | boolean                                                                                                                                                                | -            |\n| zIndex                   | Node badge rendering level                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                 | 3            |\n\n### Port Style\n\nPorts are connection points on nodes, used to connect edges. Supports adding multiple ports at different positions on nodes with customizable styles.\n\n#### Basic Ports\n\nAdding four basic directional ports to a node:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Custom Position Ports\n\nUsing percentages or absolute coordinates to precisely position ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // Relative position: 20% from top-left\n        { key: 'custom2', placement: [0.8, 0] }, // Relative position: 80% from top-right\n        { key: 'custom3', placement: [1, 0.5] }, // Relative position: right center\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### Differentiated Port Styles\n\nSetting different styles for different ports:\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // Green input port\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // Red output port\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // Unified stroke color\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\nThe complete port style configuration is as follows:\n\n| Property | Description                                                  | Type                                | Default | Required |\n| -------- | ------------------------------------------------------------ | ----------------------------------- | ------- | -------- |\n| port     | Whether the node displays ports                              | boolean                             | true    |          |\n| ports    | Node port configuration, supports configuring multiple ports | [PortStyleProps](#portstyleprops)[] | -       |          |\n\n#### PortStyleProps\n\n| Property          | Description                                                                                                                                                                                                                                                  | Type                                                                                                                                                                                                   | Default   | Required |\n| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | -------- |\n| key               | Key value of node port, defaults to the index of the node port                                                                                                                                                                                               | string                                                                                                                                                                                                 | -         |          |\n| placement         | Position of node port relative to node main graphic                                                                                                                                                                                                          | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓        |\n| r                 | Node port radius <br> - If set to undefined, the port is treated as a point, not displayed on canvas but exists, edges will preferentially connect to the nearest port <br> - If set to a number, the port is treated as a circle with radius specified here | number                                                                                                                                                                                                 | -         |          |\n| linkToCenter      | Whether edges connect to the center of the node port <br> - If true, edges connect to the center of the node port <br> - If false, edges connect to the edge of the node port                                                                                | boolean                                                                                                                                                                                                | false     |          |\n| cursor            | Node port mouse hover style, [options](#cursor)                                                                                                                                                                                                              | string                                                                                                                                                                                                 | `default` |          |\n| fill              | Node port fill color                                                                                                                                                                                                                                         | string                                                                                                                                                                                                 | -         |          |\n| fillOpacity       | Node port fill transparency                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | 1         |          |\n| isBillboard       | Whether node port has Billboard effect                                                                                                                                                                                                                       | boolean                                                                                                                                                                                                | -         |          |\n| isSizeAttenuation | Whether node port enables size attenuation                                                                                                                                                                                                                   | boolean                                                                                                                                                                                                | -         |          |\n| lineDash          | Node port stroke dash configuration                                                                                                                                                                                                                          | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |          |\n| lineDashOffset    | Node port stroke dash offset                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| lineWidth         | Node port stroke line width                                                                                                                                                                                                                                  | number                                                                                                                                                                                                 | -         |          |\n| shadowBlur        | Node port shadow blur degree                                                                                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |          |\n| shadowColor       | Node port shadow color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| shadowOffsetX     | Node port shadow X direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| shadowOffsetY     | Node port shadow Y direction offset                                                                                                                                                                                                                          | number                                                                                                                                                                                                 | -         |          |\n| stroke            | Node port stroke color                                                                                                                                                                                                                                       | string                                                                                                                                                                                                 | -         |          |\n| strokeOpacity     | Node port stroke transparency                                                                                                                                                                                                                                | number \\| string                                                                                                                                                                                       | 1         |          |\n| visibility        | Whether node port is visible                                                                                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |          |\n| zIndex            | Node port rendering level                                                                                                                                                                                                                                    | number                                                                                                                                                                                                 | 2         |          |\n\n## State\n\nIn some interactive behaviors, such as clicking to select a node or hovering to activate an edge, only certain state identifications are made on the element. To reflect these states in the visual space seen by end users, we need to set different graphic element styles for different states to respond to changes in the state of the graphic element.\n\nG6 provides several built-in states, including selected, highlight, active, inactive, and disabled. In addition, it also supports custom states to meet more specific needs. For each state, developers can define a set of style rules that will override the element's default styles.\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThe data structure is as follows:\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\nFor example, when a node is in the `focus` state, you can add a stroke with width 3 and orange color.\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // Stroke width\n        stroke: 'orange', // Stroke color\n      },\n    },\n  },\n});\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\nDefines animation effects for nodes, supporting the following two configuration methods:\n\n1. Disable all node animations\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. Configure stage animations\n\nStage animations refer to animation effects when nodes enter the canvas, update, or leave the canvas. Currently supported stages include:\n\n- `enter`: Animation when nodes enter the canvas\n- `update`: Animation when nodes are updated\n- `exit`: Animation when nodes leave the canvas\n- `show`: Animation when nodes are shown from hidden state\n- `hide`: Animation when nodes are hidden\n- `collapse`: Animation when nodes are collapsed\n- `expand`: Animation when nodes are expanded\n\nYou can refer to [Animation Paradigm](/en/manual/animation/animation#animation-paradigm) to use animation syntax to configure nodes, such as:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // Only animate x and y properties during updates\n          \"duration\": 1000, // Animation duration\n          \"easing\": \"linear\" // Easing function\n        }\n      ]\n    }\n  }\n}\n```\n\nYou can also use built-in animation effects:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // Use fade animation\n      \"update\": \"translate\", // Use translate animation\n      \"exit\": \"fade\" // Use fade animation\n    }\n  }\n}\n```\n\nYou can pass false to disable animations for specific stages:\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // Disable node entrance animation\n    }\n  }\n}\n```\n\n## Palette\n\nDefines the color palette for nodes, i.e., predefined node color pool, and allocates according to rules, mapping colors to the `fill` property.\n\n> For the definition of palettes, please refer to [Palette](/en/manual/theme/palette).\n\n| Property | Description                                                                                                           | Type                          | Default |\n| -------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ------- |\n| color    | Palette colors. If the palette is registered, you can directly specify its registration name, or accept a color array | string \\| string[]            | -       |\n| field    | Specify the grouping field in element data. If not specified, defaults to id as the grouping field                    | string \\| ((datum) => string) | `id`    |\n| invert   | Whether to invert the palette                                                                                         | boolean                       | false   |\n| type     | Specify the current palette type. <br> - `group`: Discrete palette <br> - `value`: Continuous palette                 | `group` \\| `value`            | `group` |\n\nFor example, assigning node colors to a group of data by `category` field, so that nodes of the same category have the same color:\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\nYou can also use default configuration:\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau is the palette name, defaults to assigning colors based on ID\n  }\n}\n```\n\nThe effect is shown in the figure below:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/BaseNode.zh.md) -->\n---\ntitle: 节点通用配置项\norder: 1\n---\n\n本文介绍内置节点通用属性配置。\n\n## NodeOptions\n\n```js {5-9}\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {}, // 节点样式\n    state: {}, // 状态样式\n    palette: {}, // 色板配置\n    animation: {}, // 动画配置\n  },\n});\n```\n\n| 属性      | 描述                                         | 类型                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](#type)           | `circle` |      |\n| style     | 节点样式配置，包括颜色、大小等               | [Style](#style)         | -        |      |\n| state     | 不同状态下的样式配置                         | [State](#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](#animation) | -        |      |\n\n## Type\n\n指定节点类型，内置节点类型名称或自定义节点的名称。默认为 `circle`(圆形)。**⚠️ 注意**：这里决定了主图形的形状。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n**⚠️ 动态配置说明**：`type` 属性同样支持动态配置，可以根据节点数据动态选择节点类型：\n\n```js\nconst graph = new Graph({\n  node: {\n    // 静态配置\n    type: 'circle',\n\n    // 动态配置 - 箭头函数形式\n    type: (datum) => datum.data.nodeType || 'circle',\n\n    // 动态配置 - 普通函数形式（可访问 graph 实例）\n    type: function (datum) {\n      console.log(this); // graph 实例\n      return datum.data.category === 'important' ? 'diamond' : 'circle';\n    },\n  },\n});\n```\n\n可选值有：\n\n- `circle`：[圆形节点](/manual/element/node/circle)\n- `diamond`：[菱形节点](/manual/element/node/diamond)\n- `donut`：[甜甜圈节点](/manual/element/node/donut)\n- `ellipse`：[椭圆节点](/manual/element/node/ellipse)\n- `hexagon`：[六边形节点](/manual/element/node/hexagon)\n- `html`：[HTML 节点](/manual/element/node/html)\n- `image`：[图片节点](/manual/element/node/image)\n- `rect`：[矩形节点](/manual/element/node/rect)\n- `star`：[星形节点](/manual/element/node/star)\n- `triangle`：[三角形节点](/manual/element/node/triangle)\n\n## Style\n\n定义节点的样式，包括颜色、大小等。\n\n```js {3}\nconst graph = new Graph({\n  node: {\n    style: {},\n  },\n});\n```\n\n**⚠️ 动态配置说明**：以下所有样式属性都支持动态配置，即可以传入函数来根据节点数据动态计算属性值：\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      // 静态配置\n      fill: '#1783FF',\n\n      // 动态配置 - 箭头函数形式\n      stroke: (datum) => (datum.data.isActive ? '#FF0000' : '#000000'),\n\n      // 动态配置 - 普通函数形式（可访问 graph 实例）\n      lineWidth: function (datum) {\n        console.log(this); // graph 实例\n        return datum.data.importance > 5 ? 3 : 1;\n      },\n\n      // 嵌套属性也支持动态配置\n      labelText: (datum) => `节点: ${datum.id}`,\n      badges: (datum) => datum.data.tags.map((tag) => ({ text: tag })),\n    },\n  },\n});\n```\n\n其中 `datum` 参数为节点数据对象 (`NodeData`)，包含节点的所有数据信息。\n\n一个完整的节点由以下几部分构成：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n- `key` ：节点的主图形，表示节点的主要形状，例如矩形、圆形等；\n- `label` ：文本标签，通常用于展示节点的名称或描述；\n- `icon` ：图标图形，通常用于展示节点的图标，可以是图片或者文本图标；\n- `badge` ：默认位于节点右上角的徽标；\n- `halo` ：主图形周围展示的光晕效果的图形；\n- `port` ：节点上的连接点，用于连接边。\n\n以下样式配置将按原子图形依次说明：\n\n### 主图形样式\n\n主图形是节点的核心部分，定义了节点的基本形状和外观。以下是常见的配置场景：\n\n#### 基础样式配置\n\n设置节点的基本外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#5B8FF9', // 蓝色填充\n      stroke: '#1A1A1A', // 深色描边\n      lineWidth: 2,\n      size: 40,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 透明度和阴影效果\n\n为节点添加透明度和阴影效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#61DDAA',\n      fillOpacity: 0.85,\n      shadowColor: 'rgba(97, 221, 170, 0.4)',\n      shadowBlur: 12,\n      shadowOffsetX: 2,\n      shadowOffsetY: 4,\n      stroke: '#F0F0F0',\n      lineWidth: 1,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 虚线边框样式\n\n创建带虚线边框的节点：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF1F0',\n      stroke: '#F5222D',\n      lineWidth: 2,\n      lineDash: [6, 4],\n      lineCap: 'round',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的主图形样式配置：\n\n| 属性                            | 描述                                                                                      | 类型                          | 默认值    | 必选 |\n| ------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------- | --------- | ---- |\n| collapsed                       | 当前节点/组合是否折叠                                                                     | boolean                       | false     |      |\n| cursor                          | 节点鼠标移入样式，[配置项](#cursor)                                                       | string                        | default   |      |\n| fill                            | 节点填充色                                                                                | string                        | `#1783FF` |      |\n| fillOpacity                     | 节点填充色透明度                                                                          | number \\| string              | 1         |      |\n| increasedLineWidthForHitTesting | 当 lineWidth 较小时，可交互区域也随之变小，有时我们想增大这个区域，让\"细线\"更容易被拾取到 | number                        | 0         |      |\n| lineCap                         | 节点描边端点样式                                                                          | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash                        | 节点描边虚线样式                                                                          | number[]                      | -         |      |\n| lineDashOffset                  | 节点描边虚线偏移量                                                                        | number                        | -         |      |\n| lineJoin                        | 节点描边连接处样式                                                                        | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth                       | 节点描边宽度                                                                              | number                        | 1         |      |\n| opacity                         | 节点透明度                                                                                | number \\| string              | 1         |      |\n| pointerEvents                   | 节点如何响应指针事件，[配置项](#pointerevents)                                            | string                        | `auto`    |      |\n| shadowBlur                      | 节点阴影模糊度                                                                            | number                        | -         |      |\n| shadowColor                     | 节点阴影颜色                                                                              | string                        | -         |      |\n| shadowOffsetX                   | 节点阴影在 x 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowOffsetY                   | 节点阴影在 y 轴方向上的偏移量                                                             | number \\| string              | -         |      |\n| shadowType                      | 节点阴影类型                                                                              | `inner` \\| `outer`            | `outer`   |      |\n| size                            | 节点大小，快捷设置节点宽高，[配置项](#size)                                               | number \\| number[]            | 32        |      |\n| stroke                          | 节点描边色                                                                                | string                        | `#000`    |      |\n| strokeOpacity                   | 节点描边色透明度                                                                          | number \\| string              | 1         |      |\n| transform                       | transform 属性允许你旋转、缩放、倾斜或平移给定节点                                        | string                        | -         |      |\n| transformOrigin                 | 旋转与缩放中心，也称作变换中心                                                            | string                        | -         |      |\n| visibility                      | 节点是否可见                                                                              | `visible` \\| `hidden`         | `visible` |      |\n| x                               | 节点 x 坐标                                                                               | number                        | 0         |      |\n| y                               | 节点 y 坐标                                                                               | number                        | 0         |      |\n| z                               | 节点 z 坐标                                                                               | number                        | 0         |      |\n| zIndex                          | 节点渲染层级                                                                              | number                        | 0         |      |\n\n#### Size\n\n节点大小，快捷设置节点宽高，支持三种配置方式：\n\n- number：表示节点宽高相同为指定值\n- [number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度\n- [number, number, number]：表示节点宽高分别为数组元素依次表示节点的宽度、高度以及深度\n\n#### PointerEvents\n\n`pointerEvents` 属性控制图形如何响应交互事件，可参考 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events)。\n\n可选值有：`visible` | `visiblepainted` | `visiblestroke` | `non-transparent-pixel` | `visiblefill` | `visible` | `painted` | `fill` | `stroke` | `all` | `none` | `auto` | `inherit` | `initial` | `unset`\n\n简而言之，`fill`、`stroke` 和 `visibility` 都可以独立或组合影响拾取判定行为。目前支持以下关键词：\n\n- **`auto`**：默认值，等同于 `visiblepainted`\n- **`none`**：永远不会成为响应事件的目标\n- **`visiblepainted`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n- **`visiblefill`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n- **`visiblestroke`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n- **`visible`**：满足以下条件才会响应事件：\n  - `visibility` 设置为 `visible`，即图形为可见的\n  - 在图形填充或者描边区域触发，不受 `fill` 和 `stroke` 取值的影响\n- **`painted`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发同时 `fill` 取非 `none` 的值；或者在图形描边区域触发同时 `stroke` 取非 `none` 的值\n  - 不受 `visibility` 取值的影响\n- **`fill`**：满足以下条件才会响应事件：\n  - 在图形填充区域触发，不受 `fill` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`stroke`**：满足以下条件才会响应事件：\n  - 在图形描边区域触发，不受 `stroke` 取值的影响\n  - 不受 `visibility` 取值的影响\n- **`all`**：只要进入图形的填充和描边区域就会响应事件，不会受 `fill`、`stroke`、`visibility` 的取值影响\n\n**使用示例：**\n\n```js\n// 示例1：只有描边区域响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: 'none',\n      stroke: '#000',\n      lineWidth: 2,\n      pointerEvents: 'stroke', // 只有描边响应事件\n    },\n  },\n});\n\n// 示例2：完全不响应事件\nconst graph = new Graph({\n  node: {\n    style: {\n      pointerEvents: 'none', // 节点不响应任何事件\n    },\n  },\n});\n```\n\n#### Cursor\n\n可选值有：`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`\n\n### 标签样式\n\n标签用于显示节点的文本信息，支持多种样式配置和布局方式。以下是常见的使用场景：\n\n#### 基础文本标签\n\n最简单的文本标签配置：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '节点名称',\n      labelFill: '#262626',\n      labelFontSize: 12,\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多行文本标签\n\n当文本较长时，可以设置自动换行：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '这是一个很长的节点名称需要换行显示',\n      labelWordWrap: true,\n      labelMaxWidth: '150%',\n      labelMaxLines: 3,\n      labelTextOverflow: 'ellipsis',\n      labelFill: '#434343',\n      labelPlacement: 'bottom',\n      labelTextAlign: 'center',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 带背景的标签\n\n为标签添加背景，提高可读性：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 120,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      labelText: '重要节点',\n      labelBackground: true,\n      labelBackgroundFill: 'rgba(250, 140, 22, 0.1)',\n      labelBackgroundRadius: 6,\n      labelPadding: [6, 12],\n      labelFill: '#D4380D',\n      labelFontWeight: 'bold',\n      labelPlacement: 'bottom',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的标签样式配置：\n\n| 属性                     | 描述                                                                               | 类型                                                                        | 默认值    | 必选 |\n| ------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---- |\n| label                    | 是否显示节点标签                                                                   | boolean                                                                     | true      |      |\n| labelCursor              | 鼠标移入节点标签时显示的样式，[配置项](#cursor)                                    | string                                                                      | `default` |      |\n| labelFill                | 节点标签文字颜色                                                                   | string                                                                      | -         |      |\n| labelFontFamily          | 节点标签字体族                                                                     | string                                                                      | -         |      |\n| labelFontSize            | 节点标签字体大小                                                                   | number                                                                      | 12        |      |\n| labelFontStyle           | 节点标签字体样式                                                                   | `normal` \\| `italic` \\| `oblique`                                           | -         |      |\n| labelFontVariant         | 节点标签字体变种                                                                   | `normal` \\| `small-caps` \\| string                                          | -         |      |\n| labelFontWeight          | 节点标签字体粗细                                                                   | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       | -         |      |\n| labelLeading             | 行间距                                                                             | number                                                                      | 0         |      |\n| labelLetterSpacing       | 节点标签字间距                                                                     | number \\| string                                                            | -         |      |\n| labelLineHeight          | 节点标签行高                                                                       | number \\| string                                                            | -         |      |\n| labelMaxLines            | 节点标签最大行数                                                                   | number                                                                      | 1         |      |\n| labelMaxWidth            | 节点标签最大宽度，[配置项](#labelmaxwidth)                                         | number \\| string                                                            | `200%`    |      |\n| labelOffsetX             | 节点标签在 x 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelOffsetY             | 节点标签在 y 轴方向上的偏移量                                                      | number                                                                      | 0         |      |\n| labelPadding             | 节点标签内边距                                                                     | number \\| number[]                                                          | 0         |      |\n| labelPlacement           | 节点标签相对于节点主图形的位置，[配置项](#labelplacement)                          | string                                                                      | `bottom`  |      |\n| labelText                | 节点标签文字内容                                                                   | `string` \\| `(datum) => string`                                             | -         |      |\n| labelTextAlign           | 节点标签文本水平对齐方式                                                           | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`    |      |\n| labelTextBaseline        | 节点标签文本基线                                                                   | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | -         |      |\n| labelTextDecorationColor | 节点标签文本装饰线颜色                                                             | string                                                                      | -         |      |\n| labelTextDecorationLine  | 节点标签文本装饰线                                                                 | string                                                                      | -         |      |\n| labelTextDecorationStyle | 节点标签文本装饰线样式                                                             | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | -         |      |\n| labelTextOverflow        | 节点标签文本溢出处理方式                                                           | `clip` \\| `ellipsis` \\| string                                              | -         |      |\n| labelTextPath            | 节点标签文本路径                                                                   | Path                                                                        | -         |      |\n| labelWordWrap            | 节点标签是否开启自动折行。开启 labelWordWrap 后，超出 labelMaxWidth 的部分自动换行 | boolean                                                                     | false     |      |\n| labelZIndex              | 节点标签渲染层级                                                                   | number                                                                      | 0         |      |\n\n#### LabelPlacement\n\n可选值有：`left` | `right` | `top` | `bottom` | `left-top` | `left-bottom` | `right-top` | `right-bottom` | `top-left` | `top-right` | `bottom-left` | `bottom-right` | `center` | `bottom`\n\n#### LabelMaxWidth\n\n开启自动折行 `labelWordWrap` 后，超出该宽度则换行:\n\n- string: 表示以相对于节点宽度的百分比形式定义最大宽度。例如 `50%` 表示标签宽度不超过节点宽度的一半\n- number: 表示以像素值为单位定义最大宽度。例如 100 表示标签的最大宽度为 100 像素\n\n比如，设置多行标签文字：\n\n```json\n{\n  \"labelWordWrap\": true,\n  \"labelMaxWidth\": 200,\n  \"labelMaxLines\": 3\n}\n```\n\n### 标签背景样式\n\n标签背景用于显示节点标签的背景：\n\n| 属性                          | 描述                                                                                                           | 类型                                     | 默认值    |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | --------- |\n| labelBackground               | 节点标签背景是否显示                                                                                           | boolean                                  | false     |\n| labelBackgroundCursor         | 节点标签背景鼠标移入样式，[配置项](#cursor)                                                                    | string                                   | `default` |\n| labelBackgroundFill           | 节点标签背景填充色                                                                                             | string                                   | -         |\n| labelBackgroundFillOpacity    | 节点标签背景透明度                                                                                             | number                                   | 1         |\n| labelBackgroundHeight         | 节点标签背景高度                                                                                               | string \\| number                         | -         |\n| labelBackgroundLineDash       | 节点标签背景虚线配置                                                                                           | number \\| string \\|(number \\| string )[] | -         |\n| labelBackgroundLineDashOffset | 节点标签背景虚线偏移量                                                                                         | number                                   | -         |\n| labelBackgroundLineWidth      | 节点标签背景描边线宽                                                                                           | number                                   | -         |\n| labelBackgroundRadius         | 节点标签背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，不足则自动补充 | number \\| number[]                       | 0         |\n| labelBackgroundShadowBlur     | 节点标签背景阴影模糊程度                                                                                       | number                                   | -         |\n| labelBackgroundShadowColor    | 节点标签背景阴影颜色                                                                                           | string                                   | -         |\n| labelBackgroundShadowOffsetX  | 节点标签背景阴影 X 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundShadowOffsetY  | 节点标签背景阴影 Y 方向偏移                                                                                    | number                                   | -         |\n| labelBackgroundStroke         | 节点标签背景描边颜色                                                                                           | string                                   | -         |\n| labelBackgroundStrokeOpacity  | 节点标签背景描边透明度                                                                                         | number \\| string                         | 1         |\n| labelBackgroundVisibility     | 节点标签背景是否可见                                                                                           | `visible` \\| `hidden`                    | -         |\n| labelBackgroundZIndex         | 节点标签背景渲染层级                                                                                           | number                                   | 1         |\n\n### 光晕样式\n\n光晕是围绕节点主图形显示的效果，通常用于高亮显示或表示节点的特殊状态。\n\n#### 基础光晕效果\n\n为节点添加基本的光晕效果：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      lineWidth: 1.5,\n      halo: true,\n      haloStroke: '#1890FF',\n      haloLineWidth: 6,\n      haloStrokeOpacity: 0.3,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的光晕样式配置：\n\n| 属性              | 描述                                                                   | 类型                   | 默认值                       | 必选 |\n| ----------------- | ---------------------------------------------------------------------- | ---------------------- | ---------------------------- | ---- |\n| halo              | 节点光晕是否显示                                                       | boolean                | false                        |      |\n| haloCursor        | 节点光晕鼠标移入样式，[配置项](#cursor)                                | strig                  | `default`                    |      |\n| haloDraggable     | 节点光晕是否允许拖拽                                                   | boolean                | true                         |      |\n| haloDroppable     | 节点光晕是否允许接收被拖拽的元素                                       | boolean                | true                         |      |\n| haloFillRule      | 节点光晕填充规则                                                       | `nonzero` \\| `evenodd` | -                            |      |\n| haloFilter        | 节点光晕滤镜                                                           | string                 | -                            |      |\n| haloLineWidth     | 节点光晕描边宽度                                                       | number                 | 3                            |      |\n| haloPointerEvents | 节点光晕效果是否响应指针事件，[配置项](#pointerevents)                 | string                 | `none`                       |      |\n| haloStroke        | 节点光晕描边色，**此属性用于设置节点周围光晕的颜色，帮助突出显示节点** | string                 | 与主图形的填充色 `fill` 一致 |      |\n| haloStrokeOpacity | 节点光晕描边色透明度                                                   | number                 | 0.25                         |      |\n| haloVisibility    | 节点光晕可见性                                                         | `visible` \\| `hidden`  | `visible`                    |      |\n| haloZIndex        | 节点光晕渲染层级                                                       | number                 | -1                           |      |\n\n### 图标样式\n\n节点图标支持三种常见的使用方式：文字图标、图片图标和 IconFont 图标。下面分别展示这三种方式的配置：\n\n#### 1. 文字图标\n\n直接使用文字作为图标，适合简单的标识：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#FFF0F6',\n      stroke: '#EB2F96',\n      lineWidth: 1.5,\n      iconText: 'A', // 图标文字内容\n      iconFill: '#C41D7F', // 深粉色图标\n      iconFontSize: 16,\n      iconFontWeight: 'bold',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 2. 图片图标\n\n使用图片作为图标，支持各种图片格式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#F6FFED',\n      stroke: '#52C41A',\n      lineWidth: 1.5,\n      iconSrc:\n        'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTEyIDJMMTMuMDkgOC4yNkwyMSA5TDEzLjA5IDE1Ljc4TDEyIDIyTDEwLjkxIDE1Ljc4TDMgOUwxMC45MSA4LjI2TDEyIDJaIiBmaWxsPSIjNTJDNDFBIi8+Cjwvc3ZnPgo=',\n      iconWidth: 20,\n      iconHeight: 20,\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 3. IconFont 图标\n\n使用 IconFont 字体图标，需要先引入相应的字体文件：\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      fill: '#E6F7FF', // 淡蓝色背景\n      stroke: '#1890FF', // 蓝色边框\n      lineWidth: 1.5,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      iconFill: '#1890FF',\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的图标样式配置：\n\n| 属性                    | 描述                                | 类型                                                                        | 默认值           |\n| ----------------------- | ----------------------------------- | --------------------------------------------------------------------------- | ---------------- |\n| icon                    | 是否显示节点图标                    | boolean                                                                     | true             |\n| iconFill                | 节点图标文字颜色                    | string                                                                      | -                |\n| iconFontFamily          | 节点图标字体族                      | string                                                                      | -                |\n| iconFontSize            | 节点图标字体大小                    | number                                                                      | 16               |\n| iconFontStyle           | 节点图标字体样式                    | `normal` \\| `italic` \\| `oblique`                                           | `normal`         |\n| iconFontVariant         | 节点图标字体变种                    | `normal` \\| `small-caps` \\| string                                          | `normal`         |\n| iconFontWeight          | 节点图标字体粗细                    | number \\| string                                                            | `normal`         |\n| iconHeight              | 节点图标高度                        | number                                                                      | 主图形高度的一半 |\n| iconLetterSpacing       | 节点图标文本字间距                  | number \\| string                                                            | -                |\n| iconLineHeight          | 节点图标文本行高                    | number \\| string                                                            | -                |\n| iconMaxLines            | 节点图标文本最大行数                | number                                                                      | 1                |\n| iconRadius              | 节点图标圆角半径                    | number                                                                      | 0                |\n| iconSrc                 | 节点图片来源。其优先级高于 iconText | string \\| ((datum) => string)                                                | -                |\n| iconText                | 节点图标文字                        | string \\| ((datum) => string)                                               | -                |\n| iconTextAlign           | 节点图标文本水平对齐方式            | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               | `left`           |\n| iconTextBaseline        | 节点图标文本基线                    | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom` | `alphabetic`     |\n| iconTextDecorationColor | 节点图标文本装饰线颜色              | string                                                                      | -                |\n| iconTextDecorationLine  | 节点图标文本装饰线                  | string                                                                      | -                |\n| iconTextDecorationStyle | 节点图标文本装饰线样式              | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       | `solid`          |\n| iconTextOverflow        | 节点图标文本溢出处理方式            | `clip` \\| `ellipsis` \\| string                                              | `clip`           |\n| iconWidth               | 节点图标宽度                        | number                                                                      | 主图形宽度的一半 |\n| iconWordWrap            | 节点图标文本是否自动换行            | boolean                                                                     | -                |\n\n### 徽标样式\n\n徽标是节点上显示的小标记，通常用于展示状态、数量或其他辅助信息。支持多个徽标同时显示，并可自定义位置。\n\n#### 单个徽标\n\n为节点添加一个简单的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        { text: 'NEW' }, // 默认显示在上方\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 多个徽标\n\n为节点添加多个不同位置的徽标：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badge: true, // 是否显示徽标\n      badges: [\n        { text: 'A', placement: 'right-top' },\n        { text: 'Important', placement: 'right' },\n        { text: 'Notice', placement: 'right-bottom' },\n      ],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'], // 徽标的背景色板\n      badgeFontSize: 7, // 徽标字体大小\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义徽标样式\n\n完全自定义徽标的外观：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      badges: [\n        {\n          text: '99+',\n          placement: 'right-top',\n          backgroundFill: '#FF4D4F', // 红色背景\n          fill: '#fff', // 白色文字\n          fontSize: 10,\n          padding: [2, 6],\n          backgroundRadius: 8,\n        },\n      ],\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的徽标样式配置：\n\n| 属性         | 描述               | 类型                                  | 默认值                            |\n| ------------ | ------------------ | ------------------------------------- | --------------------------------- |\n| badge        | 节点是否显示徽标   | boolean                               | true                              |\n| badgePalette | 节点徽标的背景色板 | string[]                              | [`#7E92B5`, `#F4664A`, `#FFBE3A`] |\n| badges       | 节点徽标设置       | [BadgeStyleProps](#badgestyleprops)[] | -                                 |\n\n#### BadgeStyleProps\n\n| 属性                     | 描述                                                                                                                                                                                                                              | 类型                                                                                                                                                                   | 默认值       |\n| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| background               | 节点徽标是否显示背景                                                                                                                                                                                                              | boolean                                                                                                                                                                | true         |\n| backgroundCursor         | 节点徽标背景鼠标移入样式，[配置项](#cursor)                                                                                                                                                                                       | string                                                                                                                                                                 | `default`    |\n| backgroundFill           | 节点徽标背景填充色。若不指定，优先考虑 badgePalette 按顺序分配                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| backgroundFillOpacity    | 节点徽标背景填充透明度                                                                                                                                                                                                            | number                                                                                                                                                                 | 1            |\n| backgroundFilter         | 节点徽标背景滤镜                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| backgroundHeight         | 节点徽标背景高度                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | -            |\n| backgroundLineDash       | 节点徽标背景虚线配置                                                                                                                                                                                                              | number \\| string \\|(number \\| string )[]                                                                                                                               | -            |\n| backgroundLineDashOffset | 节点徽标背景虚线偏移量                                                                                                                                                                                                            | number                                                                                                                                                                 | -            |\n| backgroundLineWidth      | 节点徽标背景描边线宽                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| backgroundRadius         | 节点徽标背景圆角半径 <br> - number: 统一设置四个圆角半径 <br> - number[]: 分别设置四个圆角半径，会补足缺省的分量 <br> - string: 与 [CSS padding](https://developer.mozilla.org/zh-CN/docs/Web/CSS/padding) 属性类似，使用空格分隔 | number \\| number[] \\| string                                                                                                                                           | 0            |\n| backgroundShadowBlur     | 节点徽标背景阴影模糊程度                                                                                                                                                                                                          | number                                                                                                                                                                 | -            |\n| backgroundShadowColor    | 节点徽标背景阴影颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundShadowOffsetX  | 节点徽标背景阴影 X 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundShadowOffsetY  | 节点徽标背景阴影 Y 方向偏移                                                                                                                                                                                                       | number                                                                                                                                                                 | -            |\n| backgroundStroke         | 节点徽标背景描边颜色                                                                                                                                                                                                              | string                                                                                                                                                                 | -            |\n| backgroundStrokeOpacity  | 节点徽标背景描边透明度                                                                                                                                                                                                            | number \\| string                                                                                                                                                       | 1            |\n| backgroundVisibility     | 节点徽标背景是否可见                                                                                                                                                                                                              | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| backgroundZIndex         | 节点徽标背景渲染层级                                                                                                                                                                                                              | number                                                                                                                                                                 | -            |\n| fill                     | 节点徽标文字颜色                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| fontFamily               | 节点徽标字体族                                                                                                                                                                                                                    | string                                                                                                                                                                 | -            |\n| fontSize                 | 节点徽标字体大小                                                                                                                                                                                                                  | number                                                                                                                                                                 | 8            |\n| fontStyle                | 节点徽标字体样式                                                                                                                                                                                                                  | `normal` \\| `italic` \\| `oblique`                                                                                                                                      | `normal`     |\n| fontVariant              | 节点徽标字体变种                                                                                                                                                                                                                  | `normal` \\| `small-caps` \\| string                                                                                                                                     | `normal`     |\n| fontWeight               | 节点徽标字体粗细                                                                                                                                                                                                                  | number \\| string                                                                                                                                                       | `normal`     |\n| lineHeight               | 节点徽标行高                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| lineWidth                | 节点徽标行宽                                                                                                                                                                                                                      | string \\| number                                                                                                                                                       | -            |\n| maxLines                 | 节点徽标文本最大行数                                                                                                                                                                                                              | number                                                                                                                                                                 | 1            |\n| offsetX                  | 节点徽标在 x 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| offsetY                  | 节点徽标在 y 轴方向上的偏移量                                                                                                                                                                                                     | number                                                                                                                                                                 | 0            |\n| padding                  | 节点徽标内边距                                                                                                                                                                                                                    | number \\| number[]                                                                                                                                                     | 0            |\n| placement                | 节点徽标相对于节点主图形的位置。若不指定，默认从右上角顺时针依次排放                                                                                                                                                              | `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` | -            |\n| text                     | 节点徽标文字内容                                                                                                                                                                                                                  | string                                                                                                                                                                 | -            |\n| textAlign                | 节点徽标文本水平对齐方式                                                                                                                                                                                                          | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`                                                                                                          | `left`       |\n| textBaseline             | 节点徽标文本基线                                                                                                                                                                                                                  | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom`                                                                                            | `alphabetic` |\n| textDecorationColor      | 节点徽标文本装饰线颜色                                                                                                                                                                                                            | string                                                                                                                                                                 | -            |\n| textDecorationLine       | 节点徽标文本装饰线                                                                                                                                                                                                                | string                                                                                                                                                                 | -            |\n| textDecorationStyle      | 节点徽标文本装饰线样式                                                                                                                                                                                                            | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                                                                                                                  | `solid`      |\n| textOverflow             | 节点徽标文本溢出处理方式                                                                                                                                                                                                          | `clip` \\| `ellipsis` \\| string                                                                                                                                         | `clip`       |\n| visibility               | 节点徽标是否可见                                                                                                                                                                                                                  | `visible` \\| `hidden`                                                                                                                                                  | -            |\n| wordWrap                 | 节点徽标文本是否自动换行                                                                                                                                                                                                          | boolean                                                                                                                                                                | -            |\n| zIndex                   | 节点徽标渲染层级                                                                                                                                                                                                                  | number                                                                                                                                                                 | 3            |\n\n### 连接桩样式\n\n连接桩是节点上的连接点，用于连接边。支持在节点的不同位置添加多个连接桩，并可自定义样式。\n\n#### 基础连接桩\n\n为节点添加四个基本方向的连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      port: true,\n      ports: [\n        { key: 'top', placement: 'top', fill: '#7E92B5' },\n        { key: 'right', placement: 'right', fill: '#F4664A' },\n        { key: 'bottom', placement: 'bottom', fill: '#FFBE3A' },\n        { key: 'left', placement: 'left', fill: '#D580FF' },\n      ],\n      portR: 3,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 自定义位置连接桩\n\n使用百分比或绝对坐标精确定位连接桩：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        { key: 'custom1', placement: [0.2, 0] }, // 相对位置：左上角20%处\n        { key: 'custom2', placement: [0.8, 0] }, // 相对位置：右上角80%处\n        { key: 'custom3', placement: [1, 0.5] }, // 相对位置：右边中央\n      ],\n      portR: 4,\n      portLineWidth: 1,\n      portStroke: '#fff',\n    },\n  },\n});\n\ngraph.render();\n```\n\n#### 差异化连接桩样式\n\n为不同的连接桩设置不同的样式：\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: { nodes: [{ id: 'node1' }] },\n  node: {\n    style: {\n      ports: [\n        {\n          key: 'input',\n          placement: 'left',\n          fill: '#52C41A', // 绿色输入桩\n          r: 4,\n        },\n        {\n          key: 'output',\n          placement: 'right',\n          fill: '#FF4D4F', // 红色输出桩\n          r: 4,\n        },\n      ],\n      portStroke: '#fff', // 统一的描边颜色\n      portLineWidth: 2,\n    },\n  },\n});\n\ngraph.render();\n```\n\n以下为完整的连接桩样式配置：\n\n| 属性  | 描述                                 | 类型                                | 默认值 | 必选 |\n| ----- | ------------------------------------ | ----------------------------------- | ------ | ---- |\n| port  | 节点是否显示连接桩                   | boolean                             | true   |      |\n| ports | 节点连接桩配置项，支持配置多个连接桩 | [PortStyleProps](#portstyleprops)[] |        |      |\n\n#### PortStyleProps\n\n| 属性              | 描述                                                                                                                                                                               | 类型                                                                                                                                                                                                   | 默认值    | 必选 |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ---- |\n| key               | 节点连接桩的键值，默认为节点连接桩的索引                                                                                                                                           | string                                                                                                                                                                                                 | -         |      |\n| placement         | 节点连接桩相对于节点主图形的位置                                                                                                                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| [number, number] | -         | ✓    |\n| r                 | 节点连接桩半径 <br> - 如果设置为 undefined，则连接桩被视为一个点，不在画布上显示但存在，边会优先连接到最近的连接桩 <br> - 如果设置为数字，则连接桩被视为一个圆，圆的半径由此处指定 | number                                                                                                                                                                                                 | -         |      |\n| linkToCenter      | 边是否连接到节点连接桩的中心 <br> - 若为 true，则边连接到节点连接桩的中心 <br> - 若为 false，则边连接到节点连接桩的边缘                                                            | boolean                                                                                                                                                                                                | false     |      |\n| cursor            | 节点连接桩鼠标移入样式，[配置项](#cursor)                                                                                                                                          | string                                                                                                                                                                                                 | `default` |      |\n| fill              | 节点连接桩填充颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| fillOpacity       | 节点连接桩填充透明度                                                                                                                                                               | number                                                                                                                                                                                                 | 1         |      |\n| isBillboard       | 节点连接桩是否为Billboard 效果                                                                                                                                                     | boolean                                                                                                                                                                                                | -         |      |\n| isSizeAttenuation | 节点连接桩是否启用大小衰减                                                                                                                                                         | boolean                                                                                                                                                                                                | -         |      |\n| lineDash          | 节点连接桩描边虚线配置                                                                                                                                                             | number \\| string \\|(number \\| string )[]                                                                                                                                                               | -         |      |\n| lineDashOffset    | 节点连接桩描边虚线偏移量                                                                                                                                                           | number                                                                                                                                                                                                 | -         |      |\n| lineWidth         | 节点连接桩描边线宽                                                                                                                                                                 | number                                                                                                                                                                                                 | -         |      |\n| shadowBlur        | 节点连接桩阴影模糊程度                                                                                                                                                             | number                                                                                                                                                                                                 | -         |      |\n| shadowColor       | 节点连接桩阴影颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| shadowOffsetX     | 节点连接桩阴影 X 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| shadowOffsetY     | 节点连接桩阴影 Y 方向偏移                                                                                                                                                          | number                                                                                                                                                                                                 | -         |      |\n| stroke            | 节点连接桩描边颜色                                                                                                                                                                 | string                                                                                                                                                                                                 | -         |      |\n| strokeOpacity     | 节点连接桩描边透明度                                                                                                                                                               | number \\| string                                                                                                                                                                                       | 1         |      |\n| visibility        | 节点连接桩是否可见                                                                                                                                                                 | `visible` \\| `hidden`                                                                                                                                                                                  | `visible` |      |\n| zIndex            | 节点连接桩渲染层级                                                                                                                                                                 | number                                                                                                                                                                                                 | 2         |      |\n\n## State\n\n在一些交互行为中，比如点击选中一个节点或鼠标悬停激活一个边，仅仅是在该元素做了某些状态的标识。为了将这些状态反应到终端用户所见的视觉空间中，我们需要为不同的状态设置不同的图元素样式，以响应该图元素状态的变化。\n\nG6 提供了几种内置的状态，包括选中（selected）、高亮（highlight）、激活（active）、不活跃（inactive）和禁用（disabled）。此外，它还支持自定义状态，以满足更特定的需求。对于每个状态，开发者可以定义一套样式规则，这些规则会覆盖元素的默认样式。\n\n<img width=\"520\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*t2qvRp92itkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n数据结构如下：\n\n```typescript\ntype NodeState = {\n  [state: string]: NodeStyle;\n};\n```\n\n例如，当节点处于 `focus` 状态时，可以为其添加一个宽度为 3 且颜色为橙色的描边。\n\n```js {4-7}\nconst graph = new Graph({\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3, // 描边宽度\n        stroke: 'orange', // 描边颜色\n      },\n    },\n  },\n});\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 200,\n  height: 100,\n  autoFit: 'center',\n  data: {\n    nodes: [{ id: 'node1', states: ['focus'] }],\n  },\n  node: {\n    state: {\n      focus: {\n        lineWidth: 3,\n        stroke: 'orange',\n      },\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Animation\n\n定义节点的动画效果，支持下列两种配置方式：\n\n1. 关闭节点全部动画\n\n```json\n{\n  \"node\": {\n    \"animation\": false\n  }\n}\n```\n\n2. 配置阶段动画\n\n阶段动画是指节点在进入画布、更新、离开画布时的动画效果。目前支持的阶段包括：\n\n- `enter`: 节点进入画布时的动画\n- `update`: 节点更新时的动画\n- `exit`: 节点离开画布时的动画\n- `show`: 节点从隐藏状态显示时的动画\n- `hide`: 节点隐藏时的动画\n- `collapse`: 节点收起时的动画\n- `expand`: 节点展开时的动画\n\n你可以参考 [动画范式](/manual/animation/animation#动画范式) 使用动画语法来配置节点，如：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"update\": [\n        {\n          \"fields\": [\"x\", \"y\"], // 更新时只对 x 和 y 属性进行动画\n          \"duration\": 1000, // 动画持续时间\n          \"easing\": \"linear\" // 缓动函数\n        }\n      ],\n  }\n}\n```\n\n也可以使用内置的动画效果：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": \"fade\", // 使用渐变动画\n      \"update\": \"translate\", // 使用平移动画\n      \"exit\": \"fade\" // 使用渐变动画\n    }\n  }\n}\n```\n\n你可以传入 false 来关闭特定阶段的动画：\n\n```json\n{\n  \"node\": {\n    \"animation\": {\n      \"enter\": false // 关闭节点入场动画\n    }\n  }\n}\n```\n\n## Palette\n\n定义节点的色板，即预定义节点颜色池，并根据规则进行分配，将颜色映射到 `fill` 属性。\n\n> 有关色板的定义，请参考 [色板](/manual/theme/palette)。\n\n| 属性   | 描述                                                                | 类型                          | 默认值  |\n| ------ | ------------------------------------------------------------------- | ----------------------------- | ------- |\n| color  | 色板颜色。如果色板注册过，可以直接指定其注册名，也接受一个颜色数组  | string \\| string[]            | -       |\n| field  | 指定元素数据中的分组字段。若不指定，默认取 id 作为分组字段          | string \\| ((datum) => string) | `id`    |\n| invert | 是否反转色板                                                        | boolean                       | false   |\n| type   | 指定当前色板类型。<br> - `group`: 离散色板 <br> - `value`: 连续色板 | `group` \\| `value`            | `group` |\n\n如将一组数据按 `category` 字段分配节点颜色，使得同类别的节点颜色相同：\n\n```json\n{\n  \"node\": {\n    \"palette\": {\n      \"type\": \"group\",\n      \"field\": \"category\",\n      \"color\": [\"#1783FF\", \"#F08F56\", \"#D580FF\", \"#00C9C9\", \"#7863FF\"]\n    }\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#1783FF', '#F08F56', '#D580FF', '#00C9C9', '#7863FF'],\n    },\n  },\n});\n\ngraph.render();\n```\n\n也可以使用默认配置：\n\n```json\n{\n  \"node\": {\n    \"palette\": \"tableau\" // tableau 为色板名，默认根据 ID 分配颜色\n  }\n}\n```\n\n效果如下图所示：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 100,\n  data: {\n    nodes: new Array(10)\n      .fill(0)\n      .map((_, i) => ({ id: `node-${i}`, data: { category: ['A', 'B', 'C', 'D', 'E'][i % 5] } })),\n  },\n  layout: { type: 'grid', cols: 10 },\n  node: {\n    palette: 'tableau',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Circle.en.md) -->\n---\ntitle: Circle Node\norder: 2\n---\n\n## Overview\n\nA circle is a symmetrical geometric shape with a uniform radius.\n\nApplicable scenarios:\n\n- Used to represent the size or weight of a node (controlled by radius).\n- Suitable for representing non-directional relationships, such as user nodes in social networks.\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node))\n\n## Example\n\n### Built-in Circle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Circle.zh.md) -->\n---\ntitle: 圆形节点 Circle\norder: 2\n---\n\n## 概述\n\n圆形是一个对称的几何形状，具有均匀的半径。\n\n适用场景：\n\n- 用于表示节点的大小或权重（通过半径控制）。\n- 适合表示无方向性的关系，如社交网络中的用户节点。\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/circle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见[BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'circle',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/custom-node.en.md) -->\n---\ntitle: Custom Node\norder: 12\n---\n\nG6 provides a series of [built-in nodes](/en/manual/element/node/base-node), including [circle (Circle Node)](/en/manual/element/node/circle), [diamond (Diamond Node)](/en/manual/element/node/diamond), [donut (Donut Node)](/en/manual/element/node/donut), [ellipse (Ellipse Node)](/en/manual/element/node/ellipse), [hexagon (Hexagon Node)](/en/manual/element/node/hexagon), [html (HTML Node)](/en/manual/element/node/html), [image (Image Node)](/en/manual/element/node/image), [rect (Rectangle Node)](/en/manual/element/node/rect), [star (Star Node)](/en/manual/element/node/star), and [triangle (Triangle Node)](/en/manual/element/node/triangle). These built-in nodes can meet most basic scenario requirements.\n\nHowever, in actual projects, you may encounter needs that these basic nodes cannot satisfy. In such cases, you need to create custom nodes. Don't worry, this is simpler than you might think!\n\n## Ways to Create Custom Nodes <Badge type=\"warning\">Choose the Right Approach</Badge>\n\nThere are mainly two approaches to creating custom nodes:\n\n### 1. Inherit from Existing Node Types <Badge type=\"success\">Recommended</Badge>\n\nThis is the most commonly used approach, where you can choose to inherit from one of the following types:\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - The most basic node class, providing core node functionality\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - Circle node\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - Rectangle node\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - Ellipse node\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - Diamond node\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - Triangle node\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - Star node\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - Image node\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - Donut node\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - Hexagon node\n\n**Why choose this approach?**\n\n- 📌 **Less Code**: Reuse properties and methods of existing nodes, only focus on new features\n- 📌 **Rapid Development**: Suitable for most project needs, quickly achieve business goals\n- 📌 **Easy Maintenance**: Clear code structure with well-defined inheritance relationships\n\n:::tip{title=Get Started Now}\nIf you choose to inherit from existing node types (recommended), you can jump directly to [Create Your First Custom Node in Three Steps](#create-your-first-custom-node-in-three-steps) to start practicing. Most users will choose this approach!\n:::\n\n### 2. Build from Scratch Based on G Graphics System <Badge>Advanced Usage</Badge>\n\nIf existing node types don't meet your requirements, you can create nodes from scratch based on G's underlying graphics system.\n\n**Why choose this approach?**\n\n- 📌 **Maximum Freedom**: Complete control over every detail of the node, achieving any complex effects\n- 📌 **Special Requirements**: Highly customized scenarios that existing node types cannot satisfy\n- 📌 **Performance Optimization**: Performance optimization for specific scenarios\n\n:::warning{title=Important Notes}\nCustom nodes built from scratch require handling all details yourself, including graphics rendering, event response, state changes, etc., with higher development difficulty. You can refer directly to the [source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) for implementation.\n:::\n\n## Create Your First Custom Node in Three Steps\n\nLet's start with a simple example - creating a **rectangle node with main and subtitle**:\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// Step 1: Create custom node class\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// Step 2: Register custom node\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// Step 3: Use custom node\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Step 1: Write Custom Node Class\n\nInherit from G6's `Rect` (rectangle node) and add a subtitle:\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// Create custom node, inheriting from Rect\nclass DualLabelNode extends Rect {\n  // Subtitle style\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // Place below the main title\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // Draw subtitle\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // Render method\n  render(attributes = this.parsedAttributes, container) {\n    // 1. Render basic rectangle and main title\n    super.render(attributes, container);\n\n    // 2. Add subtitle\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### Step 2: Register Custom Node\n\nUse the `register` method to register the node type so that G6 can recognize your custom node:\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `dual-label-node` is the name we give to this custom node, which will be used in configuration later\n- Class definition: `DualLabelNode` is the node class we just created\n\n### Step 3: Apply Custom Node\n\nUse the custom node in graph configuration:\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: 'Node A', // Main title\n          subtitle: 'Your First Custom Node', // Subtitle\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // Main title style\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // Subtitle\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 Congratulations! You have created your first custom node. It looks simple, but this process contains the core concept of custom nodes: **inherit from a basic node type**, then **override the `render` method** to add custom content.\n\n## Understanding Data Flow: How to Access Data in Custom Nodes\n\nBefore creating complex custom nodes, understanding how data flows into custom nodes is very important. G6 provides multiple ways to access data for custom nodes:\n\n### Method 1: Through `attributes` Parameter (Recommended)\n\nThe first parameter `attributes` of the `render` method contains processed style attributes, including data-driven styles:\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes contains all style attributes, including data-driven styles\n    console.log('All properties of current node:', attributes);\n\n    // If customData: (d) => d.data.someValue is defined in style\n    // Then you can access it through attributes.customData\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Method 2: Through `this.context.graph` to Access Raw Data\n\nWhen you need to access the node's raw data, you can get it through the graph instance:\n\n```js\nclass CustomNode extends Rect {\n  // Convenient data access method\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Get complete node data\n    const nodeData = this.nodeData;\n    console.log('Complete node data:', nodeData);\n\n    // Get business data from data field\n    const businessData = this.data;\n    console.log('Business data:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### Complete Data Flow Process\n\nLet's understand how data flows from graph data to custom nodes through a specific example:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // Method 2: Get raw data through graph\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // Method 1: Get processed styles from attributes\n    console.log('Get from attributes:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // Method 2: Get from raw data\n    console.log('Get from raw data:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Use data to render custom content\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // This is the node's business data\n        data: {\n          name: 'Zhang San',\n          role: 'Developer',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // Map data from data field to style attributes\n      iconUrl: (d) => d.data.icon, // This becomes attributes.iconUrl\n      userName: (d) => d.data.name, // This becomes attributes.userName\n      // Main title uses role information\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=Data Flow Summary}\n\n1. **Graph Data Definition**: Define business data in `data.nodes[].data`\n2. **Style Mapping**: Use functions in `node.style` to map data to style attributes\n3. **Node Access**: Access data in custom nodes through `attributes` or `this.context.graph`\n4. **Rendering Usage**: Use the obtained data to render custom graphics\n   :::\n\n## From Simple to Complex: Gradually Building Feature-Rich Nodes\n\nLet's gradually increase the complexity and functionality of nodes through practical examples.\n\n### Example 1: User Card Node with Icon and Badge\n\nThis example shows how to create a user card node containing avatar, name, and status badge:\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // Avatar style\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // Circular avatar\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // Status badge style\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // Username style\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // Role label style\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // Render basic rectangle\n    super.render(attributes, container);\n\n    // Add various components\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: 'Zhang Xiaoming',\n          role: 'Frontend Engineer',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // Data mapping\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 2: Node with Clickable Action Button\n\nAdd a blue button to the node that triggers events (prints logs or executes callbacks) when clicked.\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // Mouse pointer becomes hand\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // Add click event to button\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // Prevent event bubbling to avoid triggering node click event\n        e.stopPropagation();\n\n        // Execute business logic\n        console.log('Button clicked on node:', this.id);\n\n        // If there's a callback function in data, call it\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // Mark as bound to avoid duplicate binding\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // Add a button\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // Specify using our custom node\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Example 3: Node Responding to State Changes (Click to Change Color)\n\nCommon interactions require nodes and edges to provide feedback through style changes, such as when the mouse moves over a node, clicking to select nodes/edges, or activating interactions on edges through interaction. All these require changing the styles of nodes and edges. There are two ways to achieve this effect:\n\n1. Get the current state from `data.states` and handle state changes in the custom node class;\n2. Separate interaction state from raw data and node drawing logic, only update the node.\n\nWe recommend users use the second approach to implement node state adjustments, which can be achieved through the following steps:\n\n1. Implement custom node;\n2. Configure node state styles in graph configuration;\n3. Set node state through the `graph.setElementState()` method.\n\nBased on rect, extend a hole shape with default white fill color that turns orange when clicked. The sample code to achieve this effect is as follows:\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. Define node class\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. Register node\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. Create graph instance\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // Mouse selected state\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. Add node interaction\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/custom-node.zh.md) -->\n---\ntitle: 自定义节点\norder: 12\n---\n\nG6 提供了一系列 [内置节点](/manual/element/node/base-node)，包含 [circle（圆形节点）](/manual/element/node/circle)、[diamond（菱形节点）](/manual/element/node/diamond)、[donut（甜甜圈节点）](/manual/element/node/donut)、[ellipse（椭圆节点）](/manual/element/node/ellipse)、[hexagon（六边形节点）](/manual/element/node/hexagon)、[html（HTML节点）](/manual/element/node/html)、[image（图片节点）](/manual/element/node/image)、[rect（矩形节点）](/manual/element/node/rect)、[star（星形节点）](/manual/element/node/star) 和 [triangle（三角形节点）](/manual/element/node/triangle)。这些内置节点能够满足大部分基础场景需求。\n\n但在实际项目中，你可能会遇到这些基础节点无法满足的需求。这时，你需要创建自定义节点。别担心，这比你想象的要简单！\n\n## 自定义节点的方式 <Badge type=\"warning\">选择合适的方式</Badge>\n\n创建自定义节点的方式主要有两种途径：\n\n### 1. 继承现有节点类型 <Badge type=\"success\">推荐</Badge>\n\n这是最常用的方式，你可以选择继承以下类型之一：\n\n- [`BaseNode`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) - 最基础的节点类，提供节点的核心功能\n- [`Circle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/circle.ts) - 圆形节点\n- [`Rect`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/rect.ts) - 矩形节点\n- [`Ellipse`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/ellipse.ts) - 椭圆节点\n- [`Diamond`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/diamond.ts) - 菱形节点\n- [`Triangle`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/triangle.ts) - 三角形节点\n- [`Star`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/star.ts) - 星形节点\n- [`Image`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/image.ts) - 图片节点\n- [`Donut`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/donut.ts) - 甜甜圈节点\n- [`Hexagon`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/hexagon.ts) - 六边形节点\n\n**为什么选择这种方式？**\n\n- 📌 **代码量少**：复用现有节点的属性和方法，只需专注于新增功能\n- 📌 **开发迅速**：适合大多数项目需求，快速实现业务目标\n- 📌 **易于维护**：代码结构清晰，继承关系明确\n\n:::tip{title=立即开始}\n如果你选择继承现有节点类型（推荐），可以直接跳到 [三步创建你的第一个自定义节点](#三步创建你的第一个自定义节点) 开始实践。大部分用户都会选择这种方式！\n:::\n\n### 2. 基于 G 图形系统从零开发 <Badge>高级用法</Badge>\n\n如果现有节点类型都不满足需求，你可以基于 G 的底层图形系统从零创建节点。\n\n**为什么选择这种方式？**\n\n- 📌 **最大自由度**：完全控制节点的每个细节，实现任意复杂效果\n- 📌 **特殊需求**：现有节点类型无法满足的高度定制场景\n- 📌 **性能优化**：针对特定场景的性能优化\n\n:::warning{title=注意事项}\n从零开发的自定义节点需要自行处理所有细节，包括图形绘制、事件响应、状态变化等，开发难度较大。这里可以直接参考 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/nodes/base-node.ts) 进行实现。\n:::\n\n## 三步创建你的第一个自定义节点\n\n让我们从一个简单的例子开始 - 创建一个 **带有主副标题的矩形节点**：\n\n```js | ob { pin:false, inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\n// 第一步：创建自定义节点类\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n\n// 第二步：注册自定义节点\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n\n// 第三步：使用自定义节点\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 第一步：编写自定义节点类\n\n继承 G6 的 `Rect`（矩形节点），并添加一个副标题：\n\n```js\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 创建自定义节点，继承自 Rect\nclass DualLabelNode extends Rect {\n  // 副标题样式\n  getSubtitleStyle(attributes) {\n    return {\n      x: 0,\n      y: 45, // 放在主标题下方\n      text: attributes.subtitle || '',\n      fontSize: 12,\n      fill: '#666',\n      textAlign: 'center',\n      textBaseline: 'middle',\n    };\n  }\n\n  // 绘制副标题\n  drawSubtitleShape(attributes, container) {\n    const subtitleStyle = this.getSubtitleStyle(attributes);\n    this.upsert('subtitle', 'text', subtitleStyle, container);\n  }\n\n  // 渲染方法\n  render(attributes = this.parsedAttributes, container) {\n    // 1. 渲染基础矩形和主标题\n    super.render(attributes, container);\n\n    // 2. 添加副标题\n    this.drawSubtitleShape(attributes, container);\n  }\n}\n```\n\n### 第二步：注册自定义节点\n\n使用 `register` 方法注册节点类型，这样 G6 才能识别你的自定义节点：\n\n```js\nregister(ExtensionCategory.NODE, 'dual-label-node', DualLabelNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`dual-label-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：`DualLabelNode` 是我们刚刚创建的节点类\n\n### 第三步：应用自定义节点\n\n在图配置中使用自定义节点：\n\n```js\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: {\n          title: '节点 A', // 主标题\n          subtitle: '你的第一个自定义节点', // 副标题\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'dual-label-node',\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 8,\n      // 主标题样式\n      labelText: (d) => d.data.title,\n      labelFill: '#222',\n      labelFontSize: 14,\n      labelFontWeight: 500,\n      // 副标题\n      subtitle: (d) => d.data.subtitle,\n    },\n  },\n});\n\ngraph.render();\n```\n\n🎉 恭喜！你已经创建了第一个自定义节点。它看起来很简单，但这个过程包含了自定义节点的核心思想：**继承一个基础节点类型**，然后 **重写 `render` 方法** 来添加自定义内容。\n\n## 理解数据流：如何在自定义节点中获取数据\n\n在创建复杂的自定义节点之前，理解数据如何流入自定义节点是非常重要的。G6 为自定义节点提供了多种数据获取方式：\n\n### 方式一：通过 `attributes` 参数（推荐）\n\n`render` 方法的第一个参数 `attributes` 包含了经过处理的样式属性，包括数据驱动的样式：\n\n```js\nclass CustomNode extends Rect {\n  render(attributes, container) {\n    // attributes 包含了所有样式属性，包括数据驱动的样式\n    console.log('当前节点的所有属性:', attributes);\n\n    // 如果在 style 中定义了 customData: (d) => d.data.someValue\n    // 那么可以通过 attributes.customData 获取\n    const customValue = attributes.customData;\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 方式二：通过 `this.context.graph` 获取原始数据\n\n当你需要访问节点的原始数据时，可以通过图实例获取：\n\n```js\nclass CustomNode extends Rect {\n  // 便捷的数据获取方法\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 获取节点的完整数据\n    const nodeData = this.nodeData;\n    console.log('节点完整数据:', nodeData);\n\n    // 获取 data 字段中的业务数据\n    const businessData = this.data;\n    console.log('业务数据:', businessData);\n\n    super.render(attributes, container);\n  }\n}\n```\n\n### 数据传递的完整流程\n\n让我们通过一个具体例子来理解数据是如何从图数据传递到自定义节点的：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass DataFlowNode extends Rect {\n  // 方式二：通过 graph 获取原始数据\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  render(attributes, container) {\n    // 方式一：从 attributes 获取处理后的样式\n    console.log('从 attributes 获取:', {\n      iconUrl: attributes.iconUrl,\n      userName: attributes.userName,\n    });\n\n    // 方式二：从原始数据获取\n    console.log('从原始数据获取:', {\n      icon: this.data.icon,\n      name: this.data.name,\n      role: this.data.role,\n    });\n\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 使用数据渲染自定义内容\n    if (attributes.iconUrl) {\n      this.upsert(\n        'icon',\n        'image',\n        {\n          x: -25,\n          y: -12,\n          width: 20,\n          height: 20,\n          src: attributes.iconUrl,\n        },\n        container,\n      );\n    }\n\n    if (attributes.userName) {\n      this.upsert(\n        'username',\n        'text',\n        {\n          x: 10,\n          y: 0,\n          text: attributes.userName,\n          fontSize: 10,\n          fill: '#666',\n          textAlign: 'center',\n          textBaseline: 'middle',\n        },\n        container,\n      );\n    }\n  }\n}\n\nregister(ExtensionCategory.NODE, 'data-flow-node', DataFlowNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        // 这里是节点的业务数据\n        data: {\n          name: '张三',\n          role: '开发者',\n          icon: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Felix',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'data-flow-node',\n    style: {\n      size: [80, 40],\n      fill: '#f0f9ff',\n      stroke: '#0ea5e9',\n      lineWidth: 1,\n      radius: 4,\n      // 将 data 中的数据映射到样式属性\n      iconUrl: (d) => d.data.icon, // 这会变成 attributes.iconUrl\n      userName: (d) => d.data.name, // 这会变成 attributes.userName\n      // 主标题使用角色信息\n      labelText: (d) => d.data.role,\n      labelFontSize: 12,\n      labelFill: '#0369a1',\n    },\n  },\n});\n\ngraph.render();\n```\n\n:::tip{title=数据流总结}\n\n1. **图数据定义**：在 `data.nodes[].data` 中定义业务数据\n2. **样式映射**：在 `node.style` 中使用函数将数据映射到样式属性\n3. **节点获取**：在自定义节点中通过 `attributes` 或 `this.context.graph` 获取数据\n4. **渲染使用**：使用获取到的数据渲染自定义图形\n   :::\n\n## 从简单到复杂：逐步构建功能丰富的节点\n\n让我们通过实际例子，逐步增加节点的复杂度和功能。\n\n### 示例一：带图标和徽章的用户卡片节点\n\n这个例子展示如何创建一个包含头像、姓名、状态徽章的用户卡片节点：\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass UserCardNode extends Rect {\n  get nodeData() {\n    return this.context.graph.getNodeData(this.id);\n  }\n\n  get data() {\n    return this.nodeData.data || {};\n  }\n\n  // 头像样式\n  getAvatarStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 20,\n      y: -height / 2 + 15,\n      width: 30,\n      height: 30,\n      src: attributes.avatarUrl || '',\n      radius: 15, // 圆形头像\n    };\n  }\n\n  drawAvatarShape(attributes, container) {\n    if (!attributes.avatarUrl) return;\n\n    const avatarStyle = this.getAvatarStyle(attributes);\n    this.upsert('avatar', 'image', avatarStyle, container);\n  }\n\n  // 状态徽章样式\n  getBadgeStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    const status = this.data.status || 'offline';\n    const colorMap = {\n      online: '#52c41a',\n      busy: '#faad14',\n      offline: '#8c8c8c',\n    };\n\n    return {\n      x: width / 2 - 8,\n      y: -height / 2 + 8,\n      r: 4,\n      fill: colorMap[status],\n      stroke: '#fff',\n      lineWidth: 2,\n    };\n  }\n\n  drawBadgeShape(attributes, container) {\n    const badgeStyle = this.getBadgeStyle(attributes);\n    this.upsert('badge', 'circle', badgeStyle, container);\n  }\n\n  // 用户名样式\n  getUsernameStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 20,\n      text: attributes.username || '',\n      fontSize: 14,\n      fill: '#262626',\n      fontWeight: 'bold',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawUsernameShape(attributes, container) {\n    if (!attributes.username) return;\n\n    const usernameStyle = this.getUsernameStyle(attributes);\n    this.upsert('username', 'text', usernameStyle, container);\n  }\n\n  // 角色标签样式\n  getRoleStyle(attributes) {\n    const [width, height] = this.getSize(attributes);\n    return {\n      x: -width / 2 + 55,\n      y: -height / 2 + 35,\n      text: attributes.userRole || '',\n      fontSize: 11,\n      fill: '#8c8c8c',\n      textAlign: 'left',\n      textBaseline: 'middle',\n    };\n  }\n\n  drawRoleShape(attributes, container) {\n    if (!attributes.userRole) return;\n\n    const roleStyle = this.getRoleStyle(attributes);\n    this.upsert('role', 'text', roleStyle, container);\n  }\n\n  render(attributes, container) {\n    // 渲染基础矩形\n    super.render(attributes, container);\n\n    // 添加各个组件\n    this.drawAvatarShape(attributes, container);\n    this.drawBadgeShape(attributes, container);\n    this.drawUsernameShape(attributes, container);\n    this.drawRoleShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'user-card-node', UserCardNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'user1',\n        style: { x: 100, y: 100 },\n        data: {\n          name: '张小明',\n          role: '前端工程师',\n          status: 'online',\n          avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Zhang',\n        },\n      },\n    ],\n  },\n  node: {\n    type: 'user-card-node',\n    style: {\n      size: [140, 50],\n      fill: '#ffffff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      radius: 6,\n      // 数据映射\n      avatarUrl: (d) => d.data.avatar,\n      username: (d) => d.data.name,\n      userRole: (d) => d.data.role,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例二：可点击操作按钮的节点\n\n给节点加一个蓝色按钮，点击后触发事件（打印日志或执行回调）。\n\n```js | ob { inject: true }\nimport { Graph, register, Rect, ExtensionCategory } from '@antv/g6';\n\nclass ClickableNode extends Rect {\n  getButtonStyle(attributes) {\n    return {\n      x: 40,\n      y: -10,\n      width: 20,\n      height: 20,\n      radius: 10,\n      fill: '#1890ff',\n      cursor: 'pointer', // 鼠标指针变为手型\n    };\n  }\n\n  drawButtonShape(attributes, container) {\n    const btnStyle = this.getButtonStyle(attributes, container);\n    const btn = this.upsert('button', 'rect', btnStyle, container);\n\n    // 为按钮添加点击事件\n    if (!btn.__clickBound) {\n      btn.addEventListener('click', (e) => {\n        // 阻止事件冒泡，避免触发节点的点击事件\n        e.stopPropagation();\n\n        // 执行业务逻辑\n        console.log('Button clicked on node:', this.id);\n\n        // 如果数据中有回调函数，则调用\n        if (typeof attributes.onButtonClick === 'function') {\n          attributes.onButtonClick(this.id, this.data);\n        }\n      });\n      btn.__clickBound = true; // 标记已绑定事件，避免重复绑定\n    }\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    // 添加一个按钮\n    this.drawButtonShape(attributes, container);\n  }\n}\n\nregister(ExtensionCategory.NODE, 'clickable-node', ClickableNode);\n\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n      },\n    ],\n  },\n  node: {\n    type: 'clickable-node', // 指定使用我们的自定义节点\n    style: {\n      size: [60, 30],\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      radius: 5,\n      onButtonClick: (id, data) => {},\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 示例三：响应状态变化的节点（点击变色）\n\n常见的交互都需要节点和边通过样式变化做出反馈，例如鼠标移动到节点上、点击选中节点/边、通过交互激活边上的交互等，都需要改变节点和边的样式，有两种方式来实现这种效果：\n\n1. 从 `data.states` 获取当前状态，在自定义节点类中处理状态变化；\n2. 将交互状态同原始数据和绘制节点的逻辑分开，仅更新节点。\n\n我们推荐用户使用第二种方式来实现节点的状态调整，可以通过以下方式来实现：\n\n1. 实现自定义节点；\n2. 在图配置项中配置节点状态样式；\n3. 通过 `graph.setElementState()` 方法来设置节点状态。\n\n基于 rect 扩展出一个 hole 图形，默认填充色为白色，当鼠标点击时变成橙色，实现这一效果的示例代码如下：\n\n```js | ob { inject: true }\nimport { Rect, register, Graph, ExtensionCategory } from '@antv/g6';\n\n// 1. 定义节点类\nclass SelectableNode extends Rect {\n  getHoleStyle(attributes) {\n    return {\n      x: 20,\n      y: -10,\n      radius: 10,\n      width: 20,\n      height: 20,\n      fill: attributes.holeFill,\n    };\n  }\n\n  drawHoleShape(attributes, container) {\n    const holeStyle = this.getHoleStyle(attributes, container);\n\n    this.upsert('hole', 'rect', holeStyle, container);\n  }\n\n  render(attributes, container) {\n    super.render(attributes, container);\n\n    this.drawHoleShape(attributes, container);\n  }\n}\n\n// 2. 注册节点\nregister(ExtensionCategory.NODE, 'selectable-node', SelectableNode, true);\n\n// 3. 创建图实例\nconst graph = new Graph({\n  container: 'container',\n  height: 200,\n  data: {\n    nodes: [{ id: 'node-1', style: { x: 100, y: 100 } }],\n  },\n  node: {\n    type: 'selectable-node',\n    style: {\n      size: [120, 60],\n      radius: 6,\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n      holeFill: '#fff',\n    },\n    state: {\n      // 鼠标选中状态\n      selected: {\n        holeFill: 'orange',\n      },\n    },\n  },\n});\n\n// 4. 添加节点交互\ngraph.on('node:click', (evt) => {\n  const nodeId = evt.target.id;\n\n  graph.setElementState(nodeId, ['selected']);\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Diamond.en.md) -->\n---\ntitle: Diamond Node\norder: 3\n---\n\n## Overview\n\nA diamond is a geometric shape with four equal sides and diagonal symmetry.\n\nApplicable scenarios:\n\n- Used to represent decision nodes, conditional judgments, or critical paths.\n\n- Suitable for representing decision nodes or key steps in flowcharts.\n\n- Commonly used in flowcharts, decision trees, network diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Diamond Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Diamond.zh.md) -->\n---\ntitle: 菱形节点 Diamond\norder: 3\n---\n\n## 概述\n\n菱形是一个四边相等的几何形状，具有对角线对称性。\n\n适用场景：\n\n- 用于表示决策节点、条件判断或关键路径。\n\n- 适合表示流程图中的判断节点或关键步骤。\n\n- 常用于流程图、决策树、网络图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/diamond.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置菱形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'diamond',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Donut.en.md) -->\n---\ntitle: Donut Node\norder: 4\n---\n\n## Overview\n\nThe donut node is a ring-shaped geometric figure composed of two concentric circles.\n\nApplicable scenarios:\n\n- Used to represent proportional data, such as completion progress and ratio analysis.\n\n- Suitable for representing multi-layered data, such as nested ring charts.\n\n- Commonly used in data visualization, dashboards, progress charts, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute           | Description                         | Type                                    | Default   | Required |\n| ------------------- | ----------------------------------- | --------------------------------------- | --------- | -------- |\n| donutFill           | Fill color                          | string                                  | `#1783FF` |          |\n| donutFillOpacity    | Fill color opacity                  | number \\| string                        | 1         |          |\n| donutLineCap        | Stroke end style                    | `round` \\| `square` \\| `butt`           | `butt`    |          |\n| donutLineDash       | Stroke dash style                   | number[]                                | -         |          |\n| donutLineDashOffset | Stroke dash offset                  | number                                  | -         |          |\n| donutLineJoin       | Stroke join style                   | `round` \\| `bevel` \\| `miter`           | `miter`   |          |\n| donutLineWidth      | Stroke width                        | number                                  | 1         |          |\n| donutOpacity        | Opacity                             | number \\| string                        | 1         |          |\n| donutPalette        | Color or palette name               | string \\| string[]                      | `tableau` |          |\n| donuts              | Donut data                          | number[] \\| [DonutRound](#donutround)[] | -         |          |\n| donutShadowBlur     | Shadow blur                         | number                                  | -         |          |\n| donutShadowColor    | Shadow color                        | string                                  | -         |          |\n| donutShadowOffsetX  | Shadow offset in x-axis direction   | number \\| string                        | -         |          |\n| donutShadowOffsetY  | Shadow offset in y-axis direction   | number \\| string                        | -         |          |\n| donutShadowType     | Shadow type                         | `inner` \\| `outer`                      | `outer`   |          |\n| donutStroke         | Stroke color                        | string                                  | `#000`    |          |\n| donutStrokeOpacity  | Stroke color opacity                | number \\| string                        | 1         |          |\n| donutVisibility     | Visibility of the shape             | `visible` \\| `hidden`                   | `visible` |          |\n| innerR              | Inner ring radius, percentage or px | string \\| number                        | 50%       |          |\n\n### DonutRound\n\n| Attribute      | Description                       | Type                          | Default   | Required |\n| -------------- | --------------------------------- | ----------------------------- | --------- | -------- |\n| color          | Color                             | string                        | -         |          |\n| fill           | Fill color                        | string                        | `#1783FF` |          |\n| fillOpacity    | Fill color opacity                | number \\| string              | 1         |          |\n| lineCap        | Stroke end style                  | `round` \\| `square` \\| `butt` | `butt`    |          |\n| lineDash       | Stroke dash style                 | number[]                      | -         |          |\n| lineDashOffset | Stroke dash offset                | number                        | -         |          |\n| lineJoin       | Stroke join style                 | `round` \\| `bevel` \\| `miter` | `miter`   |          |\n| lineWidth      | Stroke width                      | number                        | 1         |          |\n| opacity        | Opacity                           | number \\| string              | 1         |          |\n| shadowBlur     | Shadow blur                       | number                        | -         |          |\n| shadowColor    | Shadow color                      | string                        | -         |          |\n| shadowOffsetX  | Shadow offset in x-axis direction | number \\| string              | -         |          |\n| shadowOffsetY  | Shadow offset in y-axis direction | number \\| string              | -         |          |\n| shadowType     | Shadow type                       | `inner` \\| `outer`            | `outer`   |          |\n| stroke         | Stroke color                      | string                        | `#000`    |          |\n| strokeOpacity  | Stroke color opacity              | number \\| string              | 1         |          |\n| value          | Value for ratio calculation       | number                        | -         | ✓        |\n| visibility     | Visibility of the shape           | `visible` \\| `hidden`         | `visible` |          |\n\n## Example\n\n### Built-in Donut Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Donut.zh.md) -->\n---\ntitle: 甜甜圈节点 Donut\norder: 4\n---\n\n## 概述\n\n甜甜圈节点是一个环形几何形状，由内外两个同心圆组成。\n\n适用场景：\n\n- 用于表示比例数据，如完成进度、占比分析。\n\n- 适合表示多层数据，如嵌套的环形图。\n\n- 常用于数据可视化、仪表盘、进度图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/donut.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性                | 描述                           | 类型                                        | 默认值    | 必选 |\n| ------------------- | ------------------------------ | ------------------------------------------- | --------- | ---- |\n| donutFill           | 填充色                         | string                                      | `#1783FF` |      |\n| donutFillOpacity    | 填充色透明度                   | number \\| string                            | 1         |      |\n| donutLineCap        | 描边端点样式                   | `round` \\| `square` \\| `butt`               | `butt`    |      |\n| donutLineDash       | 描边虚线样式                   | number[]                                    | -         |      |\n| donutLineDashOffset | 描边虚线偏移量                 | number                                      | -         |      |\n| donutLineJoin       | 描边连接处样式                 | `round` \\| `bevel` \\| `miter`               | `miter`   |      |\n| donutLineWidth      | 描边宽度                       | number                                      | 1         |      |\n| donutOpacity        | 透明度                         | number \\| string                            | 1         |      |\n| donutPalette        | 颜色或者色板名                 | string &#124; string[]                      | `tableau` |      |\n| donuts              | 圆环数据                       | number[] &#124; [DonutRound](#donutround)[] | -         |      |\n| donutShadowBlur     | 阴影模糊度                     | number                                      | -         |      |\n| donutShadowColor    | 阴影颜色                       | string                                      | -         |      |\n| donutShadowOffsetX  | 阴影在 x 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowOffsetY  | 阴影在 y 轴方向上的偏移量      | number \\| string                            | -         |      |\n| donutShadowType     | 阴影类型                       | `inner` \\| `outer`                          | `outer`   |      |\n| donutStroke         | 描边色                         | string                                      | `#000`    |      |\n| donutStrokeOpacity  | 描边色透明度                   | number \\| string                            | 1         |      |\n| donutVisibility     | 图形是否可见                   | `visible` \\| `hidden`                       | `visible` |      |\n| innerR              | 内环半径，使用百分比或者像素值 | string &#124; number                        | 50%       |      |\n\n### DonutRound\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| color          | 颜色                      | string                        | -         |      |\n| fill           | 填充色                    | string                        | `#1783FF` |      |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |      |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |      |\n| lineDash       | 描边虚线样式              | number[]                      | -         |      |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |      |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |      |\n| lineWidth      | 描边宽度                  | number                        | 1         |      |\n| opacity        | 透明度                    | number \\| string              | 1         |      |\n| shadowBlur     | 阴影模糊度                | number                        | -         |      |\n| shadowColor    | 阴影颜色                  | string                        | -         |      |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |      |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |      |\n| stroke         | 描边色                    | string                        | `#000`    |      |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |      |\n| value          | 数值，用于计算比例        | number                        | -         | ✓    |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |      |\n\n## 示例\n\n### 内置甜甜圈节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default', index: 0 },\n    { id: 'halo', index: 1 },\n    { id: 'badges', index: 2 },\n    { id: 'ports', index: 3 },\n    {\n      id: 'active',\n      states: ['active'],\n      index: 4,\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n      index: 5,\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n      index: 6,\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n      index: 7,\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n      index: 8,\n    },\n  ],\n};\nconst graph = new Graph({\n  container: 'container',\n  animation: false,\n  data,\n  node: {\n    type: 'donut',\n    style: {\n      size: 80,\n      fill: '#DB9D0D',\n      innerR: 20,\n      donuts: (item) => {\n        const { index } = item;\n        if (index === 0) return [1, 2, 3]; // donuts数据类型为number[]时，根据值的大小决定环的占比\n\n        if (index === 1) {\n          return [\n            { value: 50, color: 'red' },\n            { value: 150, color: 'green' },\n            { value: 100, color: 'blue' },\n          ];\n        }\n\n        if (index === 4) {\n          return [\n            { value: 150, fill: 'pink', stroke: '#fff', lineWidth: 1 },\n            { value: 250, stroke: '#fff', lineWidth: 1 },\n            { value: 200, stroke: '#fff', lineWidth: 1 },\n          ];\n        }\n\n        return [100, 200, 100, 200];\n      },\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Ellipse.en.md) -->\n---\ntitle: Ellipse Node\norder: 5\n---\n\n## Overview\n\nAn ellipse is a geometric shape with asymmetrical major and minor axes.\n\nApplicable scenarios:\n\n- Used to represent dynamic nodes, asymmetric relationships, or special shapes.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Ellipse Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Ellipse.zh.md) -->\n---\ntitle: 椭圆形节点 Ellipse\norder: 5\n---\n\n## 概述\n\n椭圆是一个长轴和短轴不对称的几何形状。\n\n适用场景：\n\n- 用于表示动态节点、非对称关系或特殊形状。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/ellipse.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置椭圆形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'ellipse',\n    style: {\n      size: [45, 35],\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Hexagon.en.md) -->\n---\ntitle: Hexagon Node\norder: 6\n---\n\n## Overview\n\nA hexagon is a geometric shape with six equal sides, featuring a honeycomb structure.\n\nApplicable scenarios:\n\n- Used to represent honeycomb networks, molecular structures, or tightly packed nodes.\n\n- Suitable for representing network topology, molecular diagrams, or game maps.\n\n- Commonly used in network diagrams, topology diagrams, game design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                        | Type   | Default                                 | Required |\n| --------- | ------------------------------------------------------------------ | ------ | --------------------------------------- | -------- |\n| outerR    | Outer radius, the distance from the hexagon's center to any vertex | number | Half of the minimum of width and height |          |\n\n## Example\n\n### Built-in Hexagon Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Hexagon.zh.md) -->\n---\ntitle: 六边形节点 Hexagon\norder: 6\n---\n\n## 概述\n\n六边形是一个六边相等的几何形状，具有蜂窝状结构。\n\n适用场景：\n\n- 用于表示蜂窝网络、分子结构或紧密排列的节点。\n\n- 适合表示网络拓扑、分子图或游戏地图。\n\n- 常用于网络图、拓扑图、游戏设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/hexagon.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                     | 类型   | 默认值                   | 必选 |\n| ------ | ---------------------------------------- | ------ | ------------------------ | ---- |\n| outerR | 外半径，是指从六边形中心到任意顶点的距离 | number | 默认为宽高的最小值的一半 |      |\n\n## 示例\n\n### 内置六边形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'hexagon',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      outerR: 30, // 外半径\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Html.en.md) -->\n---\ntitle: HTML Node\norder: 7\n---\n\n## Overview\n\nHTML node is a custom rectangular area used to display HTML content. It allows you to embed arbitrary HTML elements within graph nodes, providing great flexibility for creating complex custom nodes.\n\nUse Cases:\n\n- Used to represent complex custom nodes such as tables, charts, or rich text\n- Suitable for representing custom visual elements or interactive components\n- Commonly used in custom charts, UI design, dashboards, and other scenarios\n- When you need to embed interactive elements like forms and buttons in nodes\n\n## Framework Support\n\n> **💡 Tips**：\n>\n> - **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node) for better component-based development experience\n> - **Vue Projects**: Vue Node is not currently supported, community contributions are welcome\n> - **Native HTML**: The HTML node introduced in this document is suitable for native HTML development\n\n## Online Demo\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific properties, we will list them below. For all common style properties, see [BaseNode](/en/manual/element/node/base-node)\n\n| Property  | Description                                                                                           | Type                        | Default | Required |\n| --------- | ----------------------------------------------------------------------------------------------------- | --------------------------- | ------- | -------- |\n| dx        | Horizontal offset. HTML container defaults to top-left corner as origin, use dx for horizontal offset | number                      | 0       |          |\n| dy        | Vertical offset. HTML container defaults to top-left corner as origin, use dy for vertical offset     | number                      | 0       |          |\n| innerHTML | HTML content, can be string or `HTMLElement`                                                          | string &#124; `HTMLElement` | -       | ✓        |\n\n## Examples\n\n### Basic HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### HTML Node with Interactive Buttons\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >Restart</button>\n    <button \n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >Monitor</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle button clicks\nwindow.handleRestart = (nodeId) => {\n  console.log(`Restarting server: ${nodeId}`);\n  alert(`Restarting server ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`Opening monitoring panel: ${nodeId}`);\n  alert(`Opening monitoring panel for server ${nodeId}`);\n};\n\ngraph.render();\n```\n\n### Form Input HTML Node\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: 'User Information', type: 'user-form' } },\n      { id: 'form-2', data: { title: 'Configuration Panel', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Name</label>\n    <input \n      type=\"text\" \n      placeholder=\"Enter name\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Email</label>\n    <input \n      type=\"email\" \n      placeholder=\"Enter email\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">Role</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>Administrator</option>\n      <option>User</option>\n      <option>Guest</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Save</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >Cancel</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// Global functions to handle form operations\nwindow.handleSave = (nodeId) => {\n  console.log(`Saving form: ${nodeId}`);\n  alert(`Form ${nodeId} saved`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`Canceling form: ${nodeId}`);\n  alert(`Form ${nodeId} operation canceled`);\n};\n\ngraph.render();\n```\n\n## Usage Notes\n\n### 1. Performance Optimization\n\n- HTML nodes have higher rendering costs compared to regular graphic nodes, recommend using when node count is small\n- Complex HTML structures will affect performance, recommend keeping structure simple\n- Avoid using too many animation effects in HTML\n\n### 2. Event Handling\n\n- Event handling in HTML nodes needs to be implemented through global functions or event delegation\n- Recommend mounting event handling functions to the `window` object to ensure accessibility in HTML strings\n- Be careful to prevent event bubbling from affecting graph interaction behavior\n\n### 3. Style Isolation\n\n- HTML node styles may be affected by global page styles\n- Recommend using inline styles or ensuring sufficient style specificity\n- Consider using CSS-in-JS or style namespaces to avoid style conflicts\n\n### 4. Responsive Design\n\n- HTML node dimensions are fixed and do not automatically adapt to content\n- Need to dynamically calculate node dimensions based on content or use responsive layouts\n- Consider display effects at different zoom levels\n\n### 5. Framework Integration Recommendations\n\n- **React Projects**: Recommended to use [React Node](/en/manual/element/node/react-node), which allows direct use of React components as node content\n- **Vue Projects**: Vue Node is not currently supported, community contributions are welcome if needed\n- **Native Projects**: HTML nodes are the best choice, providing maximum flexibility\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Html.zh.md) -->\n---\ntitle: HTML节点 Html\norder: 7\n---\n\n## 概述\n\nHTML 节点是一个自定义的矩形区域，用于显示 HTML 内容。它允许您在图形节点中嵌入任意的 HTML 元素，提供了极大的灵活性来创建复杂的自定义节点。\n\n适用场景：\n\n- 用于表示复杂的自定义节点，如表格、图表或富文本\n- 适合表示自定义的可视化元素或交互组件\n- 常用于自定义图表、UI 设计、仪表板等场景\n- 需要在节点中嵌入表单、按钮等交互元素时\n\n## 框架支持说明\n\n> **💡 提示**：\n>\n> - **React 项目**：推荐使用 [React Node](/manual/element/node/react-node) 来实现更好的组件化开发体验\n> - **Vue 项目**：目前暂不支持 Vue Node，欢迎社区共建贡献\n> - **原生 HTML**：本文档介绍的 HTML 节点适用于原生 HTML 开发\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/html.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述                                                            | 类型                        | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------- | --------------------------- | ------ | ---- |\n| dx        | 横行偏移量。HTML 容器默认以左上角为原点，通过 dx 来进行横向偏移 | number                      | 0      |      |\n| dy        | 纵向偏移量。HTML 容器默认以左上角为原点，通过 dy 来进行纵向偏移 | number                      | 0      |      |\n| innerHTML | HTML 内容，可以为字符串或者 `HTMLElement`                       | string &#124; `HTMLElement` | -      | ✓    |\n\n## 示例\n\n### 基础HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', data: { location: 'East', status: 'error', ip: '192.168.1.2' } },\n      { id: 'node-2', data: { location: 'West', status: 'overload', ip: '192.168.1.3' } },\n      { id: 'node-3', data: { location: 'South', status: 'running', ip: '192.168.1.4' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [240, 80],\n      dx: -120,\n      dy: -40,\n      innerHTML: (d) => {\n        const ICON_MAP = {\n          error: '&#10060;',\n          overload: '&#9889;',\n          running: '&#9989;',\n        };\n\n        const COLOR_MAP = {\n          error: '#f5222d',\n          overload: '#faad14',\n          running: '#52c41a',\n        };\n\n        const {\n          data: { location, status, ip },\n        } = d;\n        const color = COLOR_MAP[status];\n\n        return `\n<div \n  style=\"\n    width:100%; \n    height: 100%; \n    background: ${color}bb; \n    border: 1px solid ${color};\n    color: #fff;\n    user-select: none;\n    display: flex; \n    padding: 10px;\n    border-radius: 8px;\n    \"\n>\n  <div style=\"display: flex;flex-direction: column;flex: 1;\">\n    <div style=\"font-weight: bold; font-size: 14px;\">\n      ${location} Node\n    </div>\n    <div style=\"font-size: 12px; margin-top: 4px;\">\n      status: ${status} ${ICON_MAP[status]}\n    </div>\n  </div>\n  <div>\n    <span style=\"border: 1px solid white; padding: 2px 6px; border-radius: 4px; font-size: 12px;\">\n      ${ip}\n    </span>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 带交互按钮的HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'server-1', data: { name: 'Web Server', cpu: 45, memory: 67, status: 'online' } },\n      { id: 'server-2', data: { name: 'Database', cpu: 78, memory: 89, status: 'warning' } },\n      { id: 'server-3', data: { name: 'Cache Server', cpu: 23, memory: 34, status: 'offline' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [280, 210],\n      dx: -140,\n      dy: -105,\n      innerHTML: (d) => {\n        const { data } = d;\n        const statusColors = {\n          online: '#52c41a',\n          warning: '#faad14',\n          offline: '#f5222d',\n        };\n\n        return `\n<div style=\"\n  width: 100%;\n  height: 100%;\n  background: #fff;\n  border: 2px solid ${statusColors[data.status]};\n  border-radius: 12px;\n  padding: 16px;\n  box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;\">\n    <h3 style=\"margin: 0; font-size: 16px; color: #333;\">${data.name}</h3>\n    <span style=\"\n      background: ${statusColors[data.status]};\n      color: white;\n      padding: 2px 8px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: bold;\n    \">${data.status.toUpperCase()}</span>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">CPU</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.cpu}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.cpu > 70 ? '#f5222d' : '#52c41a'}; height: 100%; width: ${data.cpu}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"margin-bottom: 12px;\">\n    <div style=\"display: flex; justify-content: space-between; margin-bottom: 4px;\">\n      <span style=\"font-size: 12px; color: #666;\">Memory</span>\n      <span style=\"font-size: 12px; color: #333;\">${data.memory}%</span>\n    </div>\n    <div style=\"background: #f0f0f0; height: 6px; border-radius: 3px; overflow: hidden;\">\n      <div style=\"background: ${data.memory > 80 ? '#f5222d' : '#1890ff'}; height: 100%; width: ${data.memory}%; transition: width 0.3s;\"></div>\n    </div>\n  </div>\n\n  <div style=\"display: flex; gap: 8px;\">\n    <button\n      onclick=\"handleRestart('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#40a9ff'\"\n      onmouseout=\"this.style.background='#1890ff'\"\n    >重启</button>\n    <button\n      onclick=\"handleMonitor('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 6px 12px;\n        background: #52c41a;\n        color: white;\n        border: none;\n        border-radius: 6px;\n        font-size: 12px;\n        cursor: pointer;\n        transition: background 0.2s;\n      \"\n      onmouseover=\"this.style.background='#73d13d'\"\n      onmouseout=\"this.style.background='#52c41a'\"\n    >监控</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理按钮点击\nwindow.handleRestart = (nodeId) => {\n  console.log(`重启服务器: ${nodeId}`);\n  alert(`正在重启服务器 ${nodeId}...`);\n};\n\nwindow.handleMonitor = (nodeId) => {\n  console.log(`打开监控面板: ${nodeId}`);\n  alert(`打开服务器 ${nodeId} 的监控面板`);\n};\n\ngraph.render();\n```\n\n### 表单输入HTML节点\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'form-1', data: { title: '用户信息', type: 'user-form' } },\n      { id: 'form-2', data: { title: '配置面板', type: 'config-form' } },\n    ],\n  },\n  node: {\n    type: 'html',\n    style: {\n      size: [300, 400],\n      dx: -150,\n      dy: -200,\n      innerHTML: (d) => {\n        const { data } = d;\n\n        return `\n<div style=\"\n  width: 100%; \n  height: 100%; \n  background: #fff;\n  border: 1px solid #d9d9d9;\n  border-radius: 8px;\n  padding: 20px;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.1);\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n\">\n  <h3 style=\"margin: 0 0 16px 0; color: #333; font-size: 16px;\">${data.title}</h3>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">姓名</label>\n    <input \n      type=\"text\" \n      placeholder=\"请输入姓名\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 12px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">邮箱</label>\n    <input \n      type=\"email\" \n      placeholder=\"请输入邮箱\"\n      style=\"\n        width: 100%;\n        padding: 8px 12px;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        box-sizing: border-box;\n      \"\n    />\n  </div>\n  \n  <div style=\"margin-bottom: 16px;\">\n    <label style=\"display: block; margin-bottom: 4px; font-size: 14px; color: #666;\">角色</label>\n    <select style=\"\n      width: 100%;\n      padding: 8px 12px;\n      border: 1px solid #d9d9d9;\n      border-radius: 4px;\n      font-size: 14px;\n      box-sizing: border-box;\n    \">\n      <option>管理员</option>\n      <option>用户</option>\n      <option>访客</option>\n    </select>\n  </div>\n  \n  <div style=\"display: flex; gap: 8px;\">\n    <button \n      onclick=\"handleSave('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #1890ff;\n        color: white;\n        border: none;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >保存</button>\n    <button \n      onclick=\"handleCancel('${d.id}')\"\n      style=\"\n        flex: 1;\n        padding: 8px 16px;\n        background: #f5f5f5;\n        color: #333;\n        border: 1px solid #d9d9d9;\n        border-radius: 4px;\n        font-size: 14px;\n        cursor: pointer;\n      \"\n    >取消</button>\n  </div>\n</div>`;\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n    cols: 2,\n  },\n  behaviors: ['drag-element', 'zoom-canvas'],\n});\n\n// 全局函数处理表单操作\nwindow.handleSave = (nodeId) => {\n  console.log(`保存表单: ${nodeId}`);\n  alert(`表单 ${nodeId} 已保存`);\n};\n\nwindow.handleCancel = (nodeId) => {\n  console.log(`取消表单: ${nodeId}`);\n  alert(`取消表单 ${nodeId} 操作`);\n};\n\ngraph.render();\n```\n\n## 使用注意事项\n\n### 1. 性能优化\n\n- HTML 节点相比普通图形节点有更高的渲染成本，建议在节点数量较少时使用\n- 复杂的 HTML 结构会影响性能，建议保持结构简洁\n- 避免在 HTML 中使用过多的动画效果\n\n### 2. 事件处理\n\n- HTML 节点中的事件处理需要通过全局函数或事件委托来实现\n- 建议将事件处理函数挂载到 `window` 对象上，确保在 HTML 字符串中可以访问\n- 注意防止事件冒泡影响图的交互行为\n\n### 3. 样式隔离\n\n- HTML 节点的样式可能会受到页面全局样式的影响\n- 建议使用内联样式或确保样式的特异性足够高\n- 考虑使用 CSS-in-JS 或样式命名空间来避免样式冲突\n\n### 4. 响应式设计\n\n- HTML 节点的尺寸是固定的，不会自动适应内容\n- 需要根据内容动态计算节点尺寸，或使用响应式布局\n- 考虑在不同缩放级别下的显示效果\n\n### 5. 框架集成建议\n\n- **React 项目**：推荐使用 [React Node](/manual/element/node/react-node)，可以直接使用 React 组件作为节点内容\n- **Vue 项目**：目前暂不支持 Vue Node，如有需求欢迎社区贡献\n- **原生项目**：HTML 节点是最佳选择，提供了最大的灵活性\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Image.en.md) -->\n---\ntitle: Image Node\norder: 8\n---\n\n## Overview\n\nThe image node is a rectangular area used to display images.\n\nApplicable scenarios:\n\n- Used to represent user avatars, product images, or icons.\n\n- Suitable for representing social networks, product catalogs, or icon collections.\n\n- Commonly used in social network graphs, product images, UI design, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                          | Type   | Default | Required |\n| --------- | ------------------------------------ | ------ | ------- | -------- |\n| img       | Alias for the img attribute          | string | -       |          |\n| src       | Image source, i.e., image URL string | string | -       | ✓        |\n\n## Example\n\n### Built-in Image Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Image.zh.md) -->\n---\ntitle: 图片节点 Image\norder: 8\n---\n\n## 概述\n\n图片节点是一个矩形区域，用于显示图像。\n\n适用场景：\n\n- 用于表示用户头像、产品图片或图标。\n\n- 适合表示社交网络、产品目录或图标集合。\n\n- 常用于社交网络图、产品图、UI 设计等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/image.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性 | 描述                       | 类型   | 默认值 | 必选 |\n| ---- | -------------------------- | ------ | ------ | ---- |\n| img  | 该属性为 img 的别名        | string | -      |      |\n| src  | 图片来源，即图片地址字符串 | string | -      | ✓    |\n\n## 示例\n\n### 内置图片节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'image',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',\n      haloStroke: '#227eff',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n    state: {\n      inactive: {\n        fillOpacity: 0.5,\n      },\n      disabled: {\n        fillOpacity: 0.2,\n      },\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/overview.en.md) -->\n---\ntitle: Node Overview\norder: 0\n---\n\n## What is a Node\n\nA node is one of the basic elements in a graph, representing an entity or an abstract concept, such as a person, a place, an organization, etc. Nodes can contain attributes like ID, name, type, etc. In G6, nodes can have various shapes and styles, and support rich interactions and customization.\n\nYou can create any number of nodes in a graph and connect them with edges to represent relationships.\n\n## Node System\n\nThe G6 node system includes three main categories: built-in nodes, extended nodes, and custom nodes. **In most cases, built-in nodes are sufficient.**\n\n### Built-in Nodes\n\nG6 provides a variety of built-in node types, **which can be used directly without registration**:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| Node Type      | Registration Name | Description                                     |\n| -------------- | ----------------- | ----------------------------------------------- |\n| Circle Node    | `circle`          | Commonly used for entities                      |\n| Rectangle Node | `rect`            | Suitable for more text and details              |\n| Ellipse Node   | `ellipse`         | A variant of the circle                         |\n| Diamond Node   | `diamond`         | Often used for decision points or special nodes |\n| Triangle Node  | `triangle`        | Can indicate direction or special marks         |\n| Hexagon Node   | `hexagon`         | Suitable for grid layouts and honeycomb charts  |\n| Star Node      | `star`            | Highlights important nodes                      |\n| Donut Node     | `donut`           | Can display proportions or progress             |\n| Image Node     | `image`           | Uses an image as the node body                  |\n| HTML Node      | `html`            | Supports custom HTML content                    |\n\n### 3D Nodes\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` provides 3D nodes:\n\n- `Capsule` - Capsule-shaped node\n- `Cone` - Cone-shaped node\n- `Cube` - Cube-shaped node\n- `Cylinder` - Cylinder-shaped node\n- `Plane` - Plane node\n- `Sphere` - Sphere node\n- `Torus` - Torus node\n\n### React Nodes\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` provides React nodes, supporting the use of React components as the node body. For detailed tutorials, please refer to the [Using React to Define Nodes](/en/manual/element/node/react-node) document.\n\n### Custom Nodes\n\nWhen built-in and extended nodes cannot meet the requirements, G6 offers powerful customization capabilities:\n\n- Extend built-in nodes\n- Create entirely new node types\n\nUnlike built-in nodes, **custom nodes need to be registered before use**. For detailed tutorials, please refer to the [Custom Nodes](/en/manual/element/node/custom-node) document.\n\n## Data Structure\n\nWhen defining nodes, you need to add a `nodes` field to the graph's data object. Each node is an object with the following structure:\n\n| Property | Description                                                                                                                             | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                     | string         | -       | ✓        |\n| type     | Node type, either a built-in node type name or a custom node name                                                                       | string         | -       |          |\n| data     | Node data, used to store custom data such as the node's name, description, etc. Can be accessed via callback functions in style mapping | object         | -       |          |\n| style    | Node style, including visual attributes like position, size, color, etc.                                                                | object         | -       |          |\n| states   | Initial states of the node, such as selected, active, hover, etc.                                                                       | string[]       | -       |          |\n| combo    | The ID of the combo to which the node belongs, used to organize hierarchical relationships. If none, it is null                         | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                         | string[]       | -       |          |\n\nAn example of a data item in the `nodes` array:\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## Configuration Methods\n\nThere are three ways to configure nodes, listed in order of priority from high to low:\n\n- Use `graph.setNode()` for dynamic configuration\n- Global configuration during graph instantiation\n- Dynamic properties in data\n\nThese configuration methods can be used simultaneously. When there are identical configuration items, the method with higher priority will override the one with lower priority.\n\n### Using `graph.setNode()`\n\nAfter creating the graph instance, you can use `graph.setNode()` to dynamically set the node's style mapping logic.\n\nThis method must be called before `graph.render()` to take effect and has the highest priority.\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### Global Configuration During Graph Instantiation\n\nWhen instantiating the graph, you can configure node style mapping through `node`, which is a global configuration and will apply to all nodes.\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### Dynamic Configuration in Data\n\nIf you need different configurations for different nodes, you can write the configuration into the node data. This configuration method can be directly written into the data in the following form:\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### Adjusting Priority\n\nIf you want the configuration in the data to have a higher priority than the global configuration, you can do so as follows:\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### Dynamically Updating Nodes\n\nG6 supports dynamically updating the style and state of nodes at runtime:\n\n```typescript\n// Update the style of a single node\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// Set node state\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=Note}\nWhen updating nodes, only the specified attributes will be updated, and unspecified attributes will remain unchanged.\n:::\n\nFor more node-related APIs, please refer to [API - Element Operations](/en/api/element).\n\n## Node States\n\nNodes can have different states, such as selected, highlighted, disabled, etc. You can define the display effect of nodes in different states by configuring state styles:\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // Default style\n      fill: '#C6E5FF',\n    },\n    // State styles\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\nThe state system is the foundation for implementing node interaction effects. For more information on states, please refer to [Element States](/en/manual/element/state).\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/overview.zh.md) -->\n---\ntitle: 节点总览\norder: 0\n---\n\n## 什么是节点\n\n节点（Node）是图中的基本元素之一，表示图中的实体或者抽象概念，例如一个人、一个地点、一个组织等，节点可以包含一些属性，例如节点的 ID、名称、类型等。在 G6 中，节点可以具有多种形状和样式，并支持丰富的交互和自定义功能。\n\n你可以在图中创建任意数量的节点，并通过边连接它们以表示关系。\n\n## 节点体系\n\nG6 的节点体系包括三大类：内置节点、扩展节点和自定义节点。**大多数场景下，内置节点即可满足需求**。\n\n### 内置节点\n\nG6 提供了丰富的内置节点类型，**无需注册，直接配置即可使用**：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n| 节点类型   | 注册名称   | 描述                     |\n| ---------- | ---------- | ------------------------ |\n| 圆形节点   | `circle`   | 常用于表示普通实体       |\n| 矩形节点   | `rect`     | 适合展示更多文本和细节   |\n| 椭圆节点   | `ellipse`  | 类似圆形的变体           |\n| 菱形节点   | `diamond`  | 常用于决策点或特殊节点   |\n| 三角形节点 | `triangle` | 可用于指示方向或特殊标记 |\n| 六边形节点 | `hexagon`  | 适合网格布局和蜂窝图     |\n| 星形节点   | `star`     | 突出显示重要节点         |\n| 甜甜圈节点 | `donut`    | 可展示比例或进度信息     |\n| 图片节点   | `image`    | 使用图片作为节点主体     |\n| HTML节点   | `html`     | 支持自定义HTML内容       |\n\n### 3D 节点\n\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ShNXTp0u3vkAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-3d` 提供了 3D 节点：\n\n- `Capsule` - 胶囊型节点\n- `Cone` - 圆锥型节点\n- `Cube` - 立方体节点\n- `Cylinder` - 圆柱型节点\n- `Plane` - 平面节点\n- `Sphere` - 球体节点\n- `Torus` - 圆环节点\n\n### React 节点\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7jypQbkp00wAAAAAAAAAAAAADmJ7AQ/original\" />\n\n`@antv/g6-extension-react` 提供了 React 节点，支持使用 React 组件作为节点的主体，详细教程请查看 [使用 React 定义节点](/manual/element/node/react-node) 文档。\n\n### 自定义节点\n\n当内置节点和扩展节点无法满足需求时，G6提供了强大的自定义能力：\n\n- 继承内置节点进行扩展\n- 创建全新的节点类型\n\n与内置节点不同，**自定义节点需要先注册后使用**。详细教程请参考 [自定义节点](/manual/element/node/custom-node) 文档。\n\n## 数据结构\n\n定义节点时，需要在图的数据对象中添加 `nodes` 字段。每个节点是一个对象，结构如下：\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n`nodes` 数组中一个数据项的示例：\n\n```json\n{\n  \"id\": \"node-1\",\n  \"type\": \"circle\",\n  \"data\": { \"name\": \"alice\", \"role\": \"Admin\" },\n  \"style\": { \"x\": 100, \"y\": 200, \"size\": 32, \"fill\": \"violet\" },\n  \"states\": [\"selected\"],\n  \"combo\": null\n}\n```\n\n## 配置方法\n\n配置节点的方式有三种，按优先级从高到低如下：\n\n- 使用 `graph.setNode()` 动态配置\n- 实例化图时全局配置\n- 在数据中动态属性\n\n这几个配置方法可以同时使用。有相同的配置项时，优先级高的方式将会覆盖优先级低的。\n\n### 使用 `graph.setNode()`\n\n可在图实例创建后，使用 `graph.setNode()` 动态设置节点的样式映射逻辑。\n\n该方法需要在 `graph.render()` 之前调用才会生效，并拥有最高优先级。\n\n```js\ngraph.setNode({\n  style: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n\ngraph.render();\n```\n\n### 实例化图时全局配置\n\n在实例化图时可以通过 `node` 配置节点样式映射，这里的配置是全局的配置，将会在所有节点上生效。\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n  },\n});\n```\n\n### 在数据中动态配置\n\n如果需要为不同节点进行不同的配置，可以将配置写入到节点数据中。这种配置方式可以通过下面代码的形式直接写入数据：\n\n```typescript\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n```\n\n### 调整优先级\n\n如果你想让数据中配置的优先级高于全局配置，你可以采取以下方式：\n\n```js\nconst data = {\n  nodes: [\n    {\n      id: 'node-1',\n      type: 'circle',\n      style: { size: 60, fill: '#7FFFD4', stroke: '#5CACEE', lineWidth: 2 },\n    },\n  ],\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'circle',\n    style: {\n      stroke: (d) => d.style.stroke || '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n});\n```\n\n### 动态更新节点\n\nG6 支持在运行时动态更新节点的样式和状态：\n\n```typescript\n// 更新单个节点样式\ngraph.updateNodeData([\n  {\n    id: 'node-1',\n    style: {\n      fill: 'red',\n      size: 80,\n    },\n  },\n]);\ngraph.draw();\n\n// 设置节点状态\ngraph.setElementState('node-1', ['selected']);\n```\n\n:::warning{title=注意}\n更新节点时，只有指定的属性会被更新，未指定的属性保持不变。\n:::\n\n更多与节点相关的 API 请参考 [API - 元素操作](/api/element)。\n\n## 节点状态\n\n节点可以拥有不同的状态，例如选中、高亮、禁用等。可以通过配置状态样式来定义节点在不同状态下的显示效果：\n\n```typescript\nconst graph = new Graph({\n  node: {\n    style: {\n      // 默认样式\n      fill: '#C6E5FF',\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#ffa940',\n        stroke: '#ff7a00',\n        haloStroke: '#ff7a00',\n      },\n      highlight: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n状态系统是实现节点交互效果的基础，更多状态的介绍，请参考 [元素状态](/manual/element/state)。\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/react-node.en.md) -->\n---\ntitle: Define Nodes with React\norder: 13\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the `@antv/g6-extension-react` ecosystem library, you can directly use React components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Ant Design\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing React design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a React project**: Ensure a React project is installed and created.\n- **React version requirement**: Ensure the React version used is >=16.8.0.\n\n### Install Dependencies\n\nTo use `@antv/g6-extension-react`, run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register React Node Type\n\nRegister the React node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `react-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: ReactNode is the implementation class exported by `@antv/g6-extension-react`\n\n#### 2. Define Business Component\n\nDefine a simple React component as the content of the node:\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. Use the Component\n\nUse the custom React node in the graph configuration. Specify the node type and style in the graph configuration to use the custom React component.\n\n- `type`: Specify the node type as `react-node` (use the name given during registration)\n- `style.component`: Define the React component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // Set border color based on selection state\n        cursor: 'pointer', // Add mouse pointer style\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/react-node.zh.md) -->\n---\ntitle: 使用 React 定义节点\norder: 13\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 `@antv/g6-extension-react` 一方生态库，可以直接使用 React 组件作为节点内容，提升开发效率与可维护性。\n\n## 自定义节点方案选择\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### React Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Ant Design 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 React 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 React 项目**：确保已安装并创建 React 项目。\n- **React 版本要求**：确保使用的 React 版本 >=16.8.0。\n\n### 安装依赖\n\n要使用 `@antv/g6-extension-react`，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install @antv/g6-extension-react\n```\n\n```bash [yarn]\nyarn add @antv/g6-extension-react\n```\n\n```bash [pnpm]\npnpm add @antv/g6-extension-react\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 React 节点类型\n\n通过扩展机制注册 React 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`react-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：ReactNode 是 `@antv/g6-extension-react` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 React 组件作为节点的内容：\n\n```jsx\nconst MyReactNode = () => {\n  return <div>node</div>;\n};\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 React 节点。通过在图配置中指定节点类型和样式，来使用自定义的 React 组件。\n\n- `type`：指定节点类型为 `react-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 React 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: () => <MyReactNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst StatefulNode = ({ data }) => {\n  const isActive = data.states?.includes('active');\n\n  return (\n    <div\n      style={{\n        width: 100,\n        padding: 5,\n        border: '1px solid #eee',\n        boxShadow: isActive ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n        transform: `scale(${isActive ? 1.05 : 1})`,\n      }}\n    >\n      {data.data.label}\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <StatefulNode data={data} />,\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst MyReactNode = ({ data, graph }) => {\n  const handleClick = () => {\n    graph.updateNodeData([{ id: data.id, data: { selected: !data.data.selected } }]);\n    graph.draw();\n  };\n\n  return (\n    <div\n      style={{\n        width: 200,\n        padding: 10,\n        border: '1px solid red',\n        borderColor: data.data.selected ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n        cursor: 'pointer', // 添加鼠标指针样式\n      }}\n      onClick={handleClick}\n    >\n      Node\n    </div>\n  );\n};\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'react-node',\n    style: {\n      component: (data) => <MyReactNode data={data} graph={graph} />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nconst IDCardNode = ({ id, selected, graph }) => {\n  const handleSelect = () => {\n    graph.updateNodeData([{ id, data: { selected: true } }]);\n    graph.draw();\n  };\n\n  return <Select onChange={handleSelect} style={{ background: selected ? 'orange' : '#eee' }} />;\n};\n\nconst graph = new Graph({\n  node: {\n    type: 'react-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={data.selected} graph={graph} />,\n    },\n  },\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { DatabaseFilled } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Badge, Flex, Input, Tag, Typography } from 'antd';\nimport { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Text } = Typography;\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n\nconst Node = ({ data, onChange }) => {\n  const { status, type } = data.data;\n\n  return (\n    <Flex\n      style={{\n        width: '100%',\n        height: '100%',\n        background: '#fff',\n        padding: 10,\n        borderRadius: 5,\n        border: '1px solid gray',\n      }}\n      vertical\n    >\n      <Flex align=\"center\" justify=\"space-between\">\n        <Text>\n          <DatabaseFilled />\n          Server\n          <Tag>{type}</Tag>\n        </Text>\n        <Badge status={status} />\n      </Flex>\n      <Text type=\"secondary\">{data.id}</Text>\n      <Flex align=\"center\">\n        <Text style={{ flexShrink: 0 }}>\n          <Text type=\"danger\">*</Text>URL:\n        </Text>\n        <Input\n          style={{ borderRadius: 0, borderBottom: '1px solid #d9d9d9' }}\n          variant=\"borderless\"\n          value={data.data?.url}\n          onChange={(event) => {\n            const url = event.target.value;\n            onChange?.(url);\n          }}\n        />\n      </Flex>\n    </Flex>\n  );\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n\n  useEffect(() => {\n    const graph = new Graph({\n      container: containerRef.current,\n      data: {\n        nodes: [\n          {\n            id: 'local-server-1',\n            data: { status: 'success', type: 'local', url: 'http://localhost:3000' },\n            style: { x: 50, y: 50 },\n          },\n          {\n            id: 'remote-server-1',\n            data: { status: 'warning', type: 'remote' },\n            style: { x: 350, y: 50 },\n          },\n        ],\n        edges: [{ source: 'local-server-1', target: 'remote-server-1' }],\n      },\n      node: {\n        type: 'react',\n        style: {\n          size: [240, 100],\n          component: (data) => <Node data={data} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n    });\n\n    graph.render();\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n<br/>\n\n```js | ob { inject: true }\nimport { UserOutlined } from '@ant-design/icons';\nimport { ExtensionCategory, Graph, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\nimport { Avatar, Button, Card, Descriptions, Select, Space, Typography } from 'antd';\nimport React, { useEffect, useRef } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst { Title, Text } = Typography;\nconst { Option } = Select;\n\nregister(ExtensionCategory.NODE, 'react-node', ReactNode);\n\nconst IDCardNode = ({ id, data }) => {\n  const { name, idNumber, address, expanded, selected, graph } = data;\n\n  const toggleExpand = (e) => {\n    e.stopPropagation();\n    graph.updateNodeData([\n      {\n        id,\n        data: { expanded: !expanded },\n      },\n    ]);\n    graph.render();\n  };\n\n  const handleSelect = (value) => {\n    graph.updateNodeData([\n      {\n        id,\n        data: { selected: value !== 0 },\n      },\n    ]);\n    if (value === 2) {\n      // 获取与当前节点相连的所有节点\n      const connectedNodes = graph.getNeighborNodesData(id);\n\n      connectedNodes.forEach((node) => {\n        graph.updateNodeData([\n          {\n            id: node.id,\n            data: { selected: true },\n          },\n        ]);\n      });\n    }\n    graph.render();\n  };\n\n  const CardTitle = (\n    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n      <Space>\n        <Avatar shape=\"square\" size=\"small\" icon={<UserOutlined />} />\n        <Title level={5} style={{ margin: 0 }}>\n          {name}\n        </Title>\n\n        <Select\n          value={selected ? data.selectedOption || 1 : 0}\n          style={{ width: 150, marginRight: 8 }}\n          onChange={handleSelect}\n        >\n          <Option value={0}>None</Option>\n          <Option value={1}>Node</Option>\n          <Option value={2}>Connected</Option>\n        </Select>\n      </Space>\n      <Button type=\"link\" onClick={toggleExpand} style={{ padding: 0 }}>\n        {expanded ? 'fold' : 'expand'}\n      </Button>\n    </div>\n  );\n\n  return (\n    <Card\n      size=\"small\"\n      title={CardTitle}\n      style={{\n        width: 340,\n        padding: 10,\n        borderRadius: 8,\n        borderWidth: 2,\n        borderColor: selected ? 'orange' : '#eee', // 根据选中状态设置边框颜色\n        cursor: 'pointer',\n      }}\n    >\n      {expanded ? (\n        <Descriptions bordered column={1} style={{ width: '100%', textAlign: 'center' }}>\n          <Descriptions.Item label=\"ID Number\">{idNumber}</Descriptions.Item>\n          <Descriptions.Item label=\"Address\">{address}</Descriptions.Item>\n        </Descriptions>\n      ) : (\n        <Text style={{ textAlign: 'center' }}>IDCard Information</Text>\n      )}\n    </Card>\n  );\n};\n\n// 定义 Graph 数据\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      data: {\n        name: 'Alice',\n        idNumber: 'IDUSAASD2131734',\n        address: '1234 Broadway, Apt 5B, New York, NY 10001',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 1, // 初始选择本节点\n      },\n      style: { x: 50, y: 50 },\n    },\n    {\n      id: 'node2',\n      data: {\n        name: 'Bob',\n        idNumber: 'IDUSAASD1431920',\n        address: '3030 Chestnut St, Philadelphia, PA 19104',\n        expanded: false, // 初始状态为收缩\n        selected: false, // 初始状态为未选中\n        selectedOption: 0, // 初始不选择\n      },\n      style: { x: 700, y: 100 },\n    },\n    {\n      id: 'node3',\n      data: {\n        name: 'Charlie',\n        idNumber: 'IDUSAASD1431921',\n        address: '4040 Elm St, Chicago, IL 60611',\n        expanded: false,\n        selected: true,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node4',\n      data: {\n        name: 'David',\n        idNumber: 'IDUSAASD1431922',\n        address: '5050 Oak St, Houston, TX 77002',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n    {\n      id: 'node5',\n      data: {\n        name: 'Eve',\n        idNumber: 'IDUSAASD1431923',\n        address: '6060 Pine St, Phoenix, AZ 85001',\n        expanded: false,\n        selected: false,\n        selectedOption: 0,\n      },\n    },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node2', target: 'node3' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n  ],\n};\n\nexport const ReactNodeDemo = () => {\n  const containerRef = useRef();\n  const graphRef = useRef(null);\n\n  useEffect(() => {\n    // 创建 Graph 实例\n    const graph = new Graph({\n      autoFit: 'view',\n      container: containerRef.current,\n      data,\n      node: {\n        type: 'react-node',\n        style: {\n          size: (datum) => (datum.data.expanded ? [340, 236] : [340, 105]), // 调整大小以适应内容\n          component: (data) => <IDCardNode id={data.id} data={{ ...data.data, graph: graph }} />,\n        },\n      },\n      behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'],\n      layout: {\n        type: 'snake',\n        cols: 2,\n        rowGap: 100,\n        colGap: 220,\n      },\n    });\n\n    // 渲染 Graph\n    graph.render();\n\n    // 保存 graph 实例\n    graphRef.current = graph;\n\n    return () => {\n      graph.destroy();\n    };\n  }, []);\n\n  return <div style={{ width: '100%', height: '100%' }} ref={containerRef}></div>;\n};\n\n// 渲染 React 组件到 DOM\nconst root = createRoot(document.getElementById('container'));\nroot.render(<ReactNodeDemo />);\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Rect.en.md) -->\n---\ntitle: Rect Node\norder: 9\n---\n\n## Overview\n\nA rectangle is a geometric shape with four equal sides and defined boundaries.\n\nApplicable scenarios:\n\n- Used to represent modules, components, or containers.\n\n- Suitable for representing hierarchies, such as organizational charts, file directory trees.\n\n- Commonly used in flowcharts, architecture diagrams, UML diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n## Example\n\n### Built-in Rect Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Rect.zh.md) -->\n---\ntitle: 矩形节点 Rect\norder: 9\n---\n\n## 概述\n\n矩形是一个四边相等的几何形状，具有明确的边界。\n\n适用场景：\n\n- 用于表示模块、组件或容器。\n\n- 适合表示层次结构，如组织结构图、文件目录树。\n\n- 常用于流程图、架构图、UML 图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/rect.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n## 示例\n\n### 内置矩形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'rect',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Star.en.md) -->\n---\ntitle: Star Node\norder: 10\n---\n\n## Overview\n\nA star is a polygonal geometric shape with prominent points.\n\nApplicable scenarios:\n\n- Used to represent important nodes, special markers, or decorative elements.\n\n- Suitable for representing flowcharts, network diagrams, or topology diagrams.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description                                                           | Type   | Default                            | Required |\n| --------- | --------------------------------------------------------------------- | ------ | ---------------------------------- | -------- |\n| innerR    | Inner radius, the distance from the star's center to the inner vertex | number | Default is 3/8 of the outer radius |\n\nStructure Description:\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## Example\n\n### Built-in Star Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Star.zh.md) -->\n---\ntitle: 五角形节点 Star\norder: 10\n---\n\n## 概述\n\n星形是一个多角几何形状，具有突出的角。\n\n适用场景：\n\n- 用于表示重要节点、特殊标记或装饰性元素。\n\n- 适合表示流程图、网络图或拓扑图。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/star.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性   | 描述                                 | 类型   | 默认值             | 必选 |\n| ------ | ------------------------------------ | ------ | ------------------ | ---- |\n| innerR | 内半径，是指从星形中心到内顶点的距离 | number | 默认为外半径的 3/8 |\n\n结构说明：\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VKrvQpdqwXoAAAAAAAAAAAAAemJ7AQ/original\" />\n\n## 示例\n\n### 内置五角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'star',\n    style: {\n      size: 40,\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Triangle.en.md) -->\n---\ntitle: Triangle Node\norder: 11\n---\n\n## Overview\n\nA triangle is a geometric shape with three sides, having a clear directionality.\n\nApplicable scenarios:\n\n- Used to represent directional nodes, warnings, or prompts.\n\n- Suitable for indicating direction or hierarchy in flowcharts.\n\n- Commonly used in flowcharts, network diagrams, topology diagrams, etc.\n\n## Online Experience\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## Style Configuration\n\n> If the element has specific attributes, we will list them below. For all general style attributes, see [BaseNode](/en/manual/element/node/base-node)\n\n| Attribute | Description               | Type                                | Default | Required |\n| --------- | ------------------------- | ----------------------------------- | ------- | -------- |\n| direction | Direction of the triangle | `up` \\| `left` \\| `right` \\| `down` | `up`    |\n\n## Example\n\n### Built-in Triangle Node Effect\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/Triangle.zh.md) -->\n---\ntitle: 三角形节点 Triangle\norder: 11\n---\n\n## 概述\n\n三角形是一个三边几何形状，具有明确的方向性。\n\n适用场景：\n\n- 用于表示方向性节点、警告或提示。\n\n- 适合表示流程图中的方向指示或层级关系。\n\n- 常用于流程图、网络图、拓扑图等。\n\n## 在线体验\n\n<embed src=\"@/common/api/elements/nodes/triangle.md\"></embed>\n\n## 样式配置\n\n> 如果元素有其特定的属性，我们将在下面列出。对于所有的通用样式属性，见 [BaseNode](/manual/element/node/base-node)\n\n| 属性      | 描述         | 类型                                | 默认值 | 必选 |\n| --------- | ------------ | ----------------------------------- | ------ | ---- |\n| direction | 三角形的方向 | `up` \\| `left` \\| `right` \\| `down` | `up`   |\n\n## 示例\n\n### 内置三角形节点效果\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nconst data = {\n  nodes: [\n    { id: 'default' },\n    { id: 'halo' },\n    { id: 'badges' },\n    { id: 'ports' },\n    {\n      id: 'active',\n      states: ['active'],\n    },\n    {\n      id: 'selected',\n      states: ['selected'],\n    },\n    {\n      id: 'highlight',\n      states: ['highlight'],\n    },\n    {\n      id: 'inactive',\n      states: ['inactive'],\n    },\n    {\n      id: 'disabled',\n      states: ['disabled'],\n    },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    type: 'triangle',\n    style: {\n      size: 40,\n      direction: (d) => (d.id === 'ports' ? 'left' : undefined),\n      labelText: (d) => d.id,\n      iconFontFamily: 'iconfont',\n      iconText: '\\ue602',\n      halo: (d) => (d.id === 'halo' ? true : false),\n      badges: (d) =>\n        d.id === 'badges'\n          ? [\n              {\n                text: 'A',\n                placement: 'right-top',\n              },\n              {\n                text: 'Important',\n                placement: 'right',\n              },\n              {\n                text: 'Notice',\n                placement: 'right-bottom',\n              },\n            ]\n          : [],\n      badgeFontSize: 8,\n      badgePadding: [1, 4],\n      portR: 3,\n      ports: (d) =>\n        d.id === 'ports'\n          ? [{ placement: 'left' }, { placement: 'right' }, { placement: 'top' }, { placement: 'bottom' }]\n          : [],\n    },\n  },\n  layout: {\n    type: 'grid',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/vue-node.en.md) -->\n---\ntitle: Define Nodes with Vue\norder: 14\n---\n\nIn G6, custom nodes typically require manipulating DOM or Canvas elements, but with the help of the [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) ecosystem library, you can directly use Vue components as node content, enhancing development efficiency and maintainability.\n\n## Choosing a Custom Node Solution\n\n### G6 Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **Recommended Scenarios:**\n\n- Nodes are simple geometric shapes\n- Scenarios requiring efficient rendering of more than 2,000 nodes\n- Need to directly manipulate graphic instances for fine control\n\n> For detailed information on how to customize nodes using Canvas graphics, please refer to the [Custom Node](/en/manual/element/node/custom-node) documentation\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **Recommended Scenarios:**\n\n- Business systems that need to integrate UI libraries like Element Plus / Ant Design Vue\n- Nodes contain interactive logic such as form input, state switching\n- Scenarios where an existing Vue design system needs to be reused\n\n## Quick Start\n\n### Environment Preparation\n\nBefore starting, please ensure you have:\n\n- **Installed a Vue project**: Ensure a Vue project is installed and created.\n- **Vue version requirement**: Ensure the Vue version used is >=2.6.0. (Vue 3 is recommended)\n\n### Install Dependencies\n\nTo use [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue), run the following command:\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### Component Integration\n\n#### 1. Register Vue Node Type\n\nRegister the Vue node type through the extension mechanism:\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\nThe `register` method requires three parameters:\n\n- Extension category: `ExtensionCategory.NODE` indicates this is a node type\n- Type name: `vue-node` is the name we give to this custom node, which will be used in the configuration later\n- Class definition: VueNode is the implementation class exported by `g6-extension-vue`\n\n#### 2. Define Business Component\n\nDefine a simple Vue component as the content of the node:\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. Use the Component\n\nUse the custom Vue node in the graph configuration. Specify the node type and style in the graph configuration to use the custom Vue component.\n\n- `type`: Specify the node type as `vue-node` (use the name given during registration)\n- `style.component`: Define the Vue component content of the node\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Advanced Features\n\n### State Management\n\nIn complex graph visualization scenarios, nodes need to dynamically respond to interaction states. We provide two complementary state management solutions:\n\n#### Respond to Built-in Interaction States\n\nG6 provides built-in interaction state management states, such as `hover-activate` and `click-select`. You can get the current node state through the `data.states` field in the node data and adjust the node style based on the state.\n\n**Example**: Change the background color when the node is hovered.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### Custom Business State\n\nWhen you need to manage business-related states (such as approval status, risk level), you can extend node data to achieve this:\n\n**Example**: Add a `selected` variable through data to achieve style changes for node selection and deselection.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // Set border color based on selection state\n          cursor: 'pointer', // Add mouse pointer style\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data is non-reactive, need to change reference to trigger Vue's props side effects\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Event Interaction\n\nAchieve two-way communication between nodes and graph instances, allowing nodes and graph instances to update each other.\n\n**Example**: Operate graph data through custom nodes and re-render the graph.\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n\n\n<!-- Skill/Rule: Node Skill (packages/site/docs/manual/element/node/vue-node.zh.md) -->\n---\ntitle: 使用 Vue 定义节点\norder: 14\n---\n\n在 G6 中，自定义节点通常需要操作 DOM 或 Canvas 元素，但借助 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue) 社区生态库，可以直接使用 Vue 组件作为节点内容，提升开发效率与可维护性。\n\n### G6 节点\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sEaLR7Q_hmoAAAAAAAAAAAAAemJ7AQ/fmt.avif\" width=\"300\" />\n\n✅ **推荐场景：**\n\n- 节点只是简单的几何图形\n- 需要高效渲染超过 2,000 个节点的场景\n- 需要直接操作图形实例进行精细控制\n\n> 有关如何使用 Canvas 图形自定义节点的详细信息，请参阅 [自定义节点](/manual/element/node/custom-node) 文档\n\n### Vue Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*9oz-R7bIkd0AAAAAAAAAAAAADmJ7AQ/original\" width=\"350\" />\n\n✅ **推荐场景：**\n\n- 需要集成 Element Plus / Ant Design Vue 等 UI 库的业务系统\n- 节点包含表单输入、状态切换等交互逻辑\n- 已有 Vue 设计系统需要复用的场景\n\n## 快速入门\n\n### 环境准备\n\n在开始之前，请确保您已经：\n\n- **安装 Vue 项目**：确保已安装并创建 Vue 项目。\n- **Vue 版本要求**：确保使用的 Vue 版本 >=2.6.0。(推荐使用 Vue 3)\n\n### 安装依赖\n\n要使用 [`g6-extension-vue`](https://github.com/Child-qjj/g6-extension-vue)，请运行以下命令：\n\n:::code-group\n\n```bash [npm]\nnpm install g6-extension-vue\n```\n\n```bash [yarn]\nyarn add g6-extension-vue\n```\n\n```bash [pnpm]\npnpm add g6-extension-vue\n```\n\n:::\n\n### 组件集成\n\n#### 1. 注册 Vue 节点类型\n\n通过扩展机制注册 Vue 节点类型：\n\n```jsx\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n```\n\n`register` 方法需要三个参数：\n\n- 扩展类别：`ExtensionCategory.NODE` 表示这是一个节点类型\n- 类型名称：`vue-node` 是我们给这个自定义节点起的名字，后续会在配置中使用\n- 类定义：VueNode 是 `g6-extension-vue` 导出的实现类\n\n#### 2. 定义业务组件\n\n定义一个简单的 Vue 组件作为节点的内容：\n\n```jsx\nimport { defineComponent, h } from 'vue';\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    return () => {\n      return h('div', 'vue node');\n    };\n  },\n});\n```\n\n#### 3. 使用组件\n\n在图配置中使用自定义的 Vue 节点。通过在图配置中指定节点类型和样式，来使用自定义的 Vue 组件。\n\n- `type`：指定节点类型为 `vue-node` (使用与注册时起的名字)\n- `style.component`：定义节点的 Vue 组件内容\n\n```jsx\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: () => <MyVueNode />,\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 高级功能\n\n### 状态管理\n\n在复杂图可视化场景中，节点需要动态响应交互状态。我们提供两种互补的状态管理方案：\n\n#### 响应内置交互状态\n\nG6 提供内置的交互状态管理状态，如 `hover-activate` 和 `click-select`。可以通过节点数据中的 `data.states` 字段获取当前节点状态，并根据状态调整节点样式。\n\n**示例**：在节点被 hover 时改变背景颜色。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { computed, defineComponent } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst StatefulNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isActive = computed(() => props.data.states?.includes('active'));\n    const label = computed(() => props.data.data?.label);\n\n    return (\n      <div\n        style={{\n          width: 100,\n          padding: 5,\n          border: '1px solid #eee',\n          boxShadow: isActive.value ? '0 0 8px rgba(24,144,255,0.8)' : 'none',\n          transform: `scale(${isActive.value ? 1.05 : 1})`,\n        }}\n      >\n        {label.value}\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 200 }, data: { label: 'node1' } },\n      { id: 'node2', style: { x: 300, y: 200 }, data: { label: 'node2' } },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <StatefulNode data={Object.assign({}, data)} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n  behaviors: ['hover-activate'],\n});\n\ngraph.render();\n```\n\n#### 自定义业务状态\n\n当需要管理业务相关状态（如审批状态、风险等级）时，可通过扩展节点数据实现：\n\n**示例**：通过 data 添加 `selected` 变量，实现节点选中和取消选中的样式变化。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst MyVueNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleClick = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: !isSelected.value } }]);\n      graph.draw();\n    };\n\n    return (\n      <div\n        style={{\n          width: 200,\n          padding: 10,\n          border: '1px solid red',\n          borderColor: isSelected.value ? 'orange' : '#ddd', // 根据选中状态设置边框颜色\n          cursor: 'pointer', // 添加鼠标指针样式\n        }}\n        onClick={handleClick}\n      >\n        Node\n      </div>\n    );\n  },\n});\n\nconst graph = new Graph({\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        style: { x: 100, y: 100 },\n        data: { selected: true },\n      },\n    ],\n  },\n  node: {\n    type: 'vue-node',\n    style: {\n      component: (data) => <MyVueNode data={Object.assign({}, data)} graph={graph} />, // data是非响应式数据，需要通过改变引用来触发Vue的props副作用\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 事件交互\n\n实现节点与图实例的双向通信，使节点和图实例可以相互更新。\n\n**示例**：通过自定义节点操作图数据，并重新渲染图形。\n\n```jsx\nimport { ExtensionCategory, register, Graph } from '@antv/g6';\nimport { VueNode } from 'g6-extension-vue';\nimport { defineComponent, computed } from 'vue';\n\nregister(ExtensionCategory.NODE, 'vue-node', VueNode);\n\nconst IDCardNode = defineComponent({\n  setup(props, { attrs, slots, expose }) {\n    const isSelected = computed(() => props.data.data.selected);\n\n    const handleSelect = () => {\n      graph.updateNodeData([{ id: props.data.id, data: { selected: true } }]);\n      graph.draw();\n    };\n\n    return <Select onChange={handleSelect} style={{ background: isSelected.value ? 'orange' : '#eee' }} />;\n  },\n});\n\nconst graph = new Graph({\n  node: {\n    type: 'vue-node',\n    style: {\n      component: ({ id, data }) => <IDCardNode id={id} selected={isSelected.value} graph={graph} />,\n    },\n  },\n});\n```\n\n\n<!-- Skill/Rule: Element Skill (packages/site/docs/manual/element/overview.en.md) -->\n---\ntitle: Element Overview\norder: 1\n---\n\n## Element System\n\nThe core of G6 charts is composed of three basic elements: **Node**, **Edge**, and **Combo**. These elements are the fundamental units for building complex graphical networks.\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### Node\n\n[Nodes](/en/manual/element/node/overview) represent entities or concepts in the graph, such as people, places, objects, etc. G6 provides a rich set of built-in node types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 also supports [defining nodes using React](/en/manual/element/node/react-node) or [custom nodes](/en/manual/element/node/custom-node) to meet specific needs.\n\n### Edge\n\n[Edges](/en/manual/element/edge/overview) represent the connections between nodes, such as friendships, transactions, etc. G6 has multiple built-in edge types:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nWhen built-in edges do not meet the requirements, complex connection expressions can be achieved through [custom edges](/en/manual/element/edge/custom-edge).\n\n### Combo\n\n[Combos](/en/manual/element/combo/overview) are special elements that can contain nodes and other combos, used to represent collections, groups, or hierarchical relationships. G6 has two built-in combo types:\n\n- **Circle Combo**(`circle`): Suitable for compact grouping\n- **Rectangle Combo**(`rect`): Suitable for regular layout grouping\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\nCombos support nesting, dragging, expanding/collapsing, and other interactions, and more complex container behaviors can be achieved through [custom combos](/en/manual/element/combo/custom-combo).\n\n## Element Composition Principle\n\nEach element is composed of one or more basic shapes. Shapes are the smallest graphical units in G6, including [rectangle](/en/manual/element/shape/properties#rectstyleprops), [circle](/en/manual/element/shape/properties#circlestyleprops), [text](/en/manual/element/shape/properties#textstyleprops), [path](/en/manual/element/shape/properties#pathstyleprops), etc.\n\nFor example:\n\n- A node may consist of a background shape (such as a circle) and a text label\n- An edge may consist of a path, arrow, and text label\n- A combo may consist of a container shape, title text, and expand/collapse button\n\nFor more information about shapes, see [Shape Overview](/en/manual/element/shape/overview) and [Shape Style Properties](/en/manual/element/shape/properties).\n\n## Element State\n\n[Element State](/en/manual/element/state) is a powerful mechanism for displaying visual changes of elements in different interactions or business scenarios. G6 provides a complete state management system:\n\n- **Preset States**: `selected`, `highlight`, `active`, etc.\n- **State Overlay**: Elements can have multiple states simultaneously, with styles overlaying according to priority\n- **Custom States**: Any state can be defined according to business needs\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Configure Elements\n\nG6 5.x adopts a flat configuration structure, where all element configurations are at the same level, making it easy to find and manage:\n\n```typescript\n{\n  node: {\n    // Default node style\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // Node styles in different states\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // Default edge style\n    style: {\n      stroke: '#aaa',\n    },\n    // Edge styles in different states\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // Default combo style\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\nThere are three configuration methods, in order of priority from high to low:\n\n1. **Dynamic configuration using instance methods**: such as `graph.setNode()`, `graph.setEdge()`, `graph.setCombo()`\n2. **Global configuration when instantiating the graph**: specify configuration items in `new Graph()`\n3. **Configuration in data**: set in the data objects of nodes, edges, and combos\n\nIn editors like VSCode, you can see all configurable properties of elements and search based on keywords:\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Extension Capabilities\n\nG6 provides powerful extension capabilities to meet various customization needs:\n\n- **Custom Nodes**: [Custom Node Guide](/en/manual/element/node/custom-node)\n- **Custom Edges**: [Custom Edge Guide](/en/manual/element/edge/custom-edge)\n- **Custom Combos**: [Custom Combo Guide](/en/manual/element/combo/custom-combo)\n- **React Nodes**: [Define Nodes Using React](/en/manual/element/node/react-node)\n- **3D Extension**: Use 3D nodes through `@antv/g6-extension-3d`\n\n## Built-in Element Reference\n\n### Node Types\n\n- [Built-in Node Library](/en/manual/element/node/base-node)\n\n### Edge Types\n\n- [Built-in Edge Library](/en/manual/element/edge/base-edge)\n\n### Combo Types\n\n- [Built-in Combo Library](/en/manual/element/combo/base-combo)\n\n\n<!-- Skill/Rule: Element Skill (packages/site/docs/manual/element/overview.zh.md) -->\n---\ntitle: 元素总览\norder: 1\n---\n\n## 元素体系\n\nG6 图表的核心是由三种基本元素构成：**节点(Node)**、**边(Edge)** 和 **组合(Combo)**。这些元素是构建复杂图形网络的基础单元。\n\n<image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2ZewT4T1p_4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 节点 (Node)\n\n[节点](/manual/element/node/overview) 表示图中的实体或概念，如人物、地点、对象等。G6 提供了丰富的内置节点类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\nG6 还支持 [使用 React 定义节点](/manual/element/node/react-node) 或 [自定义节点](/manual/element/node/custom-node) 以满足特定需求。\n\n### 边 (Edge)\n\n[边](/manual/element/edge/overview)表示节点间的连接关系，如朋友关系、交易往来等。G6 内置多种边类型：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YKN7TasqOh4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n当内置边不满足需求时，可以通过 [自定义边](/manual/element/edge/custom-edge) 来实现复杂的连接表现。\n\n### 组合 (Combo)\n\n[组合](/manual/element/combo/overview)是一种特殊元素，可以包含节点和其他组合，用于表示集合、分组或层级关系。G6 内置两种组合类型：\n\n- **圆形组合**(`circle`)：适合紧凑型分组\n- **矩形组合**(`rect`)：适合规则布局的分组\n\n<image width=\"450\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*zPAzSZ3XxpUAAAAAAAAAAAAADmJ7AQ/original\" />\n\n组合支持嵌套、拖拽、展开/收起等交互，可以通过 [自定义组合](/manual/element/combo/custom-combo) 来实现更复杂的容器行为。\n\n## 元素构成原理\n\n每个元素由一个或多个基础图形(Shape)组成。图形是 G6 中的最小图形单元，包括 [矩形](/manual/element/shape/properties#rectstyleprops)、[圆形](/manual/element/shape/properties#circlestyleprops)、[文本](/manual/element/shape/properties#textstyleprops)、[路径](/manual/element/shape/properties#pathstyleprops)等。\n\n例如：\n\n- 一个节点可能由背景图形(如圆形)和文本标签组成\n- 一条边可能由路径、箭头和文本标签组成\n- 一个组合可能由容器图形、标题文本和展开/收起按钮组成\n\n要了解更多关于图形的信息，请参阅 [图形 Shape 总览](/manual/element/shape/overview) 和 [Shape 样式属性](/manual/element/shape/properties)。\n\n## 元素状态\n\n[元素状态](/manual/element/state) 是一种强大的机制，用于展示元素在不同交互或业务场景下的视觉变化。G6 提供了一套完整的状态管理系统：\n\n- **预设状态**：`selected`(选中)、`highlight`(高亮)、`active`(激活)等\n- **状态叠加**：元素可同时拥有多个状态，样式按优先级叠加\n- **自定义状态**：可根据业务需求定义任意状态\n\n<image width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 配置元素\n\nG6 5.x 采用扁平化的配置结构，所有元素的配置都在同一层级，便于查找和管理：\n\n```typescript\n{\n  node: {\n    // 节点默认样式\n    style: {\n      fill: 'orange',\n      labelText: 'node',\n    },\n    // 节点在不同状态下的样式\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      }\n    }\n  },\n  edge: {\n    // 边默认样式\n    style: {\n      stroke: '#aaa',\n    },\n    // 边在不同状态下的样式\n    state: {\n      highlight: {\n        stroke: 'red',\n      }\n    }\n  },\n  combo: {\n    // 组合默认样式\n    style: {\n      fill: 'lightblue',\n      stroke: 'blue',\n    }\n  }\n};\n```\n\n配置方式有三种，按优先级从高到低：\n\n1. **使用实例方法动态配置**：如 `graph.setNode()`、`graph.setEdge()`、`graph.setCombo()`\n2. **实例化图时全局配置**：在 `new Graph()` 时指定配置项\n3. **在数据中配置**：在节点、边、组合的数据对象中设置\n\n在 VSCode 等编辑器中，你可以看到元素的全部可配置属性，并基于关键字进行搜索：\n\n<image width=\"800\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oY_uTK80sIoAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 扩展能力\n\nG6 提供了强大的扩展能力，满足各种自定义需求：\n\n- **自定义节点**：[自定义节点指南](/manual/element/node/custom-node)\n- **自定义边**：[自定义边指南](/manual/element/edge/custom-edge)\n- **自定义组合**：[自定义组合指南](/manual/element/combo/custom-combo)\n- **React 节点**：[使用 React 定义节点](/manual/element/node/react-node)\n- **3D 扩展**：通过 `@antv/g6-extension-3d` 使用 3D 节点\n\n## 内置元素参考\n\n### 节点类型\n\n- [内置节点库](/manual/element/node/base-node)\n\n### 边类型\n\n- [内置边库](/manual/element/edge/base-edge)\n\n### 组合类型\n\n- [内置组合库](/manual/element/combo/base-combo)\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/label-shape.en.md) -->\n---\ntitle: Design and Implementation of Composite Shape\norder: 3\n---\n\nG6 provides a flexible Shape mechanism, allowing developers to customize various graphics and efficiently reuse them in elements such as nodes, edges, and combos. This article uses Label as an example to explain how to customize a Shape and how to apply it in elements.\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 1. Customization and Encapsulation of Shape\n\n### 1. Base Class Design of Shape\n\nAll Shapes inherit from `BaseShape`, which centrally manages the lifecycle (creation, update, destruction), property parsing, animation, event binding, etc. You only need to focus on implementing the `render` method.\n\n**Core Abstraction:**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // Lifecycle management, property parsing, animation, etc...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. Hierarchical Structure of Composite Shape\n\nA node usually contains multiple child Shapes, for example:\n\n```\nNode\n├── keyShape (main shape)\n├── label (label, auxiliary information)\n│   ├── text\n│   └── rect\n├── icon\n│   ├── text\n│   └── image\n├── badge\n│   ├── text\n│   └── rect\n└── port\n│   ├── circle\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Implementation of Label Shape\n\nLabel is a typical composite Shape, consisting of text (Text) and an optional background (Rect). The implementation idea is as follows:\n\n- **Property Separation**: The style properties of Label are divided into text style and background style, which are passed to Text and Rect respectively.\n- **Smart Layout**: The background automatically adjusts its size and position based on the text content, padding, border radius, etc.\n- **Reuse upsert**: The `upsert` method is used to automatically manage the creation, update, and destruction of child Shapes.\n\n**Main code snippet of Label:**\n\n```js\nimport { Text, Rect } from '@antv/g'; // Import atomic graphics\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... Omitted style extraction methods\n}\n```\n\n- `getTextStyle` and `getBackgroundStyle` extract the style properties for text and background respectively to avoid interference.\n- The `upsert` method ensures automatic CRUD of Shapes, greatly improving reusability and robustness.\n\n### 4. Complete Custom Shape Example\n\nBelow is an example of customizing a label with special decoration, demonstrating the complete definition, registration, and usage of a Shape:\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // Main text\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // Background\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // Extra decoration: small dot on the left\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...implement getTextStyle/getBackgroundStyle\n}\n\n// Register custom Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// Define custom node\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// Register custom node\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 2. Prefix Separation of Style Properties\n\nIn G6, elements such as nodes, edges, and combos often contain multiple child Shapes (such as main shape, label, badge, port, etc.). To ensure that the style of each child Shape does not interfere with each other, G6 adopts a **prefix separation** design for style properties.\n\n### 1. Significance of Prefix Separation\n\n- **Decoupling**: Each child Shape only cares about its own style properties, avoiding style pollution.\n- **Easy Expansion**: Adding a new child Shape only requires defining a new prefix, without modifying the original logic.\n- **Intuitive Configuration**: When configuring nodes/edges/combos, users can clearly set the style of each part.\n\n### 2. Code Implementation\n\nTake Label as an example:\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` means all properties starting with `background` belong to the label background style.\n- During rendering, tools such as `subStyleProps` and `subObject` are used to automatically extract prefixed styles and pass them to the corresponding Shape.\n\n**Label background style extraction example**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...Omitted layout calculation\n  return backgroundStyle;\n}\n```\n\n**Style configuration example**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 3. Relationship between Label and keyShape\n\n- **keyShape** is the main shape of a node/edge/combo, determining interaction picking, bounding box, main style, etc.\n- **Label**, icon, badge, port, etc. usually exist as auxiliary Shapes and are not used as keyShape.\n- When customizing a node, you can specify the keyShape via `drawKeyShape` or similar methods. Label is only responsible for displaying text information and does not affect the main interaction control of the node.\n\n## 4. How to Apply Custom Shape in Elements\n\nTake nodes as an example. The node base class `BaseNode` has built-in support for multiple child Shapes (keyShape, label, icon, badge, port, halo, etc.). You only need to focus on drawing the keyShape, and other child Shapes can be automatically managed through configuration and style prefixing.\n\n### 1. Node Rendering Process\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. Draw keyShape (main shape)\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. Draw halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. Draw icon\n  this.drawIconShape(attributes, container);\n\n  // 4. Draw badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. Draw label\n  this.drawLabelShape(attributes, container);\n\n  // 6. Draw ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- The style of each child Shape is automatically extracted by prefix separation and passed to the corresponding Shape instance.\n- You can flexibly control the display and style of each child Shape through configuration options.\n\n### 2. Example of Applying Label\n\nSuppose you want to add a label with a background to a node, just configure the label-related properties in the node data:\n\n```js\n{\n  label: true,\n  labelText: 'I am a label',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`, `labelFill`, `labelFontSize`, etc. will be automatically extracted and passed to the text part of the Label.\n- `labelBackground`, `labelBackgroundFill`, `labelBackgroundRadius`, `labelPadding`, etc. will be automatically extracted and passed to the background part of the Label.\n\nYou do not need to manually manage the creation, update, or destruction of the Label. G6 will handle it automatically.\n\n## 5. Common Issues and Debugging Suggestions\n\n### 1. Why is the label style not effective?\n\n- Check whether the style property prefix is correct (such as `labelFill`, `labelBackgroundFill`).\n- Make sure the `label` configuration of the node/edge/combo is `true` and `labelText` is set.\n- Check if it is overridden by other styles.\n\n### 2. How to debug the rendering of custom Shape?\n\n- Use the browser console to view `shapeMap` and confirm whether each child Shape is created correctly.\n\n### 3. How to make Label respond to node states (such as hover, selected)?\n\n- Directly set node state styles in the graph configuration (recommended)\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- Or listen for state changes in the implementation of Label and dynamically adjust the style. You can get the current state value through data.\n\n---\n\nFor more details, it is recommended to read the source code [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts), [`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts).\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/label-shape.zh.md) -->\n---\ntitle: 复合 Shape 的设计与实现\norder: 3\n---\n\nG6 提供了灵活的 Shape 机制，支持开发者自定义各种图形，并在节点、边、Combo 等元素中高效复用。本文将以 Label（标签）为例，讲解如何自定义 Shape、如何在元素中应用。\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*W3oqSYPZtWEAAAAAAAAAAAAAemJ7AQ/original\" width=\"80\" />\n\n## 一、Shape 的自定义与封装\n\n### 1. Shape 的基类设计\n\n所有 Shape 都继承自 `BaseShape`，它统一管理了 Shape 的生命周期（创建、更新、销毁）、属性解析、动画、事件绑定等。你只需关注如何实现 `render` 方法即可。\n\n**核心抽象：**\n\n```js\nimport { CustomElement } from '@antv/g';\n\nabstract class BaseShape extends CustomElement {\n  // 生命周期管理、属性解析、动画等...\n  public abstract render(attributes, container): void;\n}\n```\n\n### 2. 复合 Shape 层级结构示意\n\n一个节点通常包含多个子 Shape，例如：\n\n```\n节点（Node）\n├── keyShape（主图形）\n├── label（标签，辅助信息）\n│   ├── text（文本）\n│   └── rect（背景）\n├── icon（图标）\n│   ├── text（文本）\n│   └── image（图片）\n├── badge（徽标）\n│   ├── text（文本）\n│   └── rect（背景）\n└── port（锚点）\n│   ├── circle（圆形）\n```\n\n<img width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Ot4bSbBx97EAAAAAAAAAAAAADmJ7AQ/original\" />\n\n### 3. Label Shape 的实现\n\nLabel 是一个典型的复合 Shape，由文本（Text）和可选的背景（Rect）组成。其实现思路如下：\n\n- **属性分离**：Label 的样式属性分为文本样式和背景样式，分别传递给 Text 和 Rect。\n- **智能布局**：背景自动根据文本内容、内边距、圆角等动态调整尺寸和位置。\n- **复用 upsert**：通过 `upsert` 方法自动管理子 Shape 的创建、更新、销毁。\n\n**Label 主要代码片段：**\n\n```js\nimport { Text, Rect } from '@antv/g'; // 引入原子图形\n\nexport class Label extends BaseShape {\n  public render(attributes = this.parsedAttributes, container= this): void {\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n  }\n  // ... 省略样式提取方法\n}\n```\n\n- `getTextStyle`、`getBackgroundStyle` 分别提取文本和背景的样式属性，避免相互干扰。\n- `upsert` 方法保证了 Shape 的自动增删改查，极大提升了复用性和健壮性。\n\n### 4. 完整自定义 Shape 示例\n\n下面以自定义一个带特殊装饰的标签为例，演示 Shape 的完整定义、注册与使用：\n\n```js\nimport { BaseShape, ExtensionCategory, Circle } from 'g6';\nimport { Text, Rect, Circle } from '@antv/g';\n\nclass FancyLabel extends BaseShape {\n  render(attributes = this.parsedAttributes, container = this) {\n    // 主文本\n    this.upsert('text', Text, this.getTextStyle(attributes), container);\n    // 背景\n    this.upsert('background', Rect, this.getBackgroundStyle(attributes), container);\n    // 额外装饰：左侧小圆点\n    this.upsert('dot', Circle, {\n      x: -8, y: 0, r: 3, fill: '#faad14',\n    }, container);\n  }\n  // ...实现 getTextStyle/getBackgroundStyle\n}\n\n// 注册自定义 Shape\nregister(ExtensionCategory.SHAPE, 'fancy-label-shape', FancyLabel);\n\n// 定义自定义节点\nclass CustomCircle extends Circle {\n  public drawFancyLabelShape(attributes, container) {\n    this.upsert('fancy-label', 'fancy-label-shape', this.getFancyLabelStyle(attributes), container);\n  }\n\n  render(attributes = this.parsedAttributes, container) {\n    super.render(attributes, container);\n\n    this.drawFancyLabelShape(attributes, container);\n  }\n}\n\n// 注册自定义节点\nregister(ExtensionCategory.Node, 'fancy-label-node', CustomCircle);\n```\n\n## 二、样式属性的前缀分离\n\nG6 中节点、边、Combo 等元素往往包含多个子 Shape（如主图形、标签、徽标、锚点等）。为了让每个子 Shape 的样式互不干扰，G6 采用了**样式属性前缀分离**的设计。\n\n### 1. 前缀分离的意义\n\n- **解耦**：每个子 Shape 只关心属于自己的样式属性，避免样式污染。\n- **易扩展**：新增子 Shape 只需定义新的前缀，无需修改原有逻辑。\n- **配置直观**：用户在配置节点/边/Combo 时，可以一目了然地设置各部分样式。\n\n### 2. 代码实现\n\n以 Label 为例：\n\n```ts\nimport { RectStyleProps, TextStyleProps } from '@antv/g';\n\ntype PrefixKey<P extends string = string, K extends string = string> = `${P}${Capitalize<K>}`;\n\ntype Prefix<P extends string, T extends object> = {\n  [K in keyof T as K extends string ? PrefixKey<P, K> : never]?: T[K];\n};\n\ninterface LabelStyleProps extends TextStyleProps, Prefix<'background', RectStyleProps> {\n  background?: boolean;\n}\n```\n\n- `Prefix<'background', RectStyleProps>` 表示所有以 `background` 开头的属性都属于标签背景样式。\n- 在实际渲染时，通过 `subStyleProps`、`subObject` 等工具函数，自动提取带前缀的样式，传递给对应的 Shape。\n\n**Label 背景样式提取示例**\n\n```js\nprotected getBackgroundStyle(attributes: Required<LabelStyleProps>) {\n  if (attributes.background === false) return false;\n  const style = this.getGraphicStyle(attributes);\n  const backgroundStyle = subStyleProps<RectStyleProps>(style, 'background');\n// ...省略布局计算\n  return backgroundStyle;\n}\n```\n\n**样式配置示例**\n\n```json\n{\n  \"text\": \"label\",\n  \"fontSize\": 12,\n  \"fontFamily\": \"system-ui, sans-serif\",\n  \"wordWrap\": true,\n  \"maxLines\": 1,\n  \"wordWrapWidth\": 128,\n  \"textOverflow\": \"...\",\n  \"textBaseline\": \"middle\",\n  \"background\": true,\n  \"backgroundOpacity\": 0.75,\n  \"backgroundZIndex\": -1,\n  \"backgroundLineWidth\": 0\n}\n```\n\n## 三、Label 与 keyShape 的关系\n\n- **keyShape** 是节点/边/Combo 的主图形，决定交互拾取、包围盒、主样式等。\n- **Label**、icon、badge、port 等通常作为辅助 Shape 存在，不会作为 keyShape。\n- 你可以在自定义节点时通过 `drawKeyShape` 或类似方法指定 keyShape，Label 只负责展示文本信息，不影响节点的交互主控。\n\n## 四、如何在元素中应用自定义 Shape\n\n以节点为例，节点基类 `BaseNode` 已经内置了对多种子 Shape 的支持（keyShape、label、icon、badge、port、halo 等）。你只需专注于 keyShape 的绘制，其他子 Shape 可以通过配置和样式前缀自动管理。\n\n### 1. 节点渲染流程\n\n```js\nprotected drawLabelShape(attributes: Required<S>, container: Group): void {\n  const style = this.getLabelStyle(attributes);\n  this.upsert('label', Label, style, container);\n}\n\npublic render(attributes = this.parsedAttributes, container: Group = this) {\n  // 1. 绘制 keyShape（主图形）\n  this._drawKeyShape(attributes, container);\n  if (!this.getShape('key')) return;\n\n  // 2. 绘制 halo\n  this.drawHaloShape(attributes, container);\n\n  // 3. 绘制 icon\n  this.drawIconShape(attributes, container);\n\n  // 4. 绘制 badges\n  this.drawBadgeShapes(attributes, container);\n\n  // 5. 绘制 label\n  this.drawLabelShape(attributes, container);\n\n  // 6. 绘制 ports\n  this.drawPortShapes(attributes, container);\n}\n```\n\n- 每个子 Shape 的样式都通过前缀分离自动提取，传递给对应的 Shape 实例。\n- 你可以通过配置项灵活控制每个子 Shape 的显示与样式。\n\n### 2. 应用 Label 的示例\n\n假设你要为节点添加带背景的标签，只需在节点数据中配置 label 相关属性：\n\n```js\n{\n  label: true,\n  labelText: '我是标签',\n  labelFill: '#333',\n  labelFontSize: 14,\n  labelBackground: true,\n  labelBackgroundFill: '#fffbe6',\n  labelBackgroundRadius: 6,\n  labelPadding: [4, 8],\n}\n```\n\n- `labelText`、`labelFill`、`labelFontSize` 等会被自动提取并传递给 Label 的文本部分。\n- `labelBackground`、`labelBackgroundFill`、`labelBackgroundRadius`、`labelPadding` 等会被自动提取并传递给 Label 的背景部分。\n\n你无需手动管理 Label 的创建、更新、销毁，G6 会自动完成。\n\n## 五、常见问题与调试建议\n\n### 1. 为什么 label 样式没有生效？\n\n- 检查样式属性前缀是否正确（如 `labelFill`、`labelBackgroundFill`）。\n- 确认节点/边/Combo 的 `label` 配置为 `true`，且 `labelText` 已设置。\n- 检查是否被其他样式覆盖。\n\n### 2. 如何调试自定义 Shape 的渲染？\n\n- 使用浏览器控制台查看 `shapeMap`，确认各子 Shape 是否被正确创建。\n\n### 3. 如何让 Label 响应节点状态（如 hover、selected）？\n\n- 直接在图配置中设置节点状态样式（推荐）\n\n```js\nconst graph = new Graph({\n  node: {\n    style: {\n      label: false,\n    },\n    state: {\n      hover: {\n        label: true,\n        labelText: 'show when hovered',\n      },\n    },\n  },\n});\n```\n\n- 或者在 Label 的实现中监听状态变化，动态调整样式。可以通过 data 获取到当前的状态值\n\n---\n\n如需更深入了解，建议阅读源码 [`base-shape.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-shape.ts)、[`base-node.ts`](https://github.com/antvis/G6/blob/v5/packages/g6/src/elements/shapes/base-node.ts)。\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/overview.en.md) -->\n---\ntitle: Shape and KeyShape\norder: 1\n---\n\n## Shape\n\nA Shape in G6 refers to a graphical element, such as a circle, rectangle, or path. Shapes are generally associated with nodes, edges, or combos in G6. **💡 Every node/edge/combo in G6 is composed of one or more shapes. The style configuration of nodes, edges, and combos is reflected on their corresponding shapes.**\n\nFor example, in the images below: the node on the left contains a single circular shape; the node in the middle contains a circle and a text shape; the node on the right contains five circles (the blue-green main circle and four anchor points at the top, bottom, left, and right) and a text shape. Each node/edge/combo has its unique key shape (keyShape). In the examples below, the keyShape for all three nodes is the blue-green circle. The keyShape is mainly used for interaction detection and automatic style updates with [element states](/en/manual/element/state), see [keyShape](#keyshape).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> (Left) A node with only one circular shape, whose keyShape is the circle. (Middle) A node with a circle and a text shape, whose keyShape is the circle. (Right) A node with a main circle, text, and four small circles at the top, bottom, left, and right, whose keyShape is the main circle.\n\nG6 uses different combinations of shapes to design various built-in nodes/edges/combos. Built-in nodes include 'circle', 'rect', 'ellipse', ... (see [Built-in Nodes](/en/manual/element/node/base-node)); built-in edges include 'line', 'polyline', 'cubic', ... (see [Built-in Edges](/en/manual/element/edge/base-edge)); built-in combos include 'circle', 'rect', ... (see [Built-in Combos](/en/manual/element/combo/base-combo)).\n\nIn addition to using built-in nodes/edges/combos, G6 also allows users to customize nodes/edges/combos by combining shapes as needed. See [Custom Node](/en/manual/element/node/custom-node), [Custom Edge](/en/manual/element/edge/custom-edge), and [Custom Combo](/en/manual/element/combo/custom-combo) for details.\n\n## KeyShape\n\nIn G6, each node, edge, or combo consists of one or more shapes, but one of them is called the keyShape, which is the \"key graphical element\" of the item:\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> The key graphical element of the node is the colored area in the image above.\n\n### Bounding Box Determination\n\n**Determines the bounding box of a node/combo**, which is used to calculate the connection point of related edges (the intersection with the edge). If the keyShape is different, the intersection calculation between the node and the edge will also differ.\n\n#### Example\n\nIn this example, a node consists of a rect shape and a circle shape with a gray stroke and transparent fill.\n\n- When the node's keyShape is the circle:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- When the node's keyShape is the rect:\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape Lifecycle\n\n> If you need to [customize nodes](/en/manual/element/node/custom-node), [customize edges](/en/manual/element/edge/custom-edge), or [customize combos](/en/manual/element/combo/custom-combo), you need to understand the lifecycle of shapes. If you use built-in nodes/edges/combos, you can skip this section.\n\nThe shape lifecycle includes:\n\n- **Initial Rendering**: Draws the shape for the first time based on data and style configuration.\n- **Update**: Automatically updates the appearance of the shape when data or style changes.\n- **Operation**: Responds to interaction states (such as selected, active, hover, etc.) and dynamically adjusts the style.\n- **Destruction**: Cleans up when the shape is removed (usually managed automatically by the Graph, so users don't need to worry).\n\nWhen customizing shapes, the most common requirement is \"how to efficiently manage the creation, update, and destruction of shapes.\" For this, G6 provides a very useful method in BaseShape:\n\n### Principle and Advantages of upsert\n\nupsert is a combination of \"update\" and \"insert\", meaning \"update if exists, insert if not\". Its function can be simply understood as:\n\n- **Automatic Judgment**: You only need to describe the desired appearance of the shape. `upsert` will automatically determine whether the shape already exists. If not, it will create it; if it exists, it will update it; if it needs to be deleted, it will remove it automatically.\n- **Simplified Logic**: Developers do not need to manually manage the CRUD of shapes, avoiding duplicate code and state confusion.\n- **Improved Robustness**: Whether it's the initial rendering, data changes, or state switching, upsert ensures that the shape always stays in sync with the data and configuration.\n\n**Type Definition:**\n\n```js\n/**\n * Create, update, or delete a shape\n * @param className Shape name\n * @param Ctor Shape type\n * @param style Shape style. Pass false to delete the shape\n * @param container Container\n * @param hooks Hooks\n * @returns Shape instance\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\nYou only need to describe \"what kind of shape you want now\" without worrying about whether it is being created, updated, or deleted. upsert will handle it for you. This makes customizing and managing complex composite shapes very simple and safe.\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/overview.zh.md) -->\n---\ntitle: 图形 Shape 与 KeyShape\norder: 1\n---\n\n## 图形 Shape\n\nShape 指 G6 中的图形、形状，可以是圆形、矩形、路径等。它一般与 G6 中的节点、边、Combo 相关。**💡 G6 中的每一种节点/边/Combo 都是由一个或多个 Shape 组合而成。节点、边、Combo 的样式配置都会被体现到对应的图形上。**\n\n例如下图（左）的节点包含了一个圆形图形；下图（中）的节点含有一个圆形和一个文本图形；下图（右）的节点中含有 5 个圆形（蓝绿色的圆和上下左右四个锚点）、一个文本图形。但每种节点/边/Combo 都会有自己的唯一关键图形 keyShape，下图中三个节点的 keyShape 都是蓝绿色的圆，keyShape 主要用于交互检测、样式随 [元素状态](/manual/element/state) 自动更新等，见 [keyShape](#keyshape)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*OcaaTIIu_4cAAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*r5M0Sowd1R8AAAAAAAAAAABkARQnAQ' width=50 alt='img'/><img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*pHoETad75CIAAAAAAAAAAABkARQnAQ' width=50 alt='img'/>\n\n> （左）只含有一个圆形图形的节点，keyShape 是该圆形。（中）含有圆形和文本图形的节点，keyShape 是圆形。（右）含有主要圆形、文本、上下左右四个小圆形的节点，keyShape 是圆形。\n\nG6 使用不同的 shape 组合，设计了多种内置的节点/边/ Combo 。G6 内置节点的有 'circle'， 'rect'，'ellipse'，...（详见 [内置节点](/manual/element/node/base-node)）；内置边的有 'line'，'polyline'，'cubic'，...（详见 [内置边](/manual/element/edge/base-edge)）；内置 Combo 有 'circle'，'rect'，（详见 [内置 Combo](/manual/element/combo/base-combo)）。\n\n除了使用内置的节点/边/ Combo 外，G6 还允许用户通过自己搭配和组合 shape 进行节点/边/ Combo 的自定义，详见 [自定义节点](/manual/element/node/custom-node)，[自定义边](/manual/element/edge/custom-edge)，[自定义 Combo](/manual/element/combo/custom-combo)。\n\n## KeyShape\n\n在 G6 中，每个节点、边、Combo 都由一个或多个 Shape 组成，但其中有一个 Shape 被称为 keyShape，它是该元素的“关键图形”：\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*TZt2S7Z0d-8AAAAAAAAAAAAADmJ7AQ/original\" />\n\n> 节点的关键图形就是上图的颜色区域\n\n### 包围盒确定\n\n**确定节点 / Combo 的包围盒（Bounding Box）** ，从而计算相关边的连入点（与相关边的交点）。若 keyShape 不同，节点与边的交点计算结果不同。\n\n#### 示例  \n\n本例中的一个节点由一个 rect 图形和一个带灰色描边、填充透明的 circle 图形构成。\n\n- 当节点的 keyShape 为 circle 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*CY7cSaMs4U0AAAAAAAAAAABkARQnAQ' width=220 alt='img'/>\n\n- 当节点的 keyShape 为 rect 时：\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*upWTQLTvxGEAAAAAAAAAAABkARQnAQ' width=250 alt='img'/>\n\n## Shape 的生命周期\n\n> 当用户需要 [自定义节点](/manual/element/node/custom-node)、[自定义边](/manual/element/edge/custom-edge)、[自定义 Combo](/manual/element/combo/custom-combo) 时，需要了解 Shape 的生命周期。使用内置节点/边/Combo 则可以跳过这一部分内容。\n\n从整体来看，Shape 的生命周期分为：\n\n- **初始化渲染**：首次根据数据和样式配置绘制出 Shape。\n- **更新**：当数据或样式发生变化时，自动更新 Shape 的表现。\n- **操作**：响应交互状态（如 selected、active、hover 等），动态调整样式。\n- **销毁**：Shape 被移除时的清理（通常由 Graph 自动管理，用户无需关心）。\n\n在自定义 Shape 时，最常见的需求就是“如何高效地管理 Shape 的创建、更新和销毁”。G6 为此在 BaseShape 中设计了一个非常实用的方法：\n\n### upsert 的原理与优势\n\nupsert 是“update” 和 “insert” 的合成词，意思是“有则更新，无则创建”。它的作用可以简单理解为：\n\n- **自动判断**：你只需描述希望 Shape 呈现的样子，`upsert` 会自动判断当前 Shape 是否已存在。如果不存在则创建，如果已存在则更新，如果需要删除则自动移除。\n- **简化逻辑**：开发者无需手动管理 Shape 的增删改查，避免了重复代码和状态混乱。\n- **提升健壮性**：无论是初次渲染、数据变更还是状态切换，upsert 都能保证 Shape 始终与数据和配置保持同步。\n\n**类型定义：**\n\n```js\n/**\n * 创建、更新或删除图形\n * @param className 图形名称\n * @param Ctor 图形类型\n * @param style 图形样式。若要删除图形，传入 false\n * @param container 容器\n * @param hooks 钩子函数\n * @returns 图形实例\n */\nupsert<T extends DisplayObject>(\n  className: string,\n  Ctor: string | { new (...args: any[]): T },\n  style: T['attributes'] | false,\n  container: DisplayObject,\n  hooks?: UpsertHooks,\n): T | undefined {}\n```\n\n你只需要描述“我现在想要什么样的图形”，不用关心它是新建、更新还是删除，upsert 都会帮你处理好。这让自定义和管理复杂的复合 Shape 变得非常简单和安全。\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/properties.en.md) -->\n---\ntitle: Atomic Shapes and Their Properties\norder: 2\n---\n\nElements (nodes/edges) in G6 are composed of **one or more [shapes](/en/manual/element/shape/overview)**, mainly added via `upsert` in the `render` method when customizing nodes or edges. G6 supports the following shapes:\n\n1. [Circle](#circlestyleprops)\n2. [Ellipse](#ellipsestyleprops)\n3. [Rect](#rectstyleprops)\n4. [HTML Element](#htmlstyleprops)\n5. [Image](#imagestyleprops)\n6. [Line](#linestyleprops)\n7. [Path](#pathstyleprops)\n8. [Polygon](#polygonstyleprops)\n9. [Polyline](#polylinestyleprops)\n10. [Text](#textstyleprops)\n\n## Common Properties of All Shapes\n\n### BaseShapeStyle\n\n| Property       | Description                                                                                      | Type                                     | Required |\n| -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------- | -------- |\n| x              | x coordinate                                                                                     | number                                   | ✓        |\n| y              | y coordinate                                                                                     | number                                   | ✓        |\n| width          | Width                                                                                            | number                                   | ✓        |\n| height         | Height                                                                                           | number                                   | ✓        |\n| fill           | Fill color                                                                                       | string \\| Pattern \\| null                |          |\n| stroke         | Stroke color                                                                                     | string \\| Pattern \\| null                |          |\n| opacity        | Overall opacity                                                                                  | number \\| string                         |          |\n| fillOpacity    | Fill opacity                                                                                     | number \\| string                         |          |\n| strokeOpacity  | Stroke opacity                                                                                   | number \\| string                         |          |\n| lineWidth      | Line width                                                                                       | number \\| string                         |          |\n| lineCap        | Line cap style                                                                                   | `butt` \\| `round` \\| `square`            |          |\n| lineJoin       | Line join style                                                                                  | `miter` \\| `round` \\| `bevel`            |          |\n| lineDash       | Dash array                                                                                       | number \\| string \\| (string \\| number)[] |          |\n| lineDashOffset | Dash offset                                                                                      | number                                   |          |\n| shadowBlur     | Shadow blur                                                                                      | number                                   |          |\n| shadowColor    | Shadow color                                                                                     | string                                   |          |\n| shadowOffsetX  | Shadow X offset                                                                                  | number                                   |          |\n| shadowOffsetY  | Shadow Y offset                                                                                  | number                                   |          |\n| cursor         | Mouse cursor, supports all [CSS cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) | string                                   |          |\n| zIndex         | Render z-index                                                                                   | number                                   |          |\n| visibility     | Visibility                                                                                       | `visible` \\| `hidden`                    |          |\n\n**Example:**\n\n```js\nconst shape = BaseShape.upsert(\n  // Specify the shape key, which must be unique within the same custom element type\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Common Methods of All Shapes\n\n### attr()\n\nSet or get the drawing attributes of the instance.\n\n### attr(name)\n\nGet the value of an attribute.\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\nUpdate a single drawing attribute.\n\n### attr({...})\n\nBatch update drawing attributes.\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## Circle Shape\n\n### CircleStyleProps\n\n| Property          | Description                               | Type             | Required |\n| ----------------- | ----------------------------------------- | ---------------- | -------- |\n| cx                | Center x coordinate                       | number \\| string | ✓        |\n| cy                | Center y coordinate                       | number \\| string | ✓        |\n| cz                | Center z coordinate                       | number \\| string |          |\n| r                 | Radius                                    | number \\| string | ✓        |\n| isBillboard       | Billboard mode (always faces camera)      | boolean          |          |\n| isSizeAttenuation | Size attenuation (size changes with view) | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Rect Shape\n\n### RectStyleProps\n\n| Property          | Description       | Type                         | Required |\n| ----------------- | ----------------- | ---------------------------- | -------- |\n| x                 | Rect x coordinate | number \\| string             |          |\n| y                 | Rect y coordinate | number \\| string             |          |\n| z                 | Rect z coordinate | number                       |          |\n| width             | Rect width        | number \\| string             | ✓        |\n| height            | Rect height       | number \\| string             | ✓        |\n| isBillboard       | Billboard mode    | boolean                      |          |\n| isSizeAttenuation | Size attenuation  | boolean                      |          |\n| radius            | Border radius     | number \\| string \\| number[] |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## Ellipse Shape\n\n### EllipseStyleProps\n\n| Property          | Description         | Type             | Required |\n| ----------------- | ------------------- | ---------------- | -------- |\n| cx                | Center x coordinate | number \\| string | ✓        |\n| cy                | Center y coordinate | number \\| string | ✓        |\n| cz                | Center z coordinate | number \\| string |          |\n| rx                | X-axis radius       | number \\| string | ✓        |\n| ry                | Y-axis radius       | number \\| string | ✓        |\n| isBillboard       | Billboard mode      | boolean          |          |\n| isSizeAttenuation | Size attenuation    | boolean          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| Property  | Description       | Type                  | Required |\n| --------- | ----------------- | --------------------- | -------- |\n| x         | HTML x coordinate | number \\| string      |          |\n| y         | HTML y coordinate | number \\| string      |          |\n| innerHTML | HTML content      | string \\| HTMLElement | ✓        |\n| width     | HTML width        | number \\| string      |          |\n| height    | HTML height       | number \\| string      |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## Image Shape\n\n### ImageStyleProps\n\n| Property          | Description                      | Type                       | Required |\n| ----------------- | -------------------------------- | -------------------------- | -------- |\n| x                 | Image x coordinate               | number \\| string           |          |\n| y                 | Image y coordinate               | number \\| string           |          |\n| z                 | Image z coordinate               | number                     |          |\n| src               | Image source or HTMLImageElement | string \\| HTMLImageElement | ✓        |\n| width             | Image width                      | number \\| string           |          |\n| height            | Image height                     | number \\| string           |          |\n| isBillboard       | Billboard mode                   | boolean                    |          |\n| isSizeAttenuation | Size attenuation                 | boolean                    |          |\n| billboardRotation | Billboard rotation angle         | number                     |          |\n| keepAspectRatio   | Keep original aspect ratio       | boolean                    |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## Line Shape\n\n### LineStyleProps\n\n| Property          | Description         | Type                  | Required |\n| ----------------- | ------------------- | --------------------- | -------- |\n| x1                | Start x coordinate  | number                | ✓        |\n| y1                | Start y coordinate  | number                | ✓        |\n| x2                | End x coordinate    | number                | ✓        |\n| y2                | End y coordinate    | number                | ✓        |\n| z1                | Start z coordinate  | number                |          |\n| z2                | End z coordinate    | number                |          |\n| isBillboard       | Billboard mode      | boolean               |          |\n| isSizeAttenuation | Size attenuation    | boolean               |          |\n| markerStart       | Marker at start     | DisplayObject \\| null |          |\n| markerEnd         | Marker at end       | DisplayObject \\| null |          |\n| markerStartOffset | Start marker offset | number                |          |\n| markerEndOffset   | End marker offset   | number                |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Path Shape\n\n### PathStyleProps\n\n| Property          | Description          | Type                   | Required |\n| ----------------- | -------------------- | ---------------------- | -------- |\n| d                 | Path string or array | string \\| PathArray    | ✓        |\n| markerStart       | Marker at start      | DisplayObject \\| null  |          |\n| markerEnd         | Marker at end        | DisplayObject \\| null  |          |\n| markerMid         | Marker at middle     | DisplayObject \\| null  |          |\n| markerStartOffset | Start marker offset  | number                 |          |\n| markerEndOffset   | End marker offset    | number                 |          |\n| isBillboard       | Billboard mode       | boolean                |          |\n| isSizeAttenuation | Size attenuation     | boolean                |          |\n| fillRule          | Fill rule            | `nonzero` \\| `evenodd` |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## Polygon Shape\n\n### PolygonStyleProps\n\n| Property          | Description             | Type                                             | Required |\n| ----------------- | ----------------------- | ------------------------------------------------ | -------- |\n| points            | Array of polygon points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start         | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end           | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle        | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset     | number                                           |          |\n| markerEndOffset   | End marker offset       | number                                           |          |\n| isClosed          | Is polygon closed       | boolean                                          |          |\n| isBillboard       | Billboard mode          | boolean                                          |          |\n| isSizeAttenuation | Size attenuation        | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Polyline Shape\n\n### PolylineStyleProps\n\n| Property          | Description              | Type                                             | Required |\n| ----------------- | ------------------------ | ------------------------------------------------ | -------- |\n| points            | Array of polyline points | ([number, number] \\| [number, number, number])[] | ✓        |\n| markerStart       | Marker at start          | DisplayObject \\| null                            |          |\n| markerEnd         | Marker at end            | DisplayObject \\| null                            |          |\n| markerMid         | Marker at middle         | DisplayObject \\| null                            |          |\n| markerStartOffset | Start marker offset      | number                                           |          |\n| markerEndOffset   | End marker offset        | number                                           |          |\n| isBillboard       | Billboard mode           | boolean                                          |          |\n| isSizeAttenuation | Size attenuation         | boolean                                          |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## Text\n\n### TextStyleProps\n\n| Property            | Description              | Type                                                                        | Required |\n| ------------------- | ------------------------ | --------------------------------------------------------------------------- | -------- |\n| x                   | Text x coordinate        | number \\| string                                                            |          |\n| y                   | Text y coordinate        | number \\| string                                                            |          |\n| z                   | Text z coordinate        | number \\| string                                                            |          |\n| text                | Text content             | number \\| string                                                            | ✓        |\n| fontSize            | Font size                | number \\| string                                                            |          |\n| fontFamily          | Font family              | string                                                                      |          |\n| fontStyle           | Font style               | `normal` \\| `italic` \\| `oblique`                                           |          |\n| fontWeight          | Font weight              | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |          |\n| fontVariant         | Font variant             | `normal` \\| `small-caps` \\| string                                          |          |\n| textAlign           | Text horizontal align    | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |          |\n| textBaseline        | Text baseline            | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |          |\n| textOverflow        | Text overflow            | `clip` \\| `ellipsis` \\| string                                              |          |\n| lineHeight          | Line height              | number \\| string                                                            |          |\n| letterSpacing       | Letter spacing           | number \\| string                                                            |          |\n| maxLines            | Max lines                | number                                                                      |          |\n| textPath            | Text path                | Path                                                                        |          |\n| textPathSide        | Text path side           | `left` \\| `right`                                                           |          |\n| textPathStartOffset | Text path start offset   | number \\| string                                                            |          |\n| textDecorationLine  | Text decoration line     | string                                                                      |          |\n| textDecorationColor | Text decoration color    | string                                                                      |          |\n| textDecorationStyle | Text decoration style    | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |          |\n| isBillboard         | Billboard mode           | boolean                                                                     |          |\n| billboardRotation   | Billboard rotation angle | number                                                                      |          |\n| isSizeAttenuation   | Size attenuation         | boolean                                                                     |          |\n| wordWrap            | Word wrap                | boolean                                                                     |          |\n| wordWrapWidth       | Word wrap width          | number                                                                      |          |\n| dx                  | X offset                 | number \\| string                                                            |          |\n| dy                  | Y offset                 | number \\| string                                                            |          |\n\n**Example:**\n\n```js\nBaseShape.upsert(\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n**Display in multiply line:**\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n\n\n<!-- Skill/Rule: Shape Skill (packages/site/docs/manual/element/shape/properties.zh.md) -->\n---\ntitle: 原子 Shape 以及其属性\norder: 2\n---\n\nG6 中的元素（节点/边）是由**一个或多个 [图形 Shape](/manual/element/shape/overview)** 组成，主要通过自定义节点或自定义边时在 `render` 方法中使用 `upsert` 添加，G6 中支持以下的图形 Shape：\n\n1. [Circle - 圆形](#circlestyleprops)\n2. [Ellipse - 椭圆](#ellipsestyleprops)\n3. [Rect - 矩形](#rectstyleprops)\n4. [HTML - HTML元素](#htmlstyleprops)\n5. [Image - 图片](#imagestyleprops)\n6. [Line - 线](#linestyleprops)\n7. [Path - 路径](#pathstyleprops)\n8. [Polygon - 多边形](#polygonstyleprops)\n9. [Polyline - 折线](#polylinestyleprops)\n10. [Text - 文本](#textstyleprops)\n\n## 各图形 Shape 的通用属性\n\n### BaseShapeStyle\n\n| 属性           | 描述                                                                                          | 类型                                     | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------- | ---- |\n| x              | x 坐标                                                                                        | number                                   | ✓    |\n| y              | y 坐标                                                                                        | number                                   | ✓    |\n| width          | 宽度                                                                                          | number                                   | ✓    |\n| height         | 高度                                                                                          | number                                   | ✓    |\n| fill           | 填充颜色                                                                                      | string \\| Pattern \\| null                |      |\n| stroke         | 描边颜色                                                                                      | string \\| Pattern \\| null                |      |\n| opacity        | 整体透明度                                                                                    | number \\| string                         |      |\n| fillOpacity    | 填充透明度                                                                                    | number \\| string                         |      |\n| strokeOpacity  | 描边透明度                                                                                    | number \\| string                         |      |\n| lineWidth      | 线宽度                                                                                        | number \\| string                         |      |\n| lineCap        | 线段端点样式                                                                                  | `butt` \\| `round` \\| `square`            |      |\n| lineJoin       | 线段连接处样式                                                                                | `miter` \\| `round` \\| `bevel`            |      |\n| lineDash       | 虚线配置                                                                                      | number \\| string \\| (string \\| number)[] |      |\n| lineDashOffset | 虚线偏移量                                                                                    | number                                   |      |\n| shadowBlur     | 阴影模糊程度                                                                                  | number                                   |      |\n| shadowColor    | 阴影颜色                                                                                      | string                                   |      |\n| shadowOffsetX  | 阴影 X 方向偏移                                                                               | number                                   |      |\n| shadowOffsetY  | 阴影 Y 方向偏移                                                                               | number                                   |      |\n| cursor         | 鼠标样式，[CSS 的 cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) 选项都支持 | string                                   |      |\n| zIndex         | 渲染层级                                                                                      | number                                   |      |\n| visibility     | 可见性                                                                                        | `visible` \\| `hidden`                    |      |\n\n**示例：**\n\n```js\nconst shape = BaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 各图形 Shape 的通用方法\n\n### attr()\n\n设置或获取实例的绘图属性。\n\n### attr(name)\n\n获取实例的属性值。\n\n```js\nconst width = shape.attr('width');\n```\n\n### attr(name, value)\n\n更新实例的单个绘图属性。\n\n### attr({...})\n\n批量更新实例绘图属性。\n\n```js\nshape.attr({\n  fill: '#999',\n  stroke: '#666',\n});\n```\n\n## 圆图形 Circle\n\n### CircleStyleProps\n\n| 属性              | 描述                               | 类型             | 必选 |\n| ----------------- | ---------------------------------- | ---------------- | ---- |\n| cx                | 圆心 x 坐标                        | number \\| string | ✓    |\n| cy                | 圆心 y 坐标                        | number \\| string | ✓    |\n| cz                | 圆心 z 坐标                        | number \\| string |      |\n| r                 | 圆的半径                           | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式（始终面向相机） | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减（随视距变化大小） | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'circle',\n  {\n    cx: 100,\n    cy: 100,\n    r: 50,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 矩形图形 Rect\n\n### RectStyleProps\n\n| 属性              | 描述               | 类型                         | 必选 |\n| ----------------- | ------------------ | ---------------------------- | ---- |\n| x                 | 矩形 x 坐标        | number \\| string             |      |\n| y                 | 矩形 y 坐标        | number \\| string             |      |\n| z                 | 矩形 z 坐标        | number                       |      |\n| width             | 矩形宽度           | number \\| string             | ✓    |\n| height            | 矩形高度           | number \\| string             | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean                      |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                      |      |\n| radius            | 矩形圆角半径       | number \\| string \\| number[] |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'rect',\n  {\n    x: 100,\n    y: 100,\n    width: 100,\n    height: 100,\n    radius: 8,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## 椭圆图形 Ellipse\n\n### EllipseStyleProps\n\n| 属性              | 描述               | 类型             | 必选 |\n| ----------------- | ------------------ | ---------------- | ---- |\n| cx                | 椭圆中心 x 坐标    | number \\| string | ✓    |\n| cy                | 椭圆中心 y 坐标    | number \\| string | ✓    |\n| cz                | 椭圆中心 z 坐标    | number \\| string |      |\n| rx                | 椭圆 x 轴半径      | number \\| string | ✓    |\n| ry                | 椭圆 y 轴半径      | number \\| string | ✓    |\n| isBillboard       | 是否启用公告牌模式 | boolean          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'ellipse',\n  {\n    cx: 100,\n    cy: 100,\n    rx: 50,\n    ry: 80,\n    fill: 'blue',\n  },\n  container,\n);\n```\n\n## HTML DOM\n\n### HTMLStyleProps\n\n| 属性      | 描述             | 类型                  | 必选 |\n| --------- | ---------------- | --------------------- | ---- |\n| x         | HTML 元素 x 坐标 | number \\| string      |      |\n| y         | HTML 元素 y 坐标 | number \\| string      |      |\n| innerHTML | HTML 内容        | string \\| HTMLElement | ✓    |\n| width     | HTML 元素宽度    | number \\| string      |      |\n| height    | HTML 元素高度    | number \\| string      |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'html',\n  {\n    x: 100,\n    y: 100,\n    innerHTML: <div>content</div>,\n  },\n  container,\n);\n```\n\n## 图片图形 Image\n\n### ImageStyleProps\n\n| 属性              | 描述                         | 类型                       | 必选 |\n| ----------------- | ---------------------------- | -------------------------- | ---- |\n| x                 | 图片 x 坐标                  | number \\| string           |      |\n| y                 | 图片 y 坐标                  | number \\| string           |      |\n| z                 | 图片 z 坐标                  | number                     |      |\n| src               | 图片资源路径或 HTML 图片元素 | string \\| HTMLImageElement | ✓    |\n| width             | 图片宽度                     | number \\| string           |      |\n| height            | 图片高度                     | number \\| string           |      |\n| isBillboard       | 是否启用公告牌模式           | boolean                    |      |\n| isSizeAttenuation | 是否启用大小衰减             | boolean                    |      |\n| billboardRotation | 公告牌模式下的旋转角度       | number                     |      |\n| keepAspectRatio   | 是否保持图片原有宽高比       | boolean                    |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'image',\n  {\n    x: 100,\n    y: 100,\n    src: 'http://',\n  },\n  container,\n);\n```\n\n## 直线 Line\n\n### LineStyleProps\n\n| 属性              | 描述               | 类型                  | 必选 |\n| ----------------- | ------------------ | --------------------- | ---- |\n| x1                | 线段起点 x 坐标    | number                | ✓    |\n| y1                | 线段起点 y 坐标    | number                | ✓    |\n| x2                | 线段终点 x 坐标    | number                | ✓    |\n| y2                | 线段终点 y 坐标    | number                | ✓    |\n| z1                | 线段起点 z 坐标    | number                |      |\n| z2                | 线段终点 z 坐标    | number                |      |\n| isBillboard       | 是否启用公告牌模式 | boolean               |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean               |      |\n| markerStart       | 线段起点的标记     | DisplayObject \\| null |      |\n| markerEnd         | 线段终点的标记     | DisplayObject \\| null |      |\n| markerStartOffset | 起点标记的偏移量   | number                |      |\n| markerEndOffset   | 终点标记的偏移量   | number                |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'line',\n  {\n    x1: 100,\n    y1: 100,\n    x2: 150,\n    y2: 150,\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 路径 Path\n\n### PathStyleProps\n\n| 属性              | 描述                 | 类型                   | 必选 |\n| ----------------- | -------------------- | ---------------------- | ---- |\n| d                 | 路径定义字符串或数组 | string \\| PathArray    | ✓    |\n| markerStart       | 路径起点的标记       | DisplayObject \\| null  |      |\n| markerEnd         | 路径终点的标记       | DisplayObject \\| null  |      |\n| markerMid         | 路径中间点的标记     | DisplayObject \\| null  |      |\n| markerStartOffset | 起点标记的偏移量     | number                 |      |\n| markerEndOffset   | 终点标记的偏移量     | number                 |      |\n| isBillboard       | 是否启用公告牌模式   | boolean                |      |\n| isSizeAttenuation | 是否启用大小衰减     | boolean                |      |\n| fillRule          | 填充规则             | `nonzero` \\| `evenodd` |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'path',\n  {\n    d: 'M 0,0 L 20,10 L 20,-10 Z',\n    stroke: 'blue',\n  },\n  container,\n);\n```\n\n## 多边形图形 Polygon\n\n### PolygonStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 多边形的顶点数组   | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 多边形起点的标记   | DisplayObject \\| null                            |      |\n| markerEnd         | 多边形终点的标记   | DisplayObject \\| null                            |      |\n| markerMid         | 多边形中间点的标记 | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isClosed          | 是否闭合多边形     | boolean                                          |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polygon',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 折线 Polyline\n\n### PolylineStyleProps\n\n| 属性              | 描述               | 类型                                             | 必选 |\n| ----------------- | ------------------ | ------------------------------------------------ | ---- |\n| points            | 折线的顶点数组     | ([number, number] \\| [number, number, number])[] | ✓    |\n| markerStart       | 折线起点的标记     | DisplayObject \\| null                            |      |\n| markerEnd         | 折线终点的标记     | DisplayObject \\| null                            |      |\n| markerMid         | 折线中间点的标记   | DisplayObject \\| null                            |      |\n| markerStartOffset | 起点标记的偏移量   | number                                           |      |\n| markerEndOffset   | 终点标记的偏移量   | number                                           |      |\n| isBillboard       | 是否启用公告牌模式 | boolean                                          |      |\n| isSizeAttenuation | 是否启用大小衰减   | boolean                                          |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'polyline',\n  {\n    points: [\n      [30, 30],\n      [40, 20],\n      [30, 50],\n      [60, 100],\n    ],\n    fill: 'red',\n  },\n  container,\n);\n```\n\n## 文字 Text\n\n### TextStyleProps\n\n| 属性                | 描述               | 类型                                                                        | 必选 |\n| ------------------- | ------------------ | --------------------------------------------------------------------------- | ---- |\n| x                   | 文本 x 坐标        | number \\| string                                                            |      |\n| y                   | 文本 y 坐标        | number \\| string                                                            |      |\n| z                   | 文本 z 坐标        | number \\| string                                                            |      |\n| text                | 文本内容           | number \\| string                                                            | ✓    |\n| fontSize            | 字体大小           | number \\| string                                                            |      |\n| fontFamily          | 字体族             | string                                                                      |      |\n| fontStyle           | 字体样式           | `normal` \\| `italic` \\| `oblique`                                           |      |\n| fontWeight          | 字体粗细           | `normal` \\| `bold` \\| `bolder` \\| `lighter` \\| number                       |      |\n| fontVariant         | 字体变种           | `normal` \\| `small-caps` \\| string                                          |      |\n| textAlign           | 文本水平对齐方式   | `start` \\| `center` \\| `middle` \\| `end` \\| `left` \\| `right`               |      |\n| textBaseline        | 文本基线           | `top` \\| `hanging` \\| `middle` \\| `alphabetic` \\| `ideographic` \\| `bottom' |      |\n| textOverflow        | 文本溢出处理方式   | `clip` \\| `ellipsis` \\| string                                              |      |\n| lineHeight          | 行高               | number \\| string                                                            |      |\n| letterSpacing       | 字间距             | number \\| string                                                            |      |\n| maxLines            | 最大行数           | number                                                                      |      |\n| textPath            | 文本路径           | Path                                                                        |      |\n| textPathSide        | 文本路径侧边       | `left` \\| `right`                                                           |      |\n| textPathStartOffset | 文本路径起始偏移   | number \\| string                                                            |      |\n| textDecorationLine  | 文本装饰线         | string                                                                      |      |\n| textDecorationColor | 文本装饰线颜色     | string                                                                      |      |\n| textDecorationStyle | 文本装饰线样式     | `solid` \\| `double` \\| `dotted` \\| `dashed` \\| `wavy`                       |      |\n| isBillboard         | 是否启用公告牌模式 | boolean                                                                     |      |\n| billboardRotation   | 公告牌旋转角度     | number                                                                      |      |\n| isSizeAttenuation   | 是否启用大小衰减   | boolean                                                                     |      |\n| wordWrap            | 是否自动换行       | boolean                                                                     |      |\n| wordWrapWidth       | 自动换行宽度       | number                                                                      |      |\n| dx                  | X 方向偏移         | number \\| string                                                            |      |\n| dy                  | Y 方向偏移         | number \\| string                                                            |      |\n\n**示例：**\n\n```js\nBaseShape.upsert(\n  // 指定图形 key，需要保证在同一个自定义元素类型中保持唯一性\n  'shape',\n  'text',\n  {\n    x: 100,\n    y: 100,\n    text: 'text',\n  },\n  container,\n);\n```\n\n多行文字显示：\n\n```js\n{\n  wordWrap: true,\n  wordWrapWidth: 100,\n  maxLines: 4,\n  textOverflow: 'ellipsis',\n}\n```\n\n\n<!-- Skill/Rule: Element Skill (packages/site/docs/manual/element/state.en.md) -->\n---\ntitle: Element State\norder: 2\n---\n\n## What is Element State\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\nElement State refers to the visual representation of elements (nodes, edges, combos) in a graph under different interaction scenarios. For example, when a user clicks on a node, the node might enter a \"selected\" state and change color; when the mouse hovers over an edge, the edge might enter a \"highlight\" state and become bold.\n\n**Simply put, states allow elements to dynamically change their appearance based on user operations or business logic.**\n\n### Characteristics of States\n\n- **Multiple State Coexistence**: An element can have multiple states simultaneously, such as being both \"selected\" and \"highlighted\"\n- **Style Stacking**: Styles from multiple states are stacked together, with later-set state styles having higher priority\n- **Complete Customization**: Besides built-in states, you can create any custom states that meet your business requirements\n\n## Built-in State Types\n\nG6 provides some commonly used built-in states that you can use directly:\n\n| State Name  | Description     | Typical Use Cases                    |\n| ----------- | --------------- | ------------------------------------ |\n| `selected`  | Selected state  | When user clicks to select elements  |\n| `active`    | Active state    | Currently interacting element        |\n| `highlight` | Highlight state | Elements that need emphasis          |\n| `inactive`  | Inactive state  | Dimmed display of unfocused elements |\n| `disabled`   | Disabled state  | Non-interactive elements             |\n\n> 💡 **Tip**: These built-in states are not mandatory. You can completely define your own state names according to business requirements.\n\n## Configuring State Styles\n\n### Basic Configuration\n\nConfigure corresponding styles for different states when creating a graph instance:\n\n```javascript\nconst graph = new Graph({\n  // Node state style configuration\n  node: {\n    // Default style (style when no state is applied)\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // Styles for various states\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // Edge state style configuration\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // Combo state style configuration\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### Custom States\n\nYou can create any custom states that meet your business requirements:\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // Custom state: error\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // Dashed border\n      },\n      // Custom state: success\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // Custom state: warning\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // Add icon\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## Setting Element States\n\n### Setting Initial States in Data\n\nSet initial states for elements in data:\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // Initially in selected state\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // Initially in disabled state\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // Initially has multiple states\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // Initial state of the edge\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### Dynamic State Setting\n\nDynamically change element states through API:\n\n```javascript\n// Set a single state for a single element\ngraph.setElementState('node1', 'selected');\n\n// Set multiple states for a single element\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// Batch set states for multiple elements\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### State Stacking Effect\n\nWhen an element has multiple states, styles are stacked in order:\n\n```javascript\n// Assume a node has both selected and highlight states\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// Final style = default style + selected state style + highlight state style\n// If there are style conflicts, later state styles will override earlier ones\n```\n\n## Clearing Element States\n\n### Clear All States\n\nRestore elements to default state (no states):\n\n```javascript\n// Clear all states of a single element\ngraph.setElementState('node1', []);\n\n// Batch clear states of multiple elements\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### Clear Specific States\n\nIf an element has multiple states, you can clear only some of them:\n\n```javascript\n// Assume node1 currently has ['selected', 'highlight', 'active'] three states\n// Now only want to keep 'selected' state, clear other states\ngraph.setElementState('node1', ['selected']);\n\n// Or get current states, then filter out unwanted states\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### Clear Specific States from All Elements\n\n```javascript\n// Clear 'highlight' state from all nodes\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## Querying Element States\n\n### Get Element States\n\n```javascript\n// Get all states of a specified element\nconst states = graph.getElementState('node1');\nconsole.log(states); // For example: ['selected', 'highlight']\n\n// If element has no states, returns empty array\nconsole.log(states); // []\n```\n\n### Find Elements with Specific States\n\n```javascript\n// Get all node data in 'selected' state\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// Get all edge data in 'highlight' state\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### Check if Element is in Specific State\n\n```javascript\n// Check if element is in specific state\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('Is node selected:', isSelected);\nconsole.log('Is node highlighted:', isHighlight);\n```\n\n\n<!-- Skill/Rule: Element Skill (packages/site/docs/manual/element/state.zh.md) -->\n---\ntitle: 元素状态\norder: 2\n---\n\n## 什么是元素状态\n\n<image width=\"500px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yVbORYybrDQAAAAAAAAAAAAADmJ7AQ/original\" />\n\n元素状态(State)是指图中元素（节点、边、组合）在不同交互场景下的视觉表现形式。比如当用户点击一个节点时，节点可能会变成\"选中\"状态并改变颜色；当鼠标悬停在边上时，边可能会进入\"高亮\"状态并加粗显示。\n\n**简单来说，状态让元素能够根据用户的操作或业务逻辑动态改变外观。**\n\n### 状态的特点\n\n- **多状态共存**：一个元素可以同时拥有多个状态，比如既是\"选中\"又是\"高亮\"\n- **样式叠加**：多个状态的样式会叠加在一起，后设置的状态样式优先级更高\n- **完全自定义**：除了内置状态，您可以创建任何符合业务需求的自定义状态\n\n## 内置状态类型\n\nG6 提供了一些常用的内置状态，您可以直接使用：\n\n| 状态名      | 说明       | 典型使用场景       |\n| ----------- | ---------- | ------------------ |\n| `selected`  | 选中状态   | 用户点击选择元素时 |\n| `active`    | 激活状态   | 当前正在交互的元素 |\n| `highlight` | 高亮状态   | 需要强调显示的元素 |\n| `inactive`  | 非活跃状态 | 淡化显示非关注元素 |\n| `disabled`   | 禁用状态   | 不可交互的元素     |\n\n> 💡 **提示**：这些内置状态并非必须使用，您完全可以根据业务需求定义自己的状态名称。\n\n## 配置状态样式\n\n### 基础配置\n\n在创建图实例时，为不同状态配置相应的样式：\n\n```javascript\nconst graph = new Graph({\n  // 节点的状态样式配置\n  node: {\n    // 默认样式（无状态时的样式）\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n      lineWidth: 1,\n    },\n    // 各种状态下的样式\n    state: {\n      selected: {\n        fill: '#95D6FB',\n        stroke: '#1890FF',\n        lineWidth: 2,\n        shadowColor: '#1890FF',\n        shadowBlur: 10,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 2,\n      },\n      disabled: {\n        fill: '#ECECEC',\n        stroke: '#BFBFBF',\n        opacity: 0.5,\n      },\n    },\n  },\n\n  // 边的状态样式配置\n  edge: {\n    style: {\n      stroke: '#E2E2E2',\n      lineWidth: 1,\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n      highlight: {\n        stroke: '#FF6A00',\n        lineWidth: 3,\n      },\n    },\n  },\n\n  // 组合的状态样式配置\n  combo: {\n    style: {\n      fill: '#F0F0F0',\n      stroke: '#D9D9D9',\n    },\n    state: {\n      selected: {\n        stroke: '#1890FF',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n### 自定义状态\n\n您可以创建任何符合业务需求的自定义状态：\n\n```javascript\nconst graph = new Graph({\n  node: {\n    style: {\n      fill: '#C6E5FF',\n      stroke: '#5B8FF9',\n    },\n    state: {\n      // 自定义状态：错误\n      error: {\n        fill: '#FFEBE6',\n        stroke: '#FF4D4F',\n        lineWidth: 2,\n        lineDash: [4, 4], // 虚线边框\n      },\n      // 自定义状态：成功\n      success: {\n        fill: '#F6FFED',\n        stroke: '#52C41A',\n        lineWidth: 2,\n      },\n      // 自定义状态：警告\n      warning: {\n        fill: '#FFFBE6',\n        stroke: '#FAAD14',\n        lineWidth: 2,\n        // 添加图标\n        icon: {\n          show: true,\n          text: '⚠️',\n          fontSize: 16,\n        },\n      },\n    },\n  },\n});\n```\n\n## 设置元素状态\n\n### 数据中设置初始状态\n\n在数据中为元素设置初始状态：\n\n```javascript\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      states: ['selected'], // 初始为选中状态\n    },\n    {\n      id: 'node2',\n      states: ['disabled'], // 初始为禁用状态\n    },\n    {\n      id: 'node3',\n      states: ['highlight', 'active'], // 初始有多个状态\n    },\n  ],\n  edges: [\n    {\n      source: 'node1',\n      target: 'node2',\n      states: ['highlight'], // 边的初始状态\n    },\n  ],\n};\n\ngraph.setData(data);\n```\n\n### 动态设置状态\n\n通过 API 动态改变元素状态：\n\n```javascript\n// 设置单个元素的单个状态\ngraph.setElementState('node1', 'selected');\n\n// 设置单个元素的多个状态\ngraph.setElementState('node2', ['highlight', 'active']);\n\n// 批量设置多个元素的状态\ngraph.setElementState({\n  node1: ['selected'],\n  node2: ['highlight'],\n  edge1: ['active'],\n});\n```\n\n### 状态的叠加效果\n\n当元素有多个状态时，样式会按顺序叠加：\n\n```javascript\n// 假设节点同时有 selected 和 highlight 状态\ngraph.setElementState('node1', ['selected', 'highlight']);\n\n// 最终样式 = 默认样式 + selected状态样式 + highlight状态样式\n// 如果有样式冲突，后面的状态样式会覆盖前面的\n```\n\n## 清除元素状态\n\n### 清除所有状态\n\n将元素恢复到默认状态（无任何状态）：\n\n```javascript\n// 清除单个元素的所有状态\ngraph.setElementState('node1', []);\n\n// 批量清除多个元素的状态\ngraph.setElementState({\n  node1: [],\n  node2: [],\n  edge1: [],\n});\n```\n\n### 清除特定状态\n\n如果元素有多个状态，您可以只清除其中的某些状态：\n\n```javascript\n// 假设 node1 当前有 ['selected', 'highlight', 'active'] 三个状态\n// 现在只想保留 'selected' 状态，清除其他状态\ngraph.setElementState('node1', ['selected']);\n\n// 或者获取当前状态，然后过滤掉不需要的状态\nconst currentStates = graph.getElementState('node1');\nconst newStates = currentStates.filter((state) => state !== 'highlight');\ngraph.setElementState('node1', newStates);\n```\n\n### 清除所有元素的特定状态\n\n```javascript\n// 清除所有节点的 'highlight' 状态\nconst allNodes = graph.getNodeData();\nconst stateUpdates = {};\n\nallNodes.forEach((node) => {\n  const currentStates = graph.getElementState(node.id);\n  const newStates = currentStates.filter((state) => state !== 'highlight');\n  stateUpdates[node.id] = newStates;\n});\n\ngraph.setElementState(stateUpdates);\n```\n\n## 查询元素状态\n\n### 获取元素状态\n\n```javascript\n// 获取指定元素的所有状态\nconst states = graph.getElementState('node1');\nconsole.log(states); // 例如：['selected', 'highlight']\n\n// 如果元素没有任何状态，返回空数组\nconsole.log(states); // []\n```\n\n### 查找特定状态的元素\n\n```javascript\n// 获取所有处于 'selected' 状态的节点数据\nconst selectedNodes = graph.getElementDataByState('node', 'selected');\n\n// 获取所有处于 'highlight' 状态的边数据\nconst highlightEdges = graph.getElementDataByState('edge', 'highlight');\n```\n\n### 判断元素是否处于某状态\n\n```javascript\n// 检查元素是否处于特定状态\nconst states = graph.getElementState('node1');\nconst isSelected = states.includes('selected');\nconst isHighlight = states.includes('highlight');\n\nconsole.log('节点是否选中:', isSelected);\nconsole.log('节点是否高亮:', isHighlight);\n```\n\n\n<!-- Skill/Rule: Extension Skill (packages/site/docs/manual/extension/3d.en.md) -->\n---\ntitle: g6-extension-3d\n---\n\n\n<!-- Skill/Rule: Extension Skill (packages/site/docs/manual/extension/3d.zh.md) -->\n---\ntitle: g6-extension-3d\n---\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/faq.en.md) -->\n---\ntitle: FAQ\norder: 13\n---\n\n### What is the Difference Between Extension and Plugin?\n\n`Extension` is a concept in G6 that collectively refers to all types of registrable content, including elements, behaviors, layouts, and plugins, among others.\n\n`Plugin` represents a flexible extension mechanism provided by G6 and is a special type of `Extension`.\n\n### Set Text Overflow Ellipsis\n\nTaking `label` as an example, you can set `labelWordWrap` and `labelWordWrapWidth` to achieve text overflow ellipsis.\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### Key Press Not Working\n\nSome plugins or behaviors support configuring key press triggers. Please use standard key names, such as `Control`, `Shift`, `Alt`, `Meta`, as well as letters, numbers, symbols, and so on.\n\n### Canvas Not Updating After Data Update\n\nEnsure that you call `graph.draw()` or `graph.render()` to update the canvas after updating the data.\n\n> G6 merges differences and updates the canvas uniformly after `draw` or `render` for multiple data updates to improve performance.\n\n### How to Resolve Interaction Conflicts\n\nWhen multiple interactions conflict with each other, you can set the enable timing of interactions to avoid multiple interactions being triggered simultaneously.\n\nTaking `drag-canvas` and `brush-select` as an example, if you directly configure these two interactions, dragging on the canvas will cause interaction exceptions. You can disable the `drag-canvas` interaction when the `shift` key is pressed.\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\nAt this point, when the `shift` key is pressed, the `drag-canvas` interaction will be disabled, and the `brush-select` interaction will not be affected.\n\n### Difference Between `draw` and `render`\n\nBoth `draw` and `render` execute drawing operations, but `render` additionally performs **layout** and **auto fit** operations based on `draw`.\n\nYou can simply understand it as: `render` = `draw` + `layout` + `fitView`/`fitCenter`.\n\n### Style in Data Not Effective\n\nReason 1: The style in the data is overridden by the style in the style mapping.\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // No matter what the style in the data is, it will be overridden by the style here\n    }\n  }\n}\n```\n\nSolution: Use a callback method to prioritize obtaining styles from the data to improve data priority.\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### Residual content in the canvas\n\nWhen using the Canvas renderer for drawing, residual content may appear in the canvas, which is referred to as \"dirty rectangles\". This phenomenon occurs because the underlying rendering engine improves performance by only drawing the parts that have changed each time, rather than clearing the entire canvas.\n\nHowever, when the graphics in the canvas change, there may be cases where some graphics are not correctly cleared, resulting in residual content.\n\nYou can solve this issue by:\n\n1. Using the SVG or WebGL renderer;\n2. Checking whether there are illegal values in the element of the nodes, such as null, NaN, and so on;\n3. Using integers as much as possible for numeric style values, such as r, width, height, fontSize, and so on.\n\n### Use Vanilla JavaScript Object Data\n\nPlease avoid using Vue reactive data, Immer.js, and other wrapped objects as the data source for G6, as these objects will be deeply monitored internally, and even freeze the data object, causing G6 to fail to operate normally.\n\n### G6 project startup Warning during compilation Type mapping points to non-existent path\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> Explanation: [@antv/util](https://github.com/antvis/util) is a tool library that AntV relies on at the bottom.\n\nFrom the partial warning message above, we can see that there is a problem with the type declaration file of the `@antv/util` tool library that G6 depends on.**This warning does not affect the normal operation of the project**.\n\nThis message will only appear in TypeScript projects. The following are ways to turn it off:\n\n1. Turn off TypeScript sourcemap\n\nCreate a `.env` file in the root directory of the project and add the following content:\n\ntext\nGENERATE_SOURCEMAP=false\ntext\n\n2. Disable sourcemapping for specific modules\n\nDisabling sourcemapping directly is too simple and crude, and is not user-friendly for developers who may have debugging needs. Therefore, sourcemapping can be disabled for specific modules by configuring the build tool separately.\n\na. webpack configuration\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite configuration\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // Ignore warnings for specific modules\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // For other warnings, use the default warning handling\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### Manually configuring the color palette does not take effect\n\n> In v5, the built-in colors are: export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\nThe solution is as follows:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line plugin does not take effect\n\n> In v5, built-in plugins include `bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [Detailed reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\nActual reason: The parent container of the `graph` instance, `<div ref={containerRef} />`, does not have a height set, so the G6 Graph may not be able to calculate the correct size.**If you want to enable the `grid-line` canvas plugin, you need to set the width and height of the parent element, which is not valid in the graph configuration**.\n\n### v5 cannot use the tree layout\n\nUse `new Graph({xxx})` uniformly.\n\n> In v5, built-in layouts include `antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [Specific reference](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5 merges the graph and tree graph, no longer creates the tree graph layout by instantiating `G6.TreeGraph`, and removes this method. For details, see [Features - Merge Graph and Tree Graph](https://g6.antv.antgroup.com/manual/feature#-%E5%90%88%E5%B9%B6%E5%9B%BE%E4%B8%8E%E6%A0%91%E5%9B%BE)\n\n### edge does not have a connection at the center of the node\n\nis configured [portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter) to `true`.\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### How to dynamically set the width of a node based on the length of the label content\n\nImplementation solution: [#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent node event object type is not complete\n\nYou can manually specify the `IPointerEvent` type. For details, see [#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### Remove the parent combo of the node\n\nUpdate the node data, set the `combo` value to `null`.\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/faq.zh.md) -->\n---\ntitle: 常见问题\norder: 13\n---\n\n### Extension 和 Plugin 有什么区别？\n\n`Extension` 是 G6 中的一个概念，是所有可注册内容的统称，包含元素、交互、布局、插件等。\n\n`Plugin` 是 G6 提供的灵活扩展机制，是一种特殊的 `Extension`。\n\n### 设置文本超出省略\n\n以 label 为例，设置 `labelWordWrap` 和 `labelWordWrapWidth` 即可实现文本超出省略。\n\n```typescript {3-4}\n{\n  labelText: 'This is a long text',\n  labelWordWrap: true,\n  labelWordWrapWidth: 50,\n}\n```\n\n### 按键不生效\n\n一些插件或交互支持配置触发按键，请使用标准按键名：如 `Control`, `Shift`, `Alt`, `Meta`，以及字母、数字、符号等。\n\n### 更新数据后画布不更新\n\n请确保数据更新后调用 `graph.draw()` 或者 `graph.render()` 更新画布。\n\n> G6 对于多次数据更新，会在 `draw` 或 `render` 后合并差异并统一更新画布，以提高性能。\n\n### 交互有冲突如何解决\n\n当多个交互之间存在冲突时，你可以设置交互的启用时机来避免多个交互被同时触发。\n\n以 `drag-canvas` 和 `brush-select` 为例，如果直接配置这两个交互，当指针在画布上进行拖拽时，会导致交互异常。可以设置为在按下 `shift` 键时禁用 `drag-canvas` 交互。\n\n```typescript {4}\nbehaviors: [\n  {\n    type: 'drag-canvas',\n    enable: (event) => event.shiftKey === false,\n  },\n  {\n    type: 'brush-select',\n  },\n];\n```\n\n此时，当按下 `shift` 键时，`drag-canvas` 交互会被禁用，`brush-select` 交互会不会受到影响。\n\n### draw 和 render 的区别\n\n`draw` 和 `render` 都会执行绘制操作，但 `render` 会在 `draw` 的基础上额外进行**布局**、**视图自适应**操作。\n\n可以简单理解为：`render` = `draw` + `layout` + `fitView`/`fitCenter`。\n\n### 数据中的样式不生效\n\n原因一：被样式映射中的样式覆盖\n\n```typescript {5}\n{\n  data: [{ id: 'node-1', style: { fill: 'orange' } }],\n  node: {\n    style: {\n      fill: 'pink', // 无论数据中的样式如何，都会被这里的样式覆盖\n    }\n  }\n}\n```\n\n解决方式：使用回调方法，优先从数据中获取样式以提高数据优先级\n\n```typescript {5}\n{\n  node: {\n    style: (data) => {\n      return {\n        fill: data.style?.fill || 'pink',\n      };\n    };\n  }\n}\n```\n\n### 画布中出现残影\n\n在使用 Canvas 渲染器进行绘制时，可能会出现残影现象，这些图形被称为“脏矩形”。该现象出现的原因是底层渲染引擎为了提高性能，每次绘制时只会绘制发生变化的部分，而不会清空整个画布。\n\n但是，当画布中的图形发生变化时，可能会出现部分图形未被正确清除的情况，从而导致残影现象。\n\n可以通过以下方式解决：\n\n1. 使用 SVG 或 WebGL 渲染器；\n2. 检查节点中的图形样式中是否存在非法值，例如 null、NaN 等；\n3. 尽量使用整数作为数值型的样式值，例如 r、width、height、fontSize 等；\n\n### 使用原生 JavaScript 对象数据\n\n请避免使用 Vue 响应式数据、Immer.js 等包装过的对象作为 G6 的数据源，因为这些对象会在内部进行深度监听，甚至冻结数据对象，导致 G6 无法正常操作数据。\n\n### G6 项目启动在编译时警告类型映射指向不存在路径\n\n```shell\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-cubic-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-cubic-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-line-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-line-factory.ts'\n\nWARNING in ./node_modules/@antv/util/esm/path/util/segment-quad-factory.js\nModule Warning (from ./node_modules/source-map-loader/dist/cjs.js):\nFailed to parse source map from '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts' file: Error: ENOENT: no such file or directory, open '/Users/xxx/workspace/antv-g6-learn/node_modules/@antv/util/esm/path/util/src/path/util/segment-quad-factory.ts'\n```\n\n> 解释: [@antv/util](https://github.com/antvis/util) 是 AntV 底层依赖的工具库。\n\n从上面部分警告信息中我们可以得知是 G6 依赖的 `@antv/util` 工具库的类型声明文件存在问题，**该警告不影响项目正常运行**。\n\n该信息只会在 TypeScript 项目中出现，关闭办法如下:\n\n1. 关闭TypeScript 的sourcemap源码映射\n\n在项目根目录下创建`.env`文件，并添加以下内容:\n\n```text\nGENERATE_SOURCEMAP=false\n```\n\n2. 单独禁用指定模块的源码映射\n\n直接禁用sourcemap映射的方式过于简单粗暴，对于部分可能有调试需求的开发者不太友好，所以也可以通过在构建工具单独配置，单独禁用这些特定模块的源码映射。\n\na. webpack配置\n\n```javascript\nmodule.exports = {\n  // ...其他配置\n  module: {\n    rules: [\n      {\n        test: /node_modules\\/@antv\\/util\\/esm\\/path\\/util\\/.+\\.js$/,\n        use: ['source-map-loader'],\n        enforce: 'pre',\n      },\n    ],\n  },\n  ignoreWarnings: [/Failed to parse source map/],\n};\n```\n\nb. vite配置\n\n```javascript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      onwarn(warning, warn) {\n        // 忽略特定模块的警告\n        if (warning.code === 'MODULE_LEVEL_DIRECTIVE' && warning.message.includes('@antv/util')) {\n          return;\n        }\n        // 对于其他警告,使用默认的警告处理\n        warn(warning);\n      },\n    },\n  },\n});\n```\n\n### 手动配置色板颜色不生效\n\n> 在 v5 中内置颜色有：export type BuiltInPalette = 'spectral' | 'oranges' | 'greens' | 'blues';\n\n解决办法如下:\n\n```typescript {10}\nconst graph = new Graph({\n  container: '#ID',\n  width: number,\n  height: number,\n  data,\n  node: {\n    palette: {\n      field: 'color',\n      // right\n      color: ['red', 'green', 'blue'],\n\n      // error\n      // color: 'red'\n    },\n  },\n});\n```\n\n### grid-line 插件不生效\n\n> 在 v5 中内置插件有`bubble-sets` `edge-filter-lens` `grid-line` `background` `contextmenu` `fisheye` `fullscreen` `history` `hull` `legend` `minimap` `snapline` `timebar` `toolbar` `tooltip` >`watermark`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L189)\n\n实际原因: `graph`实例的父容器`<div ref={containerRef} />`本身没有设置高度，G6 Graph图 可能无法正确计算出合适的大小。**如果要启用`grid-line`画布插件，需要给父元素 div 设置宽高，在 graph 配置中是无效的**。\n\n### v5无法使用树图布局\n\n统一使用`new Graph({xxx})`。\n\n> 在 v5 中内置布局有`antv-dagre` `combo-combined` `compact-box` `force-atlas2` `circular` `concentric` `d3-force` `dagre` `dendrogram` `force` `fruchterman` `grid` `indented` `mds` `mindmap` `radial` `random`. [具体参考](https://github.com/antvis/G6/blob/6e2355020c20b3a1e2e5ca0e0ee97aeb81f932b3/packages/g6/src/registry/build-in.ts#L147)\n\nv5合并了图和树图，不再通过实例化`G6.TreeGraph`创建树图布局，并且移除该方式。具体参考[特性-合并图与树图](/manual/whats-new/feature#🌲-合并图与树图)\n\n### edge 没有连接在 node 的边缘中心\n\n配置[portLinkToCenter](https://g6.antv.antgroup.com/api/elements/nodes/base-node#portlinktocenter)为 `true`。\n\n```typescript {6}\nconst graph = new Graph({\n  container: xxx,\n  node: {\n    type: 'rect',\n    style: {\n      portLinkToCenter: true,\n    },\n  },\n  edge: {\n    type: 'xxx',\n  },\n});\n```\n\n### 如何根据label内容长度动态设置node宽度\n\n参考方案：[#6347](https://github.com/antvis/G6/pull/6347#issuecomment-2357515570)\n\n```typescript\nconst measureTextWidth = memoize(\n  (text: string, font: any = {}): TextMetrics => {\n    const { fontSize, fontFamily = 'sans-serif', fontWeight, fontStyle, fontVariant } = font;\n    const ctx = getCanvasContext();\n    // @see https://developer.mozilla.org/zh-CN/docs/Web/CSS/font\n    ctx.font = [fontStyle, fontWeight, fontVariant, `${fontSize}px`, fontFamily].join(' ');\n    return ctx.measureText(isString(text) ? text : '').width;\n  },\n  (text: string, font = {}) => [text, ...values(font)].join(''),\n);\n\nconst graph = new G6.Graph({\n    node: {\n          style: { size: d => [measureTextWidth(d.label, {...}) , xxx] },\n    }\n})\n```\n\n### NodeEvent节点事件对象类型不齐全问题\n\n可以手动指定`IPointerEvent`类型。具体参考[#6346](https://github.com/antvis/G6/issues/6346)\n\n```typescript {4}\nimport { NodeEvent } from '@antv/g6';\nimport type { IPointerEvent } from '@antv/g6';\n\ngraph.on(NodeEvent.CLICK, (event: IPointerEvent) => {\n  // handler\n});\n```\n\n### 解除节点所在组合\n\n更新节点数据，`combo` 值设置为 `null`。\n\n```typescript\ngraph.updateNodeData([{ id: 'node-id', combo: null }]);\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/3d.en.md) -->\n---\ntitle: Use 3D\norder: 5\n---\n\n## Install Dependencies\n\nBefore using 3D capabilities, please install the 3D extension package first:\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\nThe extension package exports the following:\n\n- renderer: 3D renderer\n\n**Elements**\n\n- Capsule: capsule node\n- Cone: cone node\n- Cube: cube node\n- Cylinder: cylinder node\n- Sphere: sphere node\n- Torus: torus node\n- Line3D: 3D line\n\n**Layout**\n\n- D3Force3DLayout: 3D force-directed layout\n\n**Behaviors**\n\n- DragCanvas3D: drag canvas\n- ObserveCanvas3D: observe canvas\n- RollCanvas3D: rotate canvas\n- ZoomCanvas3D: zoom canvas\n\n**Plugin**\n\n- Light: light source\n\n## Register Extensions\n\nThe following extensions are required:\n\n- renderer\n- at least one 3D node\n- Line3D\n- Light\n\n> The renderer does not need to be registered, it can be passed in during the instantiation of Graph.\n\nRegister as follows:\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## Create 3D Graph\n\nAfter completing the above steps, you can create a 3D graph:\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... other options\n  // use 3d renderer\n  renderer,\n  node: {\n    type: 'sphere', // use 3d node\n    style: {\n      materialType: 'phong', // use Phong material\n    },\n  },\n  edge: {\n    type: 'line3d', // use 3D edge\n  },\n  plugins: [\n    {\n      type: 'light', // Add light source\n      // configure directional light\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\nYou can also refer to:\n\n- [Lite Solar System](/examples/feature/default/#lite-solar-system)\n- [3D Force Layout](/examples/layout/force-directed/#3d-force)\n\n## Tips\n\n`@antv/g6` has a built-in registered plugin for CameraSetting for camera configuration, refer to [plugin](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts).\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/3d.zh.md) -->\n---\ntitle: 使用 3D\norder: 5\n---\n\n## 安装依赖\n\n在使用 3D 能力之前，请首先安装 3D 扩展包：\n\n```bash\nnpm install @antv/g6-extension-3d --save\n```\n\n该扩展包导出了以下内容：\n\n- renderer：3D 渲染器\n\n**元素**\n\n- Capsule：胶囊节点\n- Cone：圆锥节点\n- Cube：立方体节点\n- Cylinder：圆柱节点\n- Sphere：球体节点\n- Torus：圆环节点\n- Line3D：3D 线\n\n**布局**\n\n- D3Force3DLayout：3D 力导向布局\n\n**交互**\n\n- DragCanvas3D：拖拽画布\n- ObserveCanvas3D：观察画布\n- RollCanvas3D：旋转画布\n- ZoomCanvas3D：缩放画布\n\n**插件**\n\n- Light：光源\n\n## 注册扩展\n\n其中下列扩展是必须的：\n\n- renderer\n- 至少一个 3D 节点\n- Line3D\n- Light\n\n> renderer 无需注册，实例化 Graph 过程中传入即可。\n\n使用如下方式进行注册：\n\n```ts\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { Sphere, Line3D, Light } from '@antv/g6-extension-3d';\n\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\nregister(ExtensionCategory.PLUGIN, 'light', Light);\n```\n\n## 创建 3D 图\n\n完成上述步骤后，即可创建 3D 图：\n\n```ts\nimport { Graph } from '@antv/g6';\nimport { renderer } from '@antv/g6-extension-3d';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 3D 渲染器\n  renderer,\n  node: {\n    type: 'sphere', // 使用 3D 节点\n    style: {\n      materialType: 'phong', // 使用 Phong 材质\n    },\n  },\n  edge: {\n    type: 'line3d', // 使用 3D 边\n  },\n  plugins: [\n    {\n      type: 'light', // 添加光源\n      // 配置方向光\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n你可以参考以下示例：\n\n- [精简太阳系](/examples/feature/default/#lite-solar-system)\n- [3D 力导向布局](/examples/layout/force-directed/#3d-force)\n\n## 其他\n\n`@antv/g6` 中内置注册了 `CameraSetting` 插件，可用于配置相机，具体可参考[插件](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts)。\n\n```typescript\n{\n  plugins: [\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n  ];\n}\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/bundle.en.md) -->\n---\ntitle: Bundle Project\norder: 6\n---\n\nIn general, if you are using modern build tools such as Webpack, Rollup, or ESBuild, you can easily build projects that depend on `@antv/g6`.\n\nSome build tools, such as Vite, use ESBuild as the underlying tool, so you can refer to ESBuild's configuration.\n\nBelow are some example configurations that you can refer to when building your project. If you find that these configurations do not work properly, make sure that your build tool version is up to date.\n\n## Bundle Project with Webpack\n\n1. Make sure that `webpack` and `webpack-cli` are installed in your project:\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. Refer to the following `webpack.config.js` for configuration:\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx webpack\n```\n\n> The above configuration works with `\"webpack\": \"^5.94.0\"`, `\"webpack-cli\": \"^5.1.4\"`.\n\n:::error{title=Webpack4}\n⚠️ It is strongly recommended that projects use Webpack 5. If you are using Webpack 4, follow the steps below to configure:\n\n1. Install the necessary dependencies: `babel-loader` (<9), `@babel/preset-env`, `@open-wc/webpack-import-meta-loader`\n\n> If you are using TypeScript, you also need to install `ts-loader`.\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. Modify the `webpack.config.js` configuration:\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> This configuration is for a standard webpack project. If you are using vue-cli, you should REMOVE the `mode: 'production'` option as it is unnecessary.\n\n## Bundle Project with Rollup\n\n1. First, make sure that `rollup` and the necessary plugins are installed in your project:\n\n- `@rollup/plugin-commonjs`: Used to load CommonJS modules\n- `@rollup/plugin-node-resolve`: Used to load Node.js modules\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. Refer to the following `rollup.config.js` for configuration:\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. Run the build command:\n\n```bash\nnpx rollup -c\n```\n\n## Bundle Project with ESBuild\n\n1. First, make sure that `esbuild` is installed in your project:\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. Run the build command:\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/bundle.zh.md) -->\n---\ntitle: 项目打包\norder: 6\n---\n\n通常情况下，如果你使用的现代构建工具，如 Webpack、Rollup 或 ESBuild，你可以很容易地构建依赖于 `@antv/g6` 的项目。\n\n一些构建工具例如 Vite，其底层是使用 ESBuild，因此你可以参考 ESBuild 的配置。\n\n下面是一些示例配置，你可以参考这些配置来构建你的项目。如果你发现这些配置无法正常工作，请确保你的构建工具版本较新。\n\n## 使用 Webpack 打包项目\n\n1. 确保你的项目中已经安装了 `webpack` 和 `webpack-cli`：\n\n```bash\nnpm install webpack webpack-cli --save-dev\n```\n\n2. 参考下面的 `webpack.config.js` 进行配置：\n\n```js\nconst path = require('path');\n\nmodule.exports = {\n  entry: './src/index.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'index.js',\n  },\n  mode: 'production',\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx webpack\n```\n\n> 上述配置在：\"webpack\": \"^5.94.0\"，\"webpack-cli\": \"^5.1.4\" 可以正常工作。\n\n:::error{title=Webpack4}\n⚠️ 强烈建议项目使用 Webpack 5，如果你使用的是 Webpack 4，按以下步骤配置：\n\n1. 安装相关依赖：babel-loader(<9)、@babel/preset-env、@open-wc/webpack-import-meta-loader\n\n> 如果你使用的 typescript，还需要安装 ts-loader\n\n```bash\nnpm install babel-loader@8 @babel/preset-env @open-wc/webpack-import-meta-loader --save-dev\n```\n\n2. 修改 `webpack.config.js` 配置：\n\n<embed src=\"@/common/manual/feature/webpack4.md\"></embed>\n:::\n> 如果你使用的是 vue-cli，请移除 mode: 'production' 配置，否则可能会影响开发模式下的构建性能。\n\n## 使用 Rollup 打包项目\n\n1. 首先，确保你的项目中已经安装了 `rollup` 及必要的插件：\n\n- `@rollup/plugin-commonjs`：用于加载 CommonJS 模块\n- `@rollup/plugin-node-resolve`：用于加载 Node.js 模块\n\n```bash\nnpm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve --save-dev\n```\n\n2. 参考下面的 `rollup.config.js` 进行配置：\n\n```js\nconst commonjs = require('@rollup/plugin-commonjs');\nconst resolve = require('@rollup/plugin-node-resolve');\n\nmodule.exports = {\n  input: 'src/index.ts',\n  output: {\n    file: 'dist/index.js',\n    format: 'umd',\n    name: 'project',\n  },\n  plugins: [resolve(), commonjs()],\n};\n```\n\n3. 执行构建命令：\n\n```bash\nnpx rollup -c\n```\n\n## 使用 ESBuild 打包项目\n\n1. 首先，确保你的项目中已经安装了 `esbuild`：\n\n```bash\nnpm install esbuild --save-dev\n```\n\n2. 执行构建命令：\n\n```bash\nnpx esbuild src/index.ts --bundle --outfile=dist/index.js\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/coordinate.en.md) -->\n---\ntitle: coordinate\norder: 2\n---\n\n## Overview\n\nThere are three coordinate systems in G6 5.0: Canvas, Viewport, and Client.\n\n### Canvas Coordinate System\n\nThe coordinate system used when drawing G6 elements is not affected by camera zooming or panning. To change the position of an element, you need to directly modify the element's position properties (x/y/z).\n\nThe canvas space is theoretically infinite. In the initial state (no panning, zoom ratio is 1), the origin of the canvas coordinate system is located at the upper-left corner of the viewport.\n\n### Viewport Coordinate System\n\nThe viewport coordinate system is the projection of the camera coordinate system. When the camera pans or zooms, the position of elements in the canvas will also change in the viewport coordinate system.\n\nThe size of the viewport is the size of the canvas DOM container. The origin of the viewport coordinate system is located at the upper-left corner of the viewport, with the x-axis pointing to the right and the y-axis pointing down.\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### Client Coordinate System\n\nThe client coordinate system has the browser's upper-left corner as the origin, with the x-axis pointing to the right and the y-axis pointing down.\n\nThe following figure describes the relationship between the viewport coordinate system and the client coordinate system:\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Coordinate System Conversion\n\nG6 provides methods for coordinate system conversion, making it easy to convert between different coordinate systems.\n\n- Canvas coordinate system to viewport coordinate system: [getViewportByCanvas](/en/api/coordinate#graphgetviewportbycanvaspoint)\n- Client coordinate system to canvas coordinate system: [getCanvasByClient](/en/api/coordinate#graphgetcanvasbyclientpoint)\n- Viewport coordinate system to canvas coordinate system: [getCanvasByViewport](/en/api/coordinate#graphgetcanvasbyviewportpoint)\n- Canvas coordinate system to client coordinate system: [getClientByCanvas](/en/api/coordinate#graphgetclientbycanvaspoint)\n\nOther related APIs are also provided:\n\n- Get the viewport center in viewport coordinates: [getCanvasCenter](/en/api/viewport#graphgetcanvascenter)\n- Get the viewport center in canvas coordinates: [getViewportCenter](/en/api/viewport#graphgetviewportcenter)\n- Get the position of the graph origin in the viewport coordinate system: [getPosition](/en/api/viewport#graphgetposition)\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/coordinate.zh.md) -->\n---\ntitle: 坐标系\norder: 2\n---\n\n## 概述\n\n在 G6 5.0 中主要会涉及三个坐标系：画布坐标系(Canvas)、视口坐标系(Viewport)和浏览器坐标系(Client)。\n\n### 画布坐标系\n\nG6 元素绘制时所使用的坐标系，其不受相机缩放、平移的影响，要改变一个元素的位置，需要直接修改元素的位置属性(x/y/z)。\n\n画布空间理论上是无限大的，在初始状态下（无平移、缩放倍率为1），画布坐标系的原点位于视口左上角位置。\n\n### 视口坐标系\n\n视口坐标系是相机坐标系的投影，当相机发生平移、缩放时，画布中元素位置在视口坐标系中的位置也会发生变化。\n\n视口的大小即画布 DOM 容器的大小，视口坐标系的原点位于视口左上角位置，x 轴正方向向右，y 轴正方向向下。\n\n![viewport](https://developer.mozilla.org/en-US/Web/API/Canvas_API/Tutorial/Drawing_shapes/canvas_default_grid.png)\n\n### 浏览器坐标系\n\n浏览器坐标系以浏览器左上角为原点，x 轴正方向向右，y 轴正方向向下。\n\n下图描述了视口坐标系和浏览器坐标系之间的关系：\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*HOcfToHFDIYAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 坐标系转换\n\nG6 提供了坐标系转换的方法，可以方便地在不同坐标系之间进行转换。\n\n- 画布坐标系转视口坐标系：[getViewportByCanvas](/api/coordinate#graphgetviewportbycanvaspoint)\n- 浏览器坐标系转画布坐标系：[getCanvasByClient](/api/coordinate#graphgetcanvasbyclientpoint)\n- 视口坐标系转画布坐标系：[getCanvasByViewport](/api/coordinate#graphgetcanvasbyviewportpoint)\n- 画布坐标系转浏览器坐标系：[getClientByCanvas](/api/coordinate#graphgetclientbycanvaspoint)\n\n另外还提供了其他相关 API：\n\n- 获取视口中心的视口坐标：[getCanvasCenter](/api/viewport#graphgetcanvascenter)\n- 获取视口中心的画布坐标：[getViewportCenter](/api/viewport#graphgetviewportcenter)\n- 获取图原点在视口坐标系中的位置：[getPosition](/api/viewport#graphgetposition)\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/download-image.en.md) -->\n---\ntitle: download-image\norder: 3\n---\n\nG6 5.0 only provides an API for exporting the canvas as a Base64 image ([toDataURL](/en/api/export-image#graphtodataurloptions)). If you need to download the image, you can use the following method:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=note}\nThe exported image may not contain the complete canvas content; the export range only includes the content within the Graph canvas. Some plugins use custom containers, canvases, etc., and this content will not appear in the exported image.\n:::\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/download-image.zh.md) -->\n---\ntitle: 下载图片\norder: 3\n---\n\nG6 5.0 仅提供导出画布为 Base64 图片的 API([toDataURL](/api/export-image#graphtodataurloptions))，如果需要下载图片，可以使用以下方法：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n:::warning{title=注意}\n导出的图片内容可能不会包含完整的画布内容，导出范围仅包含 Graph 画布中的内容。部分插件使用了自定义的容器、画布等，这部分内容不会出现在导出的图片中。\n:::\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/event.en.md) -->\n---\ntitle: Event\norder: 0\n---\n\n## Overview\n\nThe event system in G6 is encapsulated based on the event system of [G](https://g.antv.antgroup.com/en/api/event/intro), providing a wider range of event types and more convenient methods for event binding and unbinding.\n\n## Event Types\n\nThe event types in G6 are mainly divided into the following categories:\n\n1. Graph events\n2. Canvas events\n3. Element events\n\n### Graph Events\n\nGraph events refer to events associated with the entire graph instance, such as the graph's rendering completion event, the graph's update event, etc. The complete list of graph events can be found at [GraphEvent](/en/api/event#graph-lifecycle-events-graphevent).\n\n#### Listening to Graph Events\n\nListening to graph events is consistent with the default event listening method. For example, to listen to the graph's rendering completion event:\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### Canvas Events\n\nCanvas events refer to events associated with the canvas, such as the canvas's click event, the canvas's drag event, etc. The complete list of canvas events can be found at [CanvasEvent](/en/api/event#canvas-events-canvasevent).\n\n#### Listening to Canvas Events\n\nFor example, to listen to the canvas's click event:\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### Element Events\n\nElement events primarily refer to events that are triggered on element objects, such as a node's drag event, an edge's click event, etc. Elements are categorized into three types: nodes (`node`), edges (`edge`), and combos (`combo`). The complete list of corresponding events can be found at: [NodeEvent](/en/api/event#node-events-nodeevent), [EdgeEvent](/en/api/event#edge-events-edgeevent), [ComboEvent](/en/api/event#combo-events-comboevent).\n\n#### Listening to Element Events\n\nSimilar to canvas events, for example, to listen to a node's drag event and an edge's click event:\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## Event Listening and Unlistening\n\nG6 provides the following APIs for event listening and unlistening:\n\n### on\n\nAdd an event listener\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\nRemove an event listener\n\n```typescript\ngraph.off('event_name', handler);\n```\n\nWhen no arguments are passed, it will remove all event listeners:\n\n```typescript\ngraph.off();\n```\n\n### once\n\nAdd a one-time event listener, which means the event listener will be automatically removed after the event is triggered\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\nIf you want to manually trigger an event, you can use the `emit` method:\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/event.zh.md) -->\n---\ntitle: 事件\norder: 0\n---\n\n## 概述\n\nG6 中的事件系统是在 [G](https://g.antv.antgroup.com/api/event/intro) 的事件系统基础上进行了封装，提供了更多的事件类型，以及更加方便的事件绑定和解绑方法。\n\n## 事件类型\n\nG6 中的事件类型主要分为以下几类：\n\n1. 图(Graph)事件\n2. 画布(Canvas)事件\n3. 元素(Element)事件\n\n### 图事件\n\n图事件是指与整个图实例相关的事件，例如图的渲染完成事件、图的更新事件等。图事件的完整列表见[GraphEvent](/api/event#图表生命周期事件-graphevent)。\n\n#### 监听图事件\n\n图事件的监听与默认的事件监听方式一致，例如监听图的渲染完成事件：\n\n```typescript\nimport { Graph, GraphEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(GraphEvent.AFTER_RENDER, () => {\n  // event handler\n});\n```\n\n### 画布事件\n\n画布事件是指与画布相关的事件，例如画布的点击事件、画布的拖拽事件等。画布事件的完整列表见[CanvasEvent](/api/event#画布事件-canvasevent)。\n\n#### 监听画布事件\n\n例如监听画布的点击事件：\n\n```typescript\nimport { Graph, CanvasEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(CanvasEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n### 元素事件\n\n元素事件主要指在元素对象上触发的事件，例如节点的拖拽事件、边的点击事件等。元素分为节点(`node`)、边(`edge`)、组合(`combo`)三类，对应的事件完整列表分别见：[NodeEvent](/api/event#节点事件-nodeevent) 、[EdgeEvent](/api/event#边事件-edgeevent)、[ComboEvent](/api/event#combo事件-comboevent)。\n\n#### 监听元素事件\n\n与画布事件类似，例如监听节点的拖拽和边的点击事件：\n\n```ts\nimport { Graph, NodeEvent, EdgeEvent, ComboEvent } from '@antv/g6';\n\nconst graph = new Graph({\n  // ...\n});\n\ngraph.on(NodeEvent.DRAG, (event) => {\n  // event handler\n});\n\ngraph.on(EdgeEvent.CLICK, (event) => {\n  // event handler\n});\n\ngraph.on(ComboEvent.CLICK, (event) => {\n  // event handler\n});\n```\n\n## 事件监听与解除\n\nG6 提供以下 API 用于事件监听和解除：\n\n### on\n\n添加事件监听\n\n```typescript\nconst handler = (event) => {\n  // event handler\n};\n\ngraph.on('event_name', handler);\n```\n\n### off\n\n移除事件监听\n\n```typescript\ngraph.off('event_name', handler);\n```\n\n当不传入任何参数时，会移除所有事件监听：\n\n```typescript\ngraph.off();\n```\n\n### once\n\n添加一次性事件监听，即事件触发后会自动移除事件监听\n\n```typescript\ngraph.once('event_name', handler);\n```\n\n### emit\n\n如果你想手动触发一个事件，可以使用 `emit` 方法：\n\n```typescript\ngraph.emit('event_name', {\n  // event data\n});\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/iconfont.en.md) -->\n---\ntitle: Using Iconfont\norder: 4\n---\n\n## Overview\n\nWhy use iconfont? It offers great compatibility, a wide variety of icons, and multicolor options. For more details, please visit the [Alibaba Iconfont Platform](https://www.iconfont.cn).\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## Usage\n\n### Download Font Icons\n\nFirst, you need to download the desired font icons from the [iconfont](https://www.iconfont.cn) website. Create a project, select the required icons, and then download the generated icon files.\n\n### Add Font Icons\n\nAfter downloading, place the directory containing the icon font files (typically including `.eot`, `.woff`, `.ttf`, and `.svg` files, as well as the `iconfont.css` stylesheet) into your project.\n\nYou can choose how to include them. Below is an example of how to include them in HTML:\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### Using the Font\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // Corresponds to the `font-family` value in iconfont.css\n      iconText: '\\ue7f1', // Corresponds to the `content` value in iconfont.css, make sure to add `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### Utility Function `getIcon()`\n\nTo make it easier to retrieve icons, you can create a utility function `getIcon`. This function reads the icon information from the `iconfont.json` file and returns the corresponding Unicode character. Note that manually concatenating Unicode (`\\\\u${icon.unicode}`) won't work. Refer to [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint) for details.\n\nFirst, ensure you have an `iconfont.json` file containing the detailed icon information.\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\nUse it in your project:\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/iconfont.zh.md) -->\n---\ntitle: 使用 iconfont\norder: 4\n---\n\n## 概述\n\n为什么使用 iconfont？ 兼容性好、种类多、多色等。在此不做过多介绍，请直接移步 [阿里巴巴-iconfont 平台](https://www.iconfont.cn)。\n\n![iconfont](https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*rJ3lQa0HR-wAAAAAAAAAAABkARQnAQ)\n\n## 使用\n\n### 下载字体图标\n\n首先，你需要从 [iconfont](https://www.iconfont.cn) 网站下载所需的图标字体。创建一个项目并选择所需的图标，然后下载生成的图标文件。\n\n### 添加字体图标\n\n下载完成后，将包含图标字体文件的目录（通常包括 `.eot`、`.woff`、`.ttf` 和 `.svg` 文件，以及 `iconfont.css` 样式文件）放入你的项目中。\n\n引入方式可自行选择，下面为在 HTML 中引入的例子：\n\n```html\n<head>\n  <style>\n    @import 'path-to-iconfont/iconfont.css';\n  </style>\n</head>\n```\n\n### 使用字体\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: 'iconfont', // 对应 iconfont.css 中的 `font-family` 属性值\n      iconText: '\\ue7f1', // 对应 iconfont.css 中的 `content` 属性值，注意加 `u`\n      iconFill: '#7863FF'\n    }\n  }\n}\n```\n\n### 工具函数 `getIcon()`\n\n为了更方便地获取图标，可以创建一个工具函数 `getIcon`。该函数会从图标文件 `iconfont.json` 中读取图标信息并返回相应的 Unicode 字符。这里注意，手动拼接 unicode 是不行的（`\\\\u${icon.unicode}`）。详细参考 [MDN String.fromCodePoint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)。\n\n首先，确保你有一个 `iconfont.json` 文件，包含图标的详细信息。\n\n```js\nimport fonts from 'path-to-iconfont/iconfont.json';\n\nconst icons = fonts.glyphs.map((icon) => {\n  return {\n    name: icon.font_class,\n    unicode: String.fromCodePoint(icon.unicode_decimal), // `\\\\u${icon.unicode}`,\n  };\n});\n\nconst getIcon = (type: string) => {\n  const matchIcon = icons.find((icon) => {\n    return icon.name === type;\n  }) || { unicode: '', name: 'default' };\n  return matchIcon.unicode;\n};\n```\n\n在项目中使用：\n\n```js\n{\n  node: {\n    style: {\n      iconFontFamily: \"iconfont\",\n      iconText: getIcon('logo')\n    }\n  }\n}\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/renderer.en.md) -->\n---\ntitle: renderer\norder: 1\n---\n\nG6 uses Canvas as the default renderer, but also supports rendering with SVG and WebGL. To switch to the SVG or WebGL renderer, simply pass the `renderer` parameter during initialization.\n\n## Using the SVG Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the SVG renderer here\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## Using the WebGL Renderer\n\n1. Install the renderer dependency:\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. Configure the renderer:\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // All canvases will use the WebGL renderer here\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## Using Different Renderers for Different Layers\n\nG6 uses layered canvases for rendering, so `renderer` is a callback function that takes the canvas type as a parameter and returns the renderer instance. If you want to use different renderers on different canvases, you can configure it like this:\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // The main canvas uses the WebGL renderer, and the other canvases use the SVG renderer\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## Switch Renderers Dynamically\n\nG6 does not provide a API to switch the renderer, but you can still update the `renderer` option through the `setOptions` method.\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// Use the WebGL renderer by default\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// Switch to the SVG renderer\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n\n<!-- Skill/Rule: Further-reading Skill (packages/site/docs/manual/further-reading/renderer.zh.md) -->\n---\ntitle: 渲染器\norder: 1\n---\n\nG6 默认使用 Canvas 作为渲染器，但也支持通过 SVG 和 WebGL 进行渲染，要切换到 SVG 或 WebGL 渲染器，只需在初始化时传入 `renderer` 参数即可。\n\n## 使用 SVG 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-svg\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 SVG 渲染器\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## 使用 WebGL 渲染器\n\n1. 安装渲染器依赖：\n\n```bash\nnpm install @antv/g-webgl\n```\n\n2. 配置渲染器：\n\n```javascript\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other options\n  // 这里所有的画布都会使用 WebGL 渲染器\n  renderer: () => new WebGLRenderer(),\n});\n```\n\n## 分层使用不同的渲染器\n\nG6 采用了分层画布进行渲染，因此 `renderer` 是一个回调函数，参数是画布类型，返回渲染器实例，如果你想在不同的画布上使用不同的渲染器，可以这样配置：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\nconst graph = new Graph({\n  // ... other options\n  renderer: (layer) => {\n    // 主画布使用 WebGL 渲染器，其他画布使用 SVG 渲染器\n    if (layer === 'main') return new WebGLRenderer();\n    return new SVGRenderer();\n  },\n});\n```\n\n## 动态切换渲染器\n\nG6 没有提供单独的 API 来切换渲染器，但你仍可以通过 `setOptions` 方法来更新 `renderer` 参数：\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Renderer as WebGLRenderer } from '@antv/g-webgl';\n\n// 初始化时使用 WebGL 渲染器\nconst graph = new Graph({\n  // ... other options\n  renderer: () => new WebGLRenderer(),\n});\n\nawait graph.render();\n\n// 切换到 SVG 渲染器\ngraph.setOptions({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/installation.en.md) -->\n---\ntitle: Installation\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\nImport G6 in the code:\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\nVisit [G6 npm Example](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) to view the complete example code.\n\n## CDN\n\n`@antv/g6` Available on multiple CDNs:\n\n- unpkg: https://unpkg.com/@antv/g6@5/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\nImport G6 using a `script` tag:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\nVisit [G6 CDN Example](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) to view the complete example code.\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/installation.zh.md) -->\n---\ntitle: 安装\norder: 1\n---\n\n## npm\n\n```bash\n# npm\nnpm install @antv/g6 --save\n\n# pnpm\npnpm add @antv/g6\n\n# yarn\nyarn add @antv/g6\n```\n\n在代码中引入 G6：\n\n```js\nimport { Graph } from '@antv/g6';\n```\n\n访问 [G6 npm 示例](https://codesandbox.io/p/sandbox/using-g6-from-npm-d9spnr) 查看完整示例代码。\n\n## CDN\n\n`@antv/g6` 在多个 CDN 上提供：\n\n- unpkg: https://unpkg.com/@antv/g6@latest/dist/g6.min.js\n- jsDelivr: https://cdn.jsdelivr.net/npm/@antv/g6@5/dist/g6.min.js\n- npmmirror: https://registry.npmmirror.com/@antv/g6/5/files/dist/g6.min.js\n\n使用 `script` 标签引入 G6：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n访问 [G6 CDN 示例](https://codesandbox.io/p/sandbox/using-g6-from-cdn-xt9ty6) 查看完整示例代码。\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/angular.en.md) -->\n---\ntitle: angular\norder: 2\n---\n\nRefer to the example below, you can use G6 in Angular, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/angular.zh.md) -->\n---\ntitle: 在 Angular 中使用\norder: 2\n---\n\n参考下面的示例，你可以在 Angular 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-angular?file=src%2Fmain.ts)。\n\n<embed src=\"@/common/angular-snippet\"></embed>\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/react.en.md) -->\n---\ntitle: react\norder: 0\n---\n\n## Non-Strict Mode\n\nRefer to the example below, you can use G6 in React, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## Strict Mode\n\nIn strict mode, React intentionally mounts, unmounts, and remounts components in development. Create the Graph instance inside an effect, keep it in a ref, and destroy it in the cleanup callback so the first development-only mount does not leave a stale graph behind. The following complete example also shows how to register and render a React node.\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/react.zh.md) -->\n---\ntitle: 在 React 中使用\norder: 0\n---\n\n:::info{title=建议}\n如果你需要更完善的 React 与 G6 集成解决方案，可以使用 AntV 官方封装库 [`@antv/graphin`](https://github.com/antvis/graphin)。\n:::\n\n## 非严格模式\n\n参考下面的示例，你可以在 React 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-react?file=src/App.tsx) 。\n\n<embed src=\"@/common/react-snippet\"></embed>\n\n## 严格模式\n\n在严格模式下，React 会在开发环境中有意执行挂载、卸载、再挂载。请把 Graph 实例放在 effect 里创建，用 ref 保存，并在清理函数中销毁，这样第一次开发态挂载不会留下旧实例。下面的完整示例同时演示了如何注册和渲染 React 节点。\n\n<embed src=\"@/common/react-snippet-strict\"></embed>\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/vue.en.md) -->\n---\ntitle: vue\norder: 1\n---\n\n:::warning\nPlease do not pass Vue reactive data directly to the G6 instance, which may cause G6 to fail to render correctly, or even cause the page to crash.\n:::\n\nRefer to the example below, you can use G6 in Vue, and you can also view the [Live Example](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n\n\n<!-- Skill/Rule: Integration Skill (packages/site/docs/manual/getting-started/integration/vue.zh.md) -->\n---\ntitle: 在 Vue 中使用\norder: 1\n---\n\n:::warning{title=注意}\n请不要将 Vue 响应式数据直接传递给 G6 实例，这可能会导致 G6 无法正确渲染，甚至导致页面崩溃。\n:::\n\n参考下面的示例，你可以在 Vue 中使用 G6，也可以查看 [在线示例](https://stackblitz.com/edit/g6-in-vue?file=src/App.vue)。\n\n<embed src=\"@/common/vue-snippet\"></embed>\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/quick-start.en.md) -->\n---\ntitle: Quick Start\norder: 0\n---\n\n## Online Experience with G6\n\nVisit [Chart Examples](/en/examples) to experience G6 online without any environment setup.\n\n## Creating a Simple Graph\n\nIn this example, we will create a simple graph using G6 based on an HTML page.\n\nCopy the following code into an HTML file and then open this file in a browser:\n\n```html\n<!-- Prepare a container -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- Import G6's JS file -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\nYou will get a graph as shown below:\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\nLet's analyze the following code snippet:\n\n1. First, we create a `div` element to serve as the container for the graph:\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. Then, include the G6's JS file:\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. Use the `fetch` method to obtain the graph's data:\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. Finally, create an instance of the graph, pass in the configuration object, and call the `render` method to render the graph:\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\nIf you are using frameworks such as React, Vue, Angular, etc., you can refer to:\n\n- [Using G6 in React](./integration/react)\n- [Using G6 in Vue](./integration/vue)\n- [Using G6 in Angular](./integration/angular)\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/quick-start.zh.md) -->\n---\ntitle: 快速开始\norder: 0\n---\n\n## 在线体验 G6\n\n访问 [图表示例](/examples) 无需任何环境配置即可在线体验 G6。\n\n## 创建一个简单的图\n\n在本例子中，我们将基于 HTML 页面使用 G6 创建一个简单的图。\n\n将下面的代码复制到一个 HTML 文件中，然后在浏览器中打开这个文件：\n\n```html\n<!-- 准备一个容器 -->\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n\n<!-- 引入 G6 的 JS 文件 -->\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n\n<script>\n  const { Graph } = G6;\n\n  fetch('https://assets.antv.antgroup.com/g6/graph.json')\n    .then((res) => res.json())\n    .then((data) => {\n      const graph = new Graph({\n        container: 'container',\n        autoFit: 'view',\n        data,\n        node: {\n          style: {\n            size: 10,\n          },\n          palette: {\n            field: 'group',\n            color: 'tableau',\n          },\n        },\n        layout: {\n          type: 'd3-force',\n          manyBody: {},\n          x: {},\n          y: {},\n        },\n        behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n      });\n\n      graph.render();\n    });\n</script>\n```\n\n会得到如下所示的图：\n\n<embed src=\"@/common/manual/getting-started/quick-start/simple-graph.md\"></embed>\n\n下面分析一下这段代码：\n\n1. 首先我们创建一个 `div` 元素作为图的容器：\n\n```html\n<div id=\"container\" style=\"width: 500px; height: 500px\"></div>\n```\n\n2. 然后引入 G6 的 JS 文件：\n\n```html\n<script src=\"https://unpkg.com/@antv/g6@5/dist/g6.min.js\"></script>\n```\n\n3. 使用 `fetch` 方法获取图的数据：\n\n```js\nfetch('https://assets.antv.antgroup.com/g6/graph.json').then((res) => res.json());\n```\n\n4. 最后创建一个图实例，传入配置对象，并调用 `render` 方法渲染图：\n\n```js\nconst { Graph } = G6;\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      size: 10,\n    },\n    palette: {\n      field: 'group',\n      color: 'tableau',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    manyBody: {},\n    x: {},\n    y: {},\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n如果你使用 React、Vue、Angular 等框架，可以查看：\n\n- [在 React 中使用 G6](./integration/react)\n- [在 Vue 中使用 G6](./integration/vue)\n- [在 Angular 中使用 G6](./integration/angular)\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/step-by-step.en.md) -->\n---\ntitle: Step-by-step guide\norder: 3\n---\n\nThis tutorial will guide you through the development of a G6 chart from scratch, and along the way, you will learn and understand the main concepts of G6.\n\n## Create Application\n\nWe will use Vite to create a simple front-end application.\n\n### Initialization\n\nFirst, create an empty directory:\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\nInitialize the project:\n\n```bash\nnpm init -y\n```\n\nInstall G6:\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite is a new type of front-end build tool that is based on ESModule and can quickly start up projects.\n\nInstall Vite:\n\n```bash\nnpm install vite --save-dev\n```\n\nAdd a start script to the `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### Create Files\n\nCreate the `index.html` and `main.ts` files with the following content:\n\n**index.html**:\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### Start project\n\n```bash\nnpm run dev\n```\n\nOpen a web browser and visit the address output in the terminal (typically: http://127.0.0.1:5173/), and you will see a pop-up displaying \"Hello, G6!\".\n\n## Creating a Simple Graph\n\nNext, we will create a simple chart using G6.\n\n### Preparing the Data\n\nG6 uses JSON-formatted data to describe the graph, which usually includes nodes and edges. We will use the following prepared data:\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\nThe data includes two nodes and one edge. The `id` attribute for nodes is mandatory, and the position of each node is set in the `style`. The `source` and `target` attributes of the edge represent the `id` of the starting node and the ending node, respectively.\n\n### Creating and Drawing the Graph\n\nCreate an instance of the Graph, pass in a configuration object that includes the container and data, and then call the `render` method to draw the Graph:\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\nAs shown below, you can see that the chart has been successfully drawn:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### Element\n\nNext, we will introduce how to configure the style and types of elements in the canvas.\n\nG6 provides various mechanisms to configure element styles, which can be done in the data itself or within the chart instance. In the previous example, we configured the position of the nodes in the data. Next, we will configure the styles of nodes and edges in the graph configuration options:\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\nAs the code shows, we have configured the fill color of the nodes to be pink and the stroke color of the edges to be light green within the chart instance. You can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\nThe key parts are the `node.style` and `edge.style` options, which are used to configure the styles of nodes and edges, respectively.\n\n> In the subsequent code examples, we will only display the parts of the options. For the complete code of this project, please refer to the [Complete Example](https://codesandbox.io/s/g6-tutorial).\n\nNext, we will demonstrate more types of nodes by setting the node type:\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\nIn the code above, we set the `type` attribute of the node, which can be a string or a function. When `type` is a function, the argument of the function is the current node's data object, and the return value is the type of the node.\n\n> Similarly, each attribute under the `style` style of an element can also be a function, with the argument being the current element's data object.\n\n> You can even set the entire `style` property as a function, allowing you to dynamically set the element's style based on the data object.\n\nThe circular node (`circle`) is the default node type in G6. Here, we set the type of the first node to a circle and the type of the second node to a rectangle.\n\nAt the same time, we also set the size of the nodes to 20, so the first node is a circle with a radius of 10, and the second node is a square with a side length of 20.\n\n> If you want to set the size of the rectangular node to 20x10, you can set `size` to an array `[20, 10]`.\n\nYou can see the effect in the example below:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### Behaviors\n\nThe chart provided in the previous example is static. Next, we will add some interactive behaviors.\n\nG6 offers a variety of interactive behaviors. We will add a few commonly used Behaviors to allow users to drag, zoom the canvas, and drag nodes.\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\nTry dragging nodes and the canvas in the example below, and use the scroll wheel to zoom in and out on the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### Layout\n\nIn the previous example, we manually set the positions of the nodes. However, this can become very difficult when there are many nodes.\n\nLayout algorithms can automatically adjust the positions of nodes based on certain rules. G6 provides a variety of layout algorithms, such as tree layout, force-directed layout, and so on.\n\nFirst, generate a set of data that does not include position information:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nBy default, if a node does not have position information, G6 will place the node at the top-left corner, that is, at the coordinates `(0, 0)`.\n\nNext, we will use the `d3-force` layout algorithm, which is a force-directed layout algorithm that can simulate the forces of attraction and repulsion between nodes, allowing the nodes to automatically adjust to suitable positions.\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\nView the example below, and you can see that the nodes have automatically adjusted to suitable positions:\n\n<details>\n<summary>Complete Code</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### Palette\n\nSimilarly, when there are many nodes, manually setting the color of each node can become difficult. G6 provides a palette mechanism that makes it easy to assign colors to elements.\n\nPalettes typically assign colors to elements based on a specific field in the data, such as the type of node, the weight of an edge, etc.\n\nBelow, we add a `category` field in the data:\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\nThen, use the `tableau` palette to set the colors for the nodes, where the `field` attribute specifies the field in the data, and the `color` attribute specifies the name of the palette.\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> It is important to note that the `fill` style in `node.style` should be removed, as its priority is higher than the colors assigned by the palette.\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### Plugins\n\nThe plugin mechanism is an important feature of G6, which allows you to extend the functionality of G6 through plugins. G6 provides a wealth of built-in plugins, such as `tooltip`, `legend`, etc., and also supports user-defined plugins.\n\nBelow, we will use the `grid-line` plugin to add grid lines to the canvas:\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\nYou can see that grid lines have been added to the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\nThe plugin configuration mentioned above used a shorthand form. Most plugins support the passing of additional parameters. For example, the `grid-line` plugin allows you to configure the `follow` property to specify whether the grid lines should follow the canvas when it is dragged.\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\nTry dragging the canvas in the example below, and you will see that the grid lines move along with the canvas:\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## Summary\n\nIn this tutorial, we created a G6 chart from scratch and became acquainted with the main concepts of G6. We learned how to create a simple chart, how to configure the style and types of elements, how to add interactive behaviors, how to use layout algorithms, how to use palettes, and how to use plugins.\n\nFor a more detailed introduction to the concepts of G6, you can refer to [Core Concepts](/en/manual/graph/graph).\n\nDetailed explanations of options such as elements, layouts, and plugins can be found in the [API](/en/api/data).\n\n\n<!-- Skill/Rule: Getting-started Skill (packages/site/docs/manual/getting-started/step-by-step.zh.md) -->\n---\ntitle: 详细教程\norder: 3\n---\n\n本教程将引导你从头开始完成一个 G6 图表开发，并在过程中了解和学习 G6 的主要概念。\n\n## 创建应用\n\n我们将使用 Vite 来创建一个简单的前端应用。\n\n### 初始化\n\n首先创建一个空目录：\n\n```bash\nmkdir g6-tutorial\n\ncd g6-tutorial\n```\n\n初始化项目：\n\n```bash\nnpm init -y\n```\n\n安装 G6：\n\n```bash\nnpm install @antv/g6 --save\n```\n\nVite 是一个新型的前端构建工具，它基于 ESModule，可以快速启动项目。\n\n安装 Vite：\n\n```bash\nnpm install vite --save-dev\n```\n\n在 `package.json` 中添加启动脚本：\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"vite\"\n  }\n}\n```\n\n### 创建文件\n\n创建 `index.html` 和 `main.ts` 文件，内容如下：\n\n**index.html**：\n\n```html\n<!doctype html>\n<html>\n  <head>\n    <title>@antv/g6 Tutorial</title>\n  </head>\n  <body>\n    <div id=\"container\"></div>\n    <script type=\"module\" src=\"main.ts\"></script>\n  </body>\n</html>\n```\n\n**main.ts**：\n\n```typescript\nalert('Hello, G6!');\n```\n\n### 启动项目\n\n```bash\nnpm run dev\n```\n\n打开浏览器访问终端中输出的地址（通常为：http://127.0.0.1:5173/ ），你将看到一个弹窗显示 \"Hello, G6!\"。\n\n## 创建一个简单的图表\n\n接下来，我们将使用 G6 创建一个简单的图表。\n\n### 准备数据\n\nG6 使用 JSON 格式的数据来描述图，通常包括节点和边。我们将使用下面准备的数据：\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', style: { x: 50, y: 50 } },\n    { id: 'node-2', style: { x: 150, y: 50 } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2' }],\n};\n```\n\n数据中包括两个节点和一条边，节点的 `id` 属性是必须的，并在 `style` 设置了每个节点的位置。边的 `source` 和 `target` 属性分别表示边的起始节点 `id` 和结束节点 `id`。\n\n### 创建并绘制图表\n\n创建一个图表实例，传入一个配置对象，包括容器和数据，然后调用 `render` 方法渲染图表：\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n});\n\ngraph.render();\n```\n\n如下所示，可以看到图表已经顺利绘制出来：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/create-chart.md\"></embed>\n\n### 元素\n\n接下来将介绍如何配置画布中的元素样式和种类。\n\nG6 提供了多种机制来配置元素样式，可以在数据中进行配置，也可以在图表实例中进行配置。前面的示例中，我们在数据中配置了节点的位置，接下来我们在图配置项中配置节点和边的样式：\n\n<!-- TODO -->\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 50, y: 50 } },\n      { id: 'node-2', style: { x: 150, y: 50 } },\n    ],\n    edges: [{ source: 'node-1', target: 'node-2' }],\n  },\n  node: {\n    style: {\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n});\n\ngraph.render();\n```\n\n正如代码所示，我们在图表实例中配置了节点的填充颜色为粉色，边的描边颜色为浅绿色。你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-1.md\"></embed>\n\n其中的关键部分是 `node.style` 和 `edge.style` 配置项，分别用来配置节点和边的样式。\n\n> 在后续的代码示例中，我们仅展示配置项的部分代码，本项目的完整代码请查看 [完整示例](https://codesandbox.io/s/g6-tutorial)。\n\n下面我们将通过设置节点的类型来展示更多的节点种类：\n\n```js\n{\n  node: {\n    type: (datum) => datum.id === 'node-1' ? 'circle' : 'rect',\n    style: {\n      fill: 'pink',\n      size: 20\n    }\n  }\n}\n```\n\n上面的代码中，我们设置了节点的 `type` 属性，其值可以是一个字符串，也可以是一个函数。当 `type` 是一个函数时，函数的参数是当前节点的数据对象，函数的返回值是节点的类型。\n\n> 同样的，元素中 `style` 样式下的每个属性都可以是一个函数，函数的参数是当前元素的数据对象。\n\n> 你甚至可以将整个 `style` 属性设置为一个函数，这样你可以根据数据对象动态设置元素的样式。\n\n圆形节点(`circle`)是 G6 的默认节点类型，这里我们将第一个节点的类型设置为圆形，第二个节点的类型设置为矩形。\n\n同时我们还将节点的大小设置为 20，因此第一个节点是一个半径为 10 的圆形，第二个节点是一个边长为 20 的正方形。\n\n> 如果你想将矩形节点的大小设置为 20x10，可以将 `size` 设置为一个数组 `[20, 10]`。\n\n你可以在下面的示例中看到效果：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/elements-2.md\"></embed>\n\n### 交互\n\n在上面的例子中提供的图表是静态的，接下来我们将添加一些交互行为。\n\nG6 提供了多种交互行为，我们添加几个常用的交互，使得用户可以拖拽、缩放画布，拖拽节点。\n\n```js\n{\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'];\n}\n```\n\n尝试在下面的示例中拖拽节点和画布，并使用滚轮缩放画布：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/behaviors.md\"></embed>\n\n### 布局\n\n在上面的示例中，我们手动设置了节点的位置。但当节点数量较多时，这会变得非常困难。\n\n布局算法可以基于一定的规则自动调整节点的位置，G6 提供了多种布局算法，例如树形布局、力导向布局等。\n\n首先生成一组不包括位置信息的数据：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n默认情况下，如果节点没有位置信息，G6 会将节点放置在左上角，即 `(0, 0)`。\n\n接下来我们使用 `d3-force` 布局算法，它是一种力导向布局算法，可以模拟节点之间的引力和斥力，使得节点自动调整到合适的位置。\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n  },\n}\n```\n\n查看下面的示例，可以看到节点已经自动调整到合适的位置：\n\n<details>\n<summary>完整代码</summary>\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: {\n    nodes: Array.from({ length: 10 }).map((_, i) => ({ id: `node-${i}` })),\n    edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n  },\n  node: {\n    style: {\n      size: 20,\n      fill: 'pink',\n    },\n  },\n  edge: {\n    style: {\n      stroke: 'lightgreen',\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  layout: {\n    type: 'd3-force',\n  },\n});\n\ngraph.render();\n```\n\n</details>\n\n<embed src=\"@/common/manual/getting-started/step-by-step/layout.md\"></embed>\n\n### 色板\n\n同样的，当节点数量较多时，手动设置节点的颜色也会变得困难。G6 提供了色板机制，可以便捷地为元素设置颜色。\n\n色板通常会基于数据的某个字段为元素设置颜色，例如节点的类型、边的权重等。\n\n下面我们在数据中的添加 `category` 字段：\n\n```js\nconst data = {\n  nodes: Array.from({ length: 10 }).map((_, i) => ({\n    id: `node-${i}`,\n    data: { category: i === 0 ? 'central' : 'around' },\n  })),\n  edges: Array.from({ length: 9 }).map((_, i) => ({ source: `node-0`, target: `node-${i + 1}` })),\n};\n```\n\n然后使用 `tableau` 色板为节点设置颜色，`field` 属性指定了数据中的字段，`color` 属性指定了色板的名称。\n\n```js\n{\n  node: {\n    palette: {\n      field: 'category',\n      color: 'tableau',\n    }\n  }\n}\n```\n\n> 需要注意将 `node.style` 中的 `fill` 样式移除，因为其优先级高于色板分配的颜色。\n\n<embed src=\"@/common/manual/getting-started/step-by-step/palette.md\"></embed>\n\n### 插件\n\n插件机制是 G6 的一个重要特性，可以通过插件扩展 G6 的功能。G6 提供了丰富的内置插件，例如 `tooltip`、`legend` 等，也支持用户自定义插件。\n\n下面我们将使用 `grid-line` 插件为画布添加网格线：\n\n```js\n{\n  plugins: ['grid-line'],\n}\n```\n\n可以看到画布已经添加了网格线：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-1.md\"></embed>\n\n上面的插件配置项中使用了简写形式，大部分的插件都支持传递额外的参数，例如 `grid-line` 插件可以配置 `follow` 属性来指定拖拽画布时网格线是否跟随画布移动。\n\n```js\n{\n  plugins: [{ type: 'grid-line', follow: true }];\n}\n```\n\n尝试在下面的示例中拖拽画布，可以看到网格线跟随画布移动：\n\n<embed src=\"@/common/manual/getting-started/step-by-step/plugins-2.md\"></embed>\n\n## 小结\n\n在本教程中，我们从头开始创建了一个 G6 图表，并了解了 G6 的主要概念。我们学习了如何创建一个简单的图表，如何配置元素的样式和种类，如何添加交互行为，如何使用布局算法，如何使用色板，如何使用插件。\n\n关于 G6 更加详细的概念介绍可以在 [核心概念](/manual/graph/graph) 中查看。\n\n图的 API 详细说明可以在 [API](/api/graph) 中查看。\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/extension.en.md) -->\n---\ntitle: extension\norder: 9\n---\n\n## Concept\n\nExtension is an important concept in G6, it is a general term for all expandable parts in G6, including the following types:\n\n- Animation\n- Behavior\n- Element\n  - Node\n  - Edge\n  - Combo\n- Layout\n- Palette\n- Plugin\n- Theme\n- Transform\n\n## Register Extension\n\nG6 provides the `register` function for registering extensions, for example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// # Registering Nodes\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\nThe first parameter of the `register` function is the type of the extension, the second parameter is the name of the extension, and the third parameter is the implementation of the extension(refer to the custom-related sections in the documentation for each extension type).\n\nDifferent types of extensions **can** use the same extension name, but when registering extensions of the same type, only the first registration will take effect.\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## Use Extension\n\nThe configuration location for different types of extensions varies, but all are used by specifying the name that was used during registration, for example:\n\n- Using node extensions: `options.node.type`\n- Using edge extensions: `options.edge.type`\n- Using combo extensions: `options.combo.type`\n- Using behavior extensions: `options.behaviors`\n- Using layout extensions: `options.layout.type`\n- Using plugin extensions: `options.plugins`\n- Using theme extensions: `options.theme`\n- Using data transform extensions: `options.transform`\n- Using palette extensions: `options.node.palette`, `options.edge.palette`, etc.\n- Using animation extensions: `options.node.animate`, `options.edge.animate`, etc.\n\n## Get Extension\n\nG6 provides the `getExtension` and `getExtensions` methods to obtain a single extension and all extensions of a specified type, respectively, for example:\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// To get the implementation of the node extension registered with the name 'custom-node'\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// Retrieve all registered node extension implementations\ngetExtensions(ExtensionCategory.NODE);\n```\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/extension.zh.md) -->\n---\ntitle: Extension - 扩展\norder: 9\n---\n\n## 概念\n\n扩展 (Extension) 是 G6 中的一个重要概念，它是 G6 中所有可扩展部分的统称，包括以下几种：\n\n- 动画 (Animation)\n- 交互 (Behavior)\n- 元素 (Element)\n- 节点 (Node)\n  - 边 (Edge)\n  - 组合 (Combo)\n- 布局 (Layout)\n- 色板 (Palette)\n- 插件 (Plugin)\n- 主题 (Theme)\n- 数据转换 (Transform)\n\n## 注册扩展\n\nG6 提供了 `register` 函数用于注册扩展，例如：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomNode } from './my-custom-node';\n\n// 注册节点\nregister(ExtensionCategory.NODE, 'custom-node', CustomNode);\n```\n\n`register` 函数的第一个参数是扩展的类型，第二个参数是扩展的名称，第三个参数是扩展的实现(扩展实现参考各扩展类型所在文档的自定义相关章节)。\n\n不同的扩展类型之间**可以**使用相同的扩展名称，但同一类型的扩展重复注册时仅会在第一次注册时生效。\n\n<!-- TODO: 详细的参数签名见：[API 文档](/api/reference/g6/register) -->\n\n```typescript\n// ✅\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.COMBO, 'custom-name', CustomCombo);\n\n// ❌\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\nregister(ExtensionCategory.NODE, 'custom-name', CustomNode);\n```\n\n## 使用扩展\n\n不同的扩展类型的配置位置有所不同，但都是通过指定注册时所使用的名称来使用扩展，例如：\n\n- 使用节点扩展：`options.node.type`\n- 使用边扩展：`options.edge.type`\n- 使用组合扩展：`options.combo.type`\n- 使用交互扩展：`options.behaviors`\n- 使用布局扩展：`options.layout.type`\n- 使用插件扩展：`options.plugins`\n- 使用主题扩展：`options.theme`\n- 使用数据转换扩展：`options.transform`\n- 使用色板扩展：`options.node.palette` `options.edge.palette` 等\n- 使用动画扩展：`options.node.animate` `options.edge.animate` 等\n\n## 获取扩展\n\nG6 提供了 `getExtension` 和 `getExtensions` 方法分别用于获取指定扩展类型下的单个扩展和所有扩展，例如：\n\n```typescript\nimport { getExtension, getExtensions, ExtensionCategory } from '@antv/g6';\n\n// 获取注册的名称为 'custom-node' 的节点扩展实现\ngetExtension(ExtensionCategory.NODE, 'custom-node');\n\n// 获取所有注册的节点扩展实现\ngetExtensions(ExtensionCategory.NODE);\n```\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/extensions.en.md) -->\n---\n\ntitle: Built-in Extensions\norder: 4\n\nThe G6 built-in extensions and registered types are as follows:\n\n## Animations\n\n| Extension     | Registration Type |\n| ------------- | ----------------- |\n| ComboCollapse | 'combo-collapse'  |\n| ComboExpand   | 'combo-expand'    |\n| NodeCollapse  | 'node-collapse'   |\n| NodeExpand    | 'node-expand'     |\n| PathIn        | 'path-in'         |\n| PathOut       | 'path-out'        |\n| Fade          | 'fade'            |\n| Translate     | 'translate'       |\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].animation.[stage]`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    animation: {\n      update: 'translate', // Only use translation animation in the update stage\n    },\n  },\n});\n```\n\n## Behaviors\n\n| Extension                 | Registration Type             | Description                                    |\n| ------------------------- | ----------------------------- | ---------------------------------------------- |\n| BrushSelect               | 'brush-select'                | /                                              |\n| ClickSelect               | 'click-select'                | /                                              |\n| CollapseExpand            | 'collapse-expand'             | /                                              |\n| CreateEdge                | 'create-edge'                 | /                                              |\n| DragCanvas                | 'drag-canvas'                 | /                                              |\n| DragElementForce          | 'drag-element-force'          | Drag element when use d3-force layout          |\n| DragElement               | 'drag-element'                | /                                              |\n| FixElementSize            | 'fix-element-size'            | Keep the size of element during zooming canvas |\n| FocusElement              | 'focus-element'               | /                                              |\n| HoverActivate             | 'hover-activate'              | /                                              |\n| LassoSelect               | 'lasso-select'                | /                                              |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | Hide elements during manipulate the canvas     |\n| ScrollCanvas              | 'scroll-canvas'               | /                                              |\n| ZoomCanvas                | 'zoom-canvas'                 | /                                              |\n\nUsage:\n\nIn `GraphOptions.behaviors`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## Elements\n\n### Nodes\n\n| Extension | Registration Type |\n| --------- | ----------------- |\n| circle    | Circle            |\n| diamond   | Diamond           |\n| ellipse   | Ellipse           |\n| hexagon   | Hexagon           |\n| html      | HTML              |\n| image     | Image             |\n| rect      | Rect              |\n| star      | Star              |\n| donut     | Donut             |\n| triangle  | Triangle          |\n\nUsage:\n\n1. In `GraphOptions.data.nodes[number].type`;\n2. In `GraphOptions.node.type`;\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### Edges\n\n| Extension       | Registration Type  | Description                   |\n| --------------- | ------------------ | ----------------------------- |\n| Cubic           | 'cubic'            | Cubic Bezier Curve            |\n| Line            | 'line'             | /                             |\n| Polyline        | 'polyline'         | /                             |\n| Quadratic       | 'quadratic'        | Quadratic Bezier Curve        |\n| CubicHorizontal | 'cubic-horizontal' | Horizontal Cubic Bezier Curve |\n| CubicVertical   | 'cubic-vertical'   | Vertical Cubic Bezier Curve   |\n| CubicRadial     | 'cubic-radial'     | Radial Cubic Bezier Curve     |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.edges[number].type`;\n2. In `GraphOptions.edge.type`;\n\n### Combos\n\n| Extension   | Registration Type |\n| ----------- | ----------------- |\n| CircleCombo | 'circle'          |\n| RectCombo   | 'rect'            |\n\nUsage(like `Nodes`):\n\n1. In `GraphOptions.data.combos[number].type`;\n2. In `GraphOptions.combo.type`;\n\n## Layouts\n\n| Extension           | Registration Type | Description                     |\n| ------------------- | ----------------- | ------------------------------- |\n| AntVDagreLayout     | 'antv-dagre'      | /                               |\n| ComboCombinedLayout | 'combo-combined'  | /                               |\n| CompactBoxLayout    | 'compact-box'     | /                               |\n| ForceAtlas2Layout   | 'force-atlas2'    | /                               |\n| CircularLayout      | 'circular'        | /                               |\n| ConcentricLayout    | 'concentric'      | /                               |\n| D3ForceLayout       | 'd3-force'        | /                               |\n| DagreLayout         | 'dagre'           | /                               |\n| DendrogramLayout    | 'dendrogram'      | /                               |\n| ForceLayout         | 'force'           | /                               |\n| FruchtermanLayout   | 'fruchterman'     | /                               |\n| GridLayout          | 'grid'            | /                               |\n| IndentedLayout      | 'indented'        | /                               |\n| MDSLayout           | 'mds'             | Multidimensional Scaling Layout |\n| MindmapLayout       | 'mindmap'         | /                               |\n| RadialLayout        | 'radial'          | /                               |\n| RandomLayout        | 'random'          | /                               |\n\nUsage:\n\nIn `GraphOptions.layout`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## Palettes\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\nUsage:\n\nIn `GraphOptions.[node|edge|combo].palette`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## Themes\n\n| Registration Type |\n| ----------------- |\n| dark              |\n| light             |\n\nUsage:\n\nIn `GraphOptions.theme`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  theme: 'dark',\n});\n```\n\n## Plugins\n\n| Extension      | Registration Type  |\n| -------------- | ------------------ |\n| BubbleSets     | 'bubble-sets'      |\n| EdgeFilterLens | 'edge-filter-lens' |\n| GridLine       | 'grid-line'        |\n| Background     | 'background'       |\n| Contextmenu    | 'contextmenu'      |\n| Fisheye        | 'fisheye'          |\n| Fullscreen     | 'fullscreen'       |\n| History        | 'history'          |\n| Hull           | 'hull'             |\n| Legend         | 'legend'           |\n| Minimap        | 'minimap'          |\n| Snapline       | 'snapline'         |\n| Timebar        | 'timebar'          |\n| Toolbar        | 'toolbar'          |\n| Tooltip        | 'tooltip'          |\n| Watermark      | 'watermark'        |\n\nUsage:\n\nIn `GraphOptions.plugins`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## Transforms\n\n| Extension            | Registration Type        | Description |\n| -------------------- | ------------------------ | ----------- |\n| ProcessParallelEdges | 'process-parallel-edges' | /           |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签    |\n\nUsage:\n\nIn `GraphOptions.transform`, for example:\n\n```ts\nconst graph = new Graph({\n  // ... other options\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## Shapes\n\n| Registration Type |\n| ----------------- |\n| circle            |\n| ellipse           |\n| group             |\n| html              |\n| image             |\n| line              |\n| path              |\n| polygon           |\n| polyline          |\n| rect              |\n| text              |\n| label             |\n| badge             |\n\nUsage:\n\nIn the [upsert](http://localhost:8000/en/manual/custom-extension/element#methods) method of the element class when customizing the shape, pass the second parameter:\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/extensions.zh.md) -->\n---\ntitle: 内置扩展\norder: 4\n---\n\nG6 内置扩展及注册扩展类型如下：\n\n## 动画\n\n| 扩展          | 注册类型         | 描述     |\n| ------------- | ---------------- | -------- |\n| ComboCollapse | 'combo-collapse' | 组合收起 |\n| ComboExpand   | 'combo-expand'   | 组合展开 |\n| NodeCollapse  | 'node-collapse'  | 节点收起 |\n| NodeExpand    | 'node-expand'    | 节点展开 |\n| PathIn        | 'path-in'        | 路径进入 |\n| PathOut       | 'path-out'       | 路径退出 |\n| Fade          | 'fade'           | 渐变     |\n| Translate     | 'translate'      | 平移     |\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].animation.[stage]` 中使用，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    animation: {\n      update: 'translate', // 更新阶段仅使用平移动画\n    },\n  },\n});\n```\n\n## 交互\n\n| 扩展                      | 注册类型                      | 描述                   |\n| ------------------------- | ----------------------------- | ---------------------- |\n| BrushSelect               | 'brush-select'                | 框选                   |\n| ClickSelect               | 'click-select'                | 点击选中               |\n| CollapseExpand            | 'collapse-expand'             | 展开/收起元素          |\n| CreateEdge                | 'create-edge'                 | 创建边                 |\n| DragCanvas                | 'drag-canvas'                 | 拖拽画布               |\n| DragElementForce          | 'drag-element-force'          | 力导向拖拽元素         |\n| DragElement               | 'drag-element'                | 拖拽元素               |\n| FixElementSize            | 'fix-element-size'            | 缩放画布时固定元素大小 |\n| FocusElement              | 'focus-element'               | 聚焦元素               |\n| HoverActivate             | 'hover-activate'              | 悬停激活               |\n| LassoSelect               | 'lasso-select'                | 套索选择               |\n| OptimizeViewportTransform | 'optimize-viewport-transform' | 操作画布时隐藏元素     |\n| ScrollCanvas              | 'scroll-canvas'               | 滚动画布               |\n| ZoomCanvas                | 'zoom-canvas'                 | 缩放画布               |\n\n配置方式：\n\n在 `GraphOptions.behaviors` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n## 元素\n\n### 节点\n\n| 扩展     | 注册类型 | 描述       |\n| -------- | -------- | ---------- |\n| circle   | Circle   | 圆形节点   |\n| diamond  | Diamond  | 菱形节点   |\n| ellipse  | Ellipse  | 椭圆节点   |\n| hexagon  | Hexagon  | 六边形节点 |\n| html     | HTML     | HTML节点   |\n| image    | Image    | 图片节点   |\n| rect     | Rect     | 矩形节点   |\n| star     | Star     | 星形节点   |\n| donut    | Donut    | 甜甜圈节点 |\n| triangle | Triangle | 三角形节点 |\n\n配置方式：\n\n1. 在 `GraphOptions.data.nodes[number].type` 中配置；\n2. 在 `GraphOptions.node.type` 中配置；\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  data: {\n    nodes: [{ id: 'node-1', type: 'circle' }],\n  },\n  node: {\n    type: 'circle',\n  },\n});\n```\n\n### 边\n\n| 扩展            | 注册类型           | 描述               |\n| --------------- | ------------------ | ------------------ |\n| Cubic           | 'cubic'            | 三次贝塞尔曲线     |\n| Line            | 'line'             | 直线               |\n| Polyline        | 'polyline'         | 折线               |\n| Quadratic       | 'quadratic'        | 二次贝塞尔曲线     |\n| CubicHorizontal | 'cubic-horizontal' | 水平三次贝塞尔曲线 |\n| CubicVertical   | 'cubic-vertical'   | 垂直三次贝塞尔曲线 |\n| CubicRadial     | 'cubic-radial'     | 径向三次贝塞尔曲线 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.edges[number].type` 中配置；\n2. 在 `GraphOptions.edge.type` 中配置；\n\n### 组合\n\n| 扩展        | 注册类型 | 描述     |\n| ----------- | -------- | -------- |\n| CircleCombo | 'circle' | 圆形组合 |\n| RectCombo   | 'rect'   | 矩形组合 |\n\n配置方式同 `节点`：\n\n1. 在 `GraphOptions.data.combos[number].type` 中配置；\n2. 在 `GraphOptions.combo.type` 中配置；\n\n## 布局\n\n| 扩展                | 注册类型         | 描述                   |\n| ------------------- | ---------------- | ---------------------- |\n| AntVDagreLayout     | 'antv-dagre'     | AntV Dagre 布局        |\n| ComboCombinedLayout | 'combo-combined' | 组合布局               |\n| CompactBoxLayout    | 'compact-box'    | 紧凑树                 |\n| ForceAtlas2Layout   | 'force-atlas2'   | ForceAlas2 力导向布局  |\n| CircularLayout      | 'circular'       | 环形布局               |\n| ConcentricLayout    | 'concentric'     | 同心圆布局             |\n| D3ForceLayout       | 'd3-force'       | D3 力导向布局          |\n| DagreLayout         | 'dagre'          | Dagre 布局             |\n| DendrogramLayout    | 'dendrogram'     | 生态树                 |\n| ForceLayout         | 'force'          | 力导向布局             |\n| FruchtermanLayout   | 'fruchterman'    | Fruchterman 力导向布局 |\n| GridLayout          | 'grid'           | 网格布局               |\n| IndentedLayout      | 'indented'       | 缩进树                 |\n| MDSLayout           | 'mds'            | 高维数据降维布局       |\n| MindmapLayout       | 'mindmap'        | 脑图树                 |\n| RadialLayout        | 'radial'         | 径向布局               |\n| RandomLayout        | 'random'         | 随机布局               |\n\n配置方式：\n\n在 `GraphOptions.layout` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'force',\n  },\n});\n```\n\n## 色板\n\n<embed src=\"@/common/manual/getting-started/extensions/palettes.md\"></embed>\n\n配置方式：\n\n在 `GraphOptions.[node|edge|combo].palette` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  node: {\n    palette: 'tableau',\n  },\n});\n```\n\n## 主题\n\n| 注册类型 | 描述     |\n| -------- | -------- |\n| dark     | 深色主题 |\n| light    | 浅色主题 |\n\n配置方式：\n\n在 `GraphOptions.theme` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  theme: 'dark',\n});\n```\n\n## 插件\n\n| 扩展           | 注册类型           | 描述       |\n| -------------- | ------------------ | ---------- |\n| BubbleSets     | 'bubble-sets'      | 气泡集     |\n| EdgeFilterLens | 'edge-filter-lens' | 边过滤镜   |\n| GridLine       | 'grid-line'        | 网格线     |\n| Background     | 'background'       | 背景       |\n| Contextmenu    | 'contextmenu'      | 上下文菜单 |\n| Fisheye        | 'fisheye'          | 鱼眼放大镜 |\n| Fullscreen     | 'fullscreen'       | 全屏展示   |\n| History        | 'history'          | 历史记录   |\n| Hull           | 'hull'             | 轮廓包围   |\n| Legend         | 'legend'           | 图例       |\n| Minimap        | 'minimap'          | 小地图     |\n| Snapline       | 'snapline'         | 对齐线     |\n| Timebar        | 'timebar'          | 时间条     |\n| Toolbar        | 'toolbar'          | 工具栏     |\n| Tooltip        | 'tooltip'          | 提示框     |\n| Watermark      | 'watermark'        | 水印       |\n\n配置方式：\n\n在 `GraphOptions.plugins` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  plugins: ['minimap', 'contextmenu'],\n});\n```\n\n## 数据转换\n\n| 扩展                 | 注册类型                 | 描述     |\n| -------------------- | ------------------------ | -------- |\n| ProcessParallelEdges | 'process-parallel-edges' | 平行边   |\n| PlaceRadialLabels    | 'place-radial-labels'    | 径向标签 |\n\n配置方式：\n\n在 `GraphOptions.transforms` 中配置，示例：\n\n```ts\nconst graph = new Graph({\n  // ... 其他配置\n  transform: ['process-parallel-edges', 'place-radial-labels'],\n});\n```\n\n## 图形\n\n| 注册类型 | 描述   |\n| -------- | ------ |\n| circle   | 圆形   |\n| ellipse  | 椭圆   |\n| group    | 分组   |\n| html     | HTML   |\n| image    | 图片   |\n| line     | 直线   |\n| path     | 路径   |\n| polygon  | 多边形 |\n| polyline | 折线   |\n| rect     | 矩形   |\n| text     | 文本   |\n| label    | 标签   |\n| badge    | 徽标   |\n\n使用方式：\n\n自定义图形时，元素类成员方法 [upsert](/manual/element/node/custom-node) 方法第二个参数传入：\n\n```ts\nthis.upsert('shape-key', 'text', { text: 'label', fontSize: 16 }, this);\n```\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/graph.en.md) -->\n---\ntitle: Graph\norder: 0\n---\n\n## Overview\n\n### Definition of Graph\n\nIn Chinese, the character \"图\" (Graph) can often be used to represent many different concepts, such as image,shape,and chart or diagram,etc.\n\nIn Graph Theory, a graph is a mathematical structure used to model pairwise relationships between objects, which we typically represent with nodes (or Vertex) and edges (or Link) to denote the objects and the relationships between them.\n\nThe \"graph\" in G6:\n\n- Conceptually, it is the \"graph\" from Graph Theory, a data structure composed of nodes and edges.\n- Visually, a \"graph\" is a figure composed of a set of graphical elements representing nodes and edges.\n- In terms of code implementation, a \"graph\" is a class capable of transforming data into a graphical display.\n\n### Types of Graph\n\nGraph Theory categorizes graphs into many different types based on their structure and properties, such as:\n\n- Directed Graph and Undirected Graph\n- Weighted Graph and Unweighted Graph\n- Simple Graph and Multigraph\n- Cyclic Graph and Acyclic Graph\n- Connected Graph and Disconnected Graph\n- Complete Graph and Non-Complete Graph\n- Sparse Graph and Dense Graph\n- ...\n\nIn G6, we provide a universal graph representation capable of depicting the various types of graphs mentioned above, for example:\n\n- Directed Graph and Undirected Graph: Defined by the start and end points of the edges.\n- Weighted Graph and Unweighted Graph: Defined by the `weight` data on the edges.\n- Simple Graph and Multigraph: Defined by the uniqueness of the edges.\n- ...\n\n### Use Scenarios\n\nGraphs are a very versatile data structure that can be used to represent a variety of scenarios, such as:\n\n- Social Networks\n- Knowledge Graphs\n- Traffic Networks\n- Power Grids\n\nIn G6, we provide a rich expression capability for graphs that can meet the needs of different scenarios. We also offer a wealth of interactive and animated effects to make the graphs more vivid and intuitive.\n\n## Use G6 Graph\n\nTo create a Graph with G6, you first need to import the `@antv/g6` library, and then instantiate the Graph class.\n\n> For installation instructions, refer to: [Getting Started - Installation](/en/manual/getting-started/installation)\n\nThe Graph class accepts an instantiation argument object, known as **options** (Options, in visualization theory it is referred to as: `Specification`), which is used to configure the graph's data, element styles, layout, interactions, etc.\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 600,\n  // ... other other options\n});\n```\n\n:::warning{title=note}\nThe instantiation process only configures the basic information of the graph. To render the graph onto the page, you still need to call the `render` method.\n:::\n\n- To learn how to quickly create a graph, please refer to [Quick Start](/en/manual/getting-started/quick-start).\n- For more detailed information about the configuration options, please refer to [Options](/en/manual/graph/option).\n- To gain an in-depth understanding of the concepts within the configuration options, please read the rest of the content in this section.\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/graph.zh.md) -->\n---\ntitle: Graph - 图\norder: 0\n---\n\n## 什么是 Graph\n\n中文字“图”在大家的传统认知里指的是图画、图像，而图论与可视化中的“图”—— Graph 则有着更精确的定位：主体（objects）与关系（relationships）的组成。它甚至不局限于视觉，主体与关系的数据也可以称为图。\n\n> —— 摘自 [AntV 专栏](https://zhuanlan.zhihu.com/aiux-antv) 文章：[Graph Visualization · 知多少 之 《HelloWorld 图可视化》](https://zhuanlan.zhihu.com/p/83685690)。\n\n在 G6 中，Graph 对象是图的载体，它包含了图上的所有元素（节点、边等），同时挂载了图的相关操作（如交互监听、元素操作、渲染等）。\n\nGraph 对象的完整生命周期包括：\n\n1. **创建**: 通过 `new Graph(options)` 实例化\n2. **初始化**: 在创建时进行内部初始化\n3. **渲染**: 调用 `graph.render()` 进行首次渲染\n4. **更新**: 通过各种 API 更新图的数据和配置\n5. **销毁**: 调用 `graph.destroy()` 销毁实例并释放资源\n\n## 使用 G6 Graph\n\n要使用 G6 创建 Graph，首先需要引入 `@antv/g6` 库，然后实例化 Graph 类。\n\n> 安装教程参考：[开始使用 - 安装](/manual/getting-started/installation)\n\nGraph 类接收一个实例化参数对象，称之为**配置项**(Options，在可视化理论中将其称为：`Specification`)，用于配置图的数据、元素样式、布局、交互等。\n\n```typescript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container', // 通过 DOM ID 指定容器\n  width: 800, // 画布宽高（若容器已设尺寸可省略）\n  height: 600,\n  data: {\n    // 初始数据\n    nodes: [{ id: 'start', data: { label: 'Hello G6!' } }],\n  },\n});\n```\n\n:::warning{title=注意}\n实例化过程仅是配置图的基本信息，要将图渲染到页面上，还需要调用 `render` 方法\n:::\n\n## 图配置项\n\n通过下表速查图的配置项，更多类型定义说明和详细用法请参考 [API - 图配置项](/manual/graph/option)。\n\n| 属性             | 类型                               | 默认值      | 描述                                                          |\n| ---------------- | ---------------------------------- | ----------- | ------------------------------------------------------------- |\n| container        | string \\| HTMLElement \\| Canvas    | -           | 图容器，可以是 DOM 元素 ID、DOM 元素实例或 Canvas 实例        |\n| width            | number                             | 容器宽度    | 画布宽度(像素)                                                |\n| height           | number                             | 容器高度    | 画布高度(像素)                                                |\n| autoFit          | 'view' \\| 'center' \\| object       | -           | 自动适配策略，'view'(适应视图)或'center'(居中)                |\n| autoResize       | boolean                            | false       | 是否在窗口大小变化时自动调整画布大小                          |\n| background       | string                             | -           | 画布背景色，也作为导出图片时的背景色                          |\n| canvas           | CanvasConfig                       | -           | 画布配置                                                      |\n| cursor           | Cursor                             | `'default'` | 指针样式                                                      |\n| devicePixelRatio | number                             | 2           | 设备像素比                                                    |\n| padding          | number \\| number[]                 | -           | 画布内边距，在自适应时会根据内边距进行适配                    |\n| renderer         | (layer: string) => IRenderer       | -           | 手动指定渲染器                                                |\n| rotation         | number                             | 0           | 旋转角度(弧度)                                                |\n| zoom             | number                             | 1           | 缩放比例                                                      |\n| zoomRange        | [number, number]                   | [0.01, 10]  | 缩放比例的限制范围                                            |\n| x                | number                             | -           | 视口 x 坐标                                                   |\n| y                | number                             | -           | 视口 y 坐标                                                   |\n| data             | GraphData                          | -           | 图数据，详见 [数据](/manual/data)                             |\n| node             | NodeOptions                        | -           | 节点全局配置，详见 [节点](/manual/element/node/overview)      |\n| edge             | EdgeOptions                        | -           | 边全局配置，详见 [边](/manual/element/edge/overview)          |\n| combo            | ComboOptions                       | -           | 组合全局配置，详见 [组合](/manual/element/combo/overview)     |\n| animation        | boolean \\| AnimationEffectTiming   | -           | 全局动画配置，详见 [动画](/manual/animation/animation)        |\n| theme            | string \\| false                    | `'light'`   | 主题配置，支持 `'light'`、`'dark'` 或自定义主题名             |\n| layout           | LayoutOptions \\| LayoutOptions[]   | -           | 布局配置，详见 [布局](/manual/layout/overview)                |\n| behaviors        | (string \\| CustomBehaviorOption)[] | -           | 交互行为配置，详见 [交互](/manual/behavior/overview)          |\n| plugins          | (string \\| CustomPluginOption)[]   | -           | 插件配置，详见 [插件](/manual/plugin/overview)                |\n| transforms       | TransformOptions                   | -           | 数据转换器配置，详见 [数据转换器](/manual/transform/overview) |\n\n## 图属性\n\n图实例提供了一些只读属性，用于获取图的状态信息：\n\n| 属性      | 类型    | 描述                     |\n| --------- | ------- | ------------------------ |\n| destroyed | boolean | 当前图实例是否已被销毁   |\n| rendered  | boolean | 当前图实例是否已完成渲染 |\n\n## 参考示例\n\n### 完整的创建和配置示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\ngraph.render();\n```\n\n```typescript\nimport { Graph } from '@antv/g6';\n\n// 创建图实例\nconst graph = new Graph({\n  // 基础配置\n  container: 'container',\n  width: 300,\n  height: 200,\n  padding: 30,\n  autoResize: true,\n\n  // 视口配置\n  zoom: 0.8,\n  autoFit: 'view',\n  padding: 20,\n\n  // 主题配置\n  theme: 'dark',\n\n  // 节点配置\n  node: {\n    style: {\n      fill: '#7FFFD4',\n      stroke: '#5CACEE',\n      lineWidth: 2,\n    },\n  },\n\n  // 边配置\n  edge: {\n    style: {\n      stroke: '#A4D3EE',\n      lineWidth: 1.5,\n      endArrow: true,\n    },\n  },\n\n  // 布局配置\n  layout: {\n    type: 'force',\n    preventOverlap: true,\n    linkDistance: 100,\n  },\n\n  // 交互行为\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n\n  // 初始数据\n  data: {\n    nodes: [\n      { id: 'node1', data: { label: '节点1' } },\n      { id: 'node2', data: { label: '节点2' } },\n    ],\n    edges: [{ source: 'node1', target: 'node2', data: { label: '关系' } }],\n  },\n});\n\n// 渲染图\ngraph.render();\n```\n\n- 要了解如何快速创建一个图，请参考[快速上手](/manual/getting-started/quick-start)。\n- 要深入了解配置项中个部分的概念，请阅读本章节的其他内容。\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/option.en.md) -->\n---\ntitle: Options\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\nWhether to automatically fit the canvas. ⚠️ **Note**: Each time `render` is executed, it will adapt according to `autoFit`.\n\nTwo basic adaptation modes:\n\n- `'view'` - Automatically scale to ensure all content is visible within the view\n- `'center'` - Center the content without changing the zoom level\n\nMore precise adaptation control can be achieved through object form:\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // Adaptation type: 'view' or 'center'\n    options: {\n      // Only applicable to 'view' type\n      when: 'overflow', // When to adapt: 'overflow' (only when content overflows) or 'always' (always adapt)\n      direction: 'x', // Adaptation direction: 'x', 'y', or 'both'\n    },\n    animation: {\n      // Adaptation animation effect\n      duration: 1000, // Animation duration (milliseconds)\n      easing: 'ease-in-out', // Animation easing function\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| Property  | Description                                                                                                                                                             | Type                       | Default    | Required |\n| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | -------- |\n| when      | Adaptation occurs under the following conditions <br/> - `'overflow'` adapt only when content overflows <br/> - `'always'` always adapt                                 | `'overflow'` \\| `'always'` | `'always'` |          |\n| direction | Adapt only in the specified direction <br/> - `'x'` adapt only in x direction <br/> - `'y'` adapt only in y direction <br/> - `'both'` adapt in both x and y directions | `'x'` \\| `'y'` \\| `'both'` | `'both'`   |          |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true to enable default animation, false to disable animation\n  | {\n      easing?: string; // Animation easing function: 'ease-in-out', 'ease-in', 'ease-out', 'linear'\n      duration?: number; // Animation duration (milliseconds)\n    };\n```\n\n## autoResize\n\n> _boolean_ **Default:** `false`\n\nWhether to automatically resize the canvas.\n\nImplemented based on the `window.onresize` event. When the browser window size changes, the canvas will automatically resize to fit the container.\n\n## background\n\n> _string_\n\nCanvas background color.\n\nThis color is used as the background color when exporting images. Any valid CSS color value can be used, such as hexadecimal, RGB, RGBA, etc.\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\nCanvas configuration. Related configuration items under GraphOptions (such as `container`, `width`, `height`, `devicePixelRatio`, `background`, `cursor`) are shortcut configuration items and will be converted to canvas configuration items.\n\n#### CanvasConfig\n\n| Property         | Description                                                                                | Type                                                                           | Default | Required |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------- | -------- |\n| container        | Canvas container                                                                           | string \\| HTMLElement                                                          | -       |          |\n| devicePixelRatio | Device pixel ratio                                                                         | number                                                                         | -       |          |\n| width            | Canvas width                                                                               | number                                                                         | -       |          |\n| height           | Canvas height                                                                              | number                                                                         | -       |          |\n| cursor           | Cursor style, same as [GraphOptions.cursor](#cursor)                                       | string                                                                         | -       |          |\n| background       | Canvas background color                                                                    | string                                                                         | -       |          |\n| renderer         | Renderer, same as [GraphOptions.renderer](#renderer)                                       | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -       |          |\n| enableMultiLayer | Whether to enable multi-layer. Non-dynamic parameter, effective only during initialization | boolean                                                                        | -       |          |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\nCanvas container, can be one of the following three assignments:\n\n- ID string of the DOM element, such as `'container'`\n- HTML element object, such as `document.getElementById('container')`\n- Canvas instance, such as `new Canvas(options)`, where `options` is of type [CanvasConfig](#canvasconfig).\n\n## cursor\n\n> string\n\nCursor style, controls the cursor shape when hovering over the canvas. Any valid CSS cursor value can be used.\n\nSupported values include: `'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'.\n\nCursor values are referenced from [MDN - cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor).\n\n## devicePixelRatio\n\n> _number_\n\nDevice pixel ratio.\n\nUsed for high-definition screens, the default is [window.devicePixelRatio](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio).\n\n## width\n\n> _number_\n\nCanvas width. If not set, the container width will be automatically obtained.\n\n## height\n\n> _number_\n\nCanvas height. If not set, the container height will be automatically obtained.\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\nManually specify the renderer\n\nG6 uses a layered rendering approach, divided into four layers: `background`, `main`, `label`, `transient`. Users can set the renderer for each layer of the canvas through this configuration item.\n\n**Example**: Use SVG renderer for rendering\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\nCanvas padding\n\nUsually, during adaptation, it will be adapted according to the padding. It can be a single value (same padding on all sides) or an array form (specify the padding for top, right, bottom, left in order).\n\n**Example:**\n\n```javascript\n// Single value\nconst graph1 = new Graph({\n  padding: 20, // 20 pixels of padding on all sides\n});\n\n// Array form\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // Padding for top, right, bottom, left\n});\n```\n\n## rotation\n\n> _number_ **Default:** `0`\n\nRotation angle (in radians)\n\n## x\n\n> _number_\n\nViewport x coordinate, sets the initial horizontal position of the viewport.\n\n## y\n\n> _number_\n\nViewport y coordinate, sets the initial vertical position of the viewport.\n\n## zoom\n\n> _number_ **Default:** `1`\n\nSets the initial zoom level of the viewport, 1 means 100% (original size).\n\n## zoomRange\n\n> _[number, number]_ **Default:** `[0.01, 10]`\n\nZoom range, limits the minimum and maximum scale that users can zoom.\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\nEnable or disable global animation\n\nWhen configured as an animation option, animation will be enabled, and this animation configuration will be used as the base configuration for global animation.\n\n#### AnimationEffectTiming\n\n| Property   | Description                    | Type                                                                | Default     | Required |\n| ---------- | ------------------------------ | ------------------------------------------------------------------- | ----------- | -------- |\n| delay      | Animation delay time           | number                                                              | -           |          |\n| direction  | Animation direction            | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |          |\n| duration   | Animation duration             | number                                                              | -           |          |\n| easing     | Animation easing function      | string                                                              | -           |          |\n| fill       | Fill mode after animation ends | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |          |\n| iterations | Animation iteration count      | number                                                              | -           |          |\n\n**Example:**\n\n```javascript\n// Simple enable\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// Detailed configuration\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // Animation duration (milliseconds)\n    easing: 'ease-in-out', // Easing function\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\nData.\n\n#### GraphData\n\n| Property | Description | Type                      | Default | Required |\n| -------- | ----------- | ------------------------- | ------- | -------- |\n| nodes    | Node data   | [NodeData](#nodedata)[]   | -       | ✓        |\n| edges    | Edge data   | [EdgeData](#edgedata)[]   | -       | ✓        |\n| combos   | Combo data  | [ComboData](#combodata)[] | -       | ✓        |\n\n#### NodeData\n\n| Property | Description                                                                                                                                         | Type           | Default | Required |\n| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the node, used to distinguish different nodes                                                                                 | string         | -       | ✓        |\n| type     | Node type, built-in node type name or custom node name                                                                                              | string         | -       |          |\n| data     | Node data, used to store custom data for the node, such as node name, description, etc. Can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Node style, including visual attributes such as position, size, color, etc.                                                                         | object         | -       |          |\n| states   | Initial state of the node, such as selected, activated, hovered, etc.                                                                               | string[]       | -       |          |\n| combo    | ID of the combo to which it belongs, used to organize the hierarchical relationship of nodes, if none, it is null                                   | string \\| null | -       |          |\n| children | Collection of child node IDs, used only in tree graph scenarios                                                                                     | string[]       | -       |          |\n\n#### EdgeData\n\n| Property | Description                                                                                                    | Type     | Default | Required |\n| -------- | -------------------------------------------------------------------------------------------------------------- | -------- | ------- | -------- |\n| source   | Starting node ID of the edge                                                                                   | string   | -       | ✓        |\n| target   | Target node ID of the edge                                                                                     | string   | -       | ✓        |\n| id       | Unique identifier for the edge                                                                                 | string   | -       |          |\n| type     | Edge type, built-in edge type name or custom edge name                                                         | string   | -       |          |\n| data     | Edge data, used to store custom data for the edge, can be accessed in style mapping through callback functions | object   | -       |          |\n| style    | Edge style, including visual attributes such as line color, width, arrow, etc.                                 | object   | -       |          |\n| states   | Initial state of the edge                                                                                      | string[] | -       |          |\n\n#### ComboData\n\n| Property | Description                                                                                                      | Type           | Default | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | -------------- | ------- | -------- |\n| id       | Unique identifier for the combo                                                                                  | string         | -       | ✓        |\n| type     | Combo type, built-in combo type name or custom combo name                                                        | string         | -       |          |\n| data     | Combo data, used to store custom data for the combo, can be accessed in style mapping through callback functions | object         | -       |          |\n| style    | Combo style                                                                                                      | object         | -       |          |\n| states   | Initial state of the combo                                                                                       | string[]       | -       |          |\n| combo    | Parent combo ID. If there is no parent combo, it is null                                                         | string \\| null | -       |          |\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- Read [Data](/en/manual/data) to learn more about graph data, including but not limited to data formats, how to manipulate data, etc.\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\nNode configuration options.\n\n#### NodeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default  | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | -------- | -------- |\n| type      | Node type, built-in node type name or custom node name                           | [Type](/en/manual/element/node/base-node#type)           | `circle` |          |\n| style     | Node style, including color, size, etc.                                          | [Style](/en/manual/element/node/base-node#style)         | -        |          |\n| state     | Define the style of the node in different states                                 | [State](/en/manual/element/node/base-node#state)         | -        |          |\n| palette   | Define the color palette of the node, used to map colors based on different data | [Palette](/en/manual/element/node/base-node#palette)     | -        |          |\n| animation | Define the animation effect of the node                                          | [Animation](/en/manual/element/node/base-node#animation) | -        |          |\n\nSee [Node](/en/manual/element/node/base-node) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // Node type\n    style: {\n      fill: '#e6f7ff', // Fill color\n      stroke: '#91d5ff', // Border color\n      lineWidth: 1, // Border width\n      r: 20, // Radius\n      labelText: (d) => d.id, // Label text\n    },\n    // Node state style\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\nEdge configuration options\n\n#### EdgeOptions\n\n| Property  | Description                                                                      | Type                                                     | Default | Required |\n| --------- | -------------------------------------------------------------------------------- | -------------------------------------------------------- | ------- | -------- |\n| type      | Edge type, built-in edge type name or custom edge name                           | [Type](/en/manual/element/edge/base-edge#type)           | `line`  |          |\n| style     | Edge style, including color, size, etc.                                          | [Style](/en/manual/element/edge/base-edge#style)         | -       |          |\n| state     | Define the style of the edge in different states                                 | [State](/en/manual/element/edge/base-edge#state)         | -       |          |\n| palette   | Define the color palette of the edge, used to map colors based on different data | [Palette](/en/manual/element/edge/base-edge#palette)     | -       |          |\n| animation | Define the animation effect of the edge                                          | [Animation](/en/manual/element/edge/base-edge#animation) | -       |          |\n\nSee [Edge](/en/manual/element/edge/base-edge) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // Edge type\n    style: {\n      stroke: '#91d5ff', // Edge color\n      lineWidth: 2, // Edge width\n      endArrow: true, // Whether there is an arrow\n    },\n    // Edge state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\nCombo configuration options\n\n| Property  | Description                                                                       | Type                                                       | Default  | Required |\n| --------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | -------- |\n| type      | Combo type, built-in combo type name or custom combo name                         | [Type](/en/manual/element/combo/base-combo#type)           | `circle` |          |\n| style     | Combo style, including color, size, etc.                                          | [Style](/en/manual/element/combo/base-combo#style)         | -        |          |\n| state     | Define the style of the combo in different states                                 | [State](/en/manual/element/combo/base-combo#state)         | -        |          |\n| palette   | Define the color palette of the combo, used to map colors based on different data | [Palette](/en/manual/element/combo/base-combo#palette)     | -        |          |\n| animation | Define the animation effect of the combo                                          | [Animation](/en/manual/element/combo/base-combo#animation) | -        |          |\n\nSee [Combo](/en/manual/element/combo/base-combo) for details\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // Combo type\n    style: {\n      fill: '#f0f0f0', // Background color\n      stroke: '#d9d9d9', // Border color\n      lineWidth: 1, // Border width\n    },\n    // Combo state style\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\nLayout configuration options, can be an object (normal layout) or an array (pipeline layout).\n\n**Example**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // Force-directed layout\n    preventOverlap: true, // Prevent node overlap\n    nodeStrength: -50, // Repulsion between nodes\n    edgeStrength: 0.5, // Elastic coefficient of edges\n    iterations: 200, // Number of iterations\n    animation: true, // Enable layout animation\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\nSet the theme of the chart, can be the built-in `'light'`, `'dark'` theme, or the name of a custom theme. Set to `false` to use no theme.\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure the interaction behaviors of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // Enable canvas dragging with default configuration\n    'zoom-canvas', // Enable canvas zooming with default configuration\n    {\n      type: 'drag-element', // Custom configuration for dragging elements\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // Only allow dragging nodes\n    },\n    function () {\n      console.log(this); // Output graph instance\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- View [Interaction Overview](/en/manual/behavior/overview) to learn more about interaction principles\n- Browse [Built-in Interactions](/en/manual/behavior/auto-adapt-label) to get a list of all built-in interactions and their configuration options\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nSet the plugins of the chart, can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // Enable minimap with default configuration\n    {\n      type: 'grid', // Enable grid background\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // Enable toolbar\n      key: 'graph-toolbar',\n      position: 'top-right', // Position\n    },\n  ],\n});\n```\n\n- View [Plugin Overview](/en/manual/plugin/overview) to learn more about plugin principles\n- Browse [Built-in Plugins](/en/manual/plugin/background) to get a list of all built-in plugins and their configuration options\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\nConfigure data processing, used to process data before rendering, does not affect the original data. Can be a string (using default configuration), an object (custom configuration), or a function (dynamic configuration, the graph instance can be accessed within the function).\n\n**Example:**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // Process parallel edges with default configuration\n    {\n      type: 'map-node-size', // Map node size based on node data\n      field: 'value', // Use the value of the field\n      max: 50, // Maximum radius\n      min: 20, // Minimum radius\n    },\n  ],\n});\n```\n\n- View [Data Processing Overview](/en/manual/transform/overview) to learn more about data processing principles\n- Browse [Built-in Data Processing](/en/manual/transform/map-node-size) to get a list of all built-in data processing and their configuration options\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** Extension type */\n  type: string;\n  /** Extension key, i.e., unique identifier */\n  key?: string;\n}\n```\n\n\n<!-- Skill/Rule: Graph Skill (packages/site/docs/manual/graph/option.zh.md) -->\n---\ntitle: Options 配置项\norder: 0\n---\n\n## autoFit\n\n> _{ type: 'view'; options?: [FitViewOptions](#fitviewoptions); animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| { type: 'center'; animation?: [ViewportAnimationEffectTiming](#viewportanimationeffecttiming); } \\| 'view' \\| 'center'_\n\n是否自动适应画布。⚠️ **注意**：每次执行 `render` 时，都会根据 `autoFit` 进行自适应。\n\n两种基本自适应模式：\n\n- `'view'` - 自动缩放，确保所有内容都在视图内可见\n- `'center'` - 内容居中显示，但不改变缩放比例\n\n还可通过对象形式实现更精细的自适应控制：\n\n```javascript\nconst graph = new Graph({\n  autoFit: {\n    type: 'view', // 自适应类型：'view' 或 'center'\n    options: {\n      // 仅适用于 'view' 类型\n      when: 'overflow', // 何时适配：'overflow'(仅当内容溢出时) 或 'always'(总是适配)\n      direction: 'x', // 适配方向：'x'、'y' 或 'both'\n    },\n    animation: {\n      // 自适应动画效果\n      duration: 1000, // 动画持续时间(毫秒)\n      easing: 'ease-in-out', // 动画缓动函数\n    },\n  },\n});\n```\n\n#### FitViewOptions\n\n| 属性      | 描述                                                                                                           | 类型                       | 默认值     | 必选 |\n| --------- | -------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------- | ---- |\n| when      | 在以下情况下进行适配 <br/> - `'overflow'` 仅当图内容超出视口时进行适配 <br/> - `'always'` 总是进行适配         | `'overflow`' \\| `'always'` | `'always'` |      |\n| direction | 仅对指定方向进行适配 <br/> - `'x'` 仅适配 x 方向 <br/> - `'y'` 仅适配 y 方向 <br/> - `'both'` 适配 x 和 y 方向 | `'x`' \\| `'y`' \\| `'both'` | `'both'`   |      |\n\n#### ViewportAnimationEffectTiming\n\n```typescript\ntype ViewportAnimationEffectTiming =\n  | boolean // true 启用默认动画，false 禁用动画\n  | {\n      easing?: string; // 动画缓动函数：'ease-in-out'、'ease-in'、'ease-out'、'linear'\n      duration?: number; // 动画持续时间(毫秒)\n    };\n```\n\n## autoResize\n\n> _boolean_ **默认值:** `false`\n\n是否自动调整画布大小。\n\n基于 `window.onresize` 事件实现。当浏览器窗口大小变化时，画布将自动调整大小以适应容器。\n\n## background\n\n> _string_\n\n画布背景色。\n\n该颜色作为导出图片时的背景色。可以使用任何有效的 CSS 颜色值，如十六进制、RGB、RGBA 等。\n\n## canvas\n\n> [CanvasConfig](#canvasconfig)\n\n画布配置。GraphOptions 下相关配置项（如 `container`、`width`、`height`、`devicePixelRatio`、`background`、`cursor`）为快捷配置项，会被转换为 canvas 配置项。\n\n#### CanvasConfig\n\n| 属性             | 描述                                                   | 类型                                                                           | 默认值 | 必填 |\n| ---------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------ | ------ | ---- |\n| container        | 画布容器                                               | string \\| HTMLElement                                                          | -      |      |\n| devicePixelRatio | 设备像素比                                             | number                                                                         | -      |      |\n| width            | 画布宽度                                               | number                                                                         | -      |      |\n| height           | 画布高度                                               | number                                                                         | -      |      |\n| cursor           | 指针样式，与 [GraphOptions.cursor](#cursor) 配置相同   | string                                                                         | -      |      |\n| background       | 画布背景色                                             | string                                                                         | -      |      |\n| renderer         | 渲染器，与 [GraphOptions.renderer](#renderer) 配置相同 | (layer: `'background'` \\| `'main'` \\| `'label'` \\| `'transient'`) => IRenderer | -      |      |\n| enableMultiLayer | 是否启用多图层。非动态参数，仅在初始化时生效           | boolean                                                                        | -      |      |\n\n## container\n\n> _string \\|_ _HTMLElement_ _\\|_ Canvas\n\n画布容器，可以是以下三种赋值之一：\n\n- DOM 元素的 ID 字符串，如 `'container'`\n- HTML 元素对象，如 `document.getElementById('container')`\n- Canvas 实例，如 `new Canvas(options)`，其中 `options` 为 [CanvasConfig](#canvasconfig) 类型。\n\n## cursor\n\n> string\n\n指针样式，控制鼠标悬停在画布上时的光标形状。可以使用任何有效的 CSS cursor 值。\n\n支持的值有： `'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'`。\n\n这里的 Cursor 值参考 [MDN - cursor](https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor)。\n\n## devicePixelRatio\n\n> _number_\n\n设备像素比。\n\n用于高清屏的设备像素比，默认为 [window.devicePixelRatio](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/devicePixelRatio)。\n\n## width\n\n> _number_\n\n画布宽度。如果未设置，则会自动获取容器宽度。\n\n## height\n\n> _number_\n\n画布高度。如果未设置，则会自动获取容器高度。\n\n## renderer\n\n> _(layer: 'background' \\| 'main' \\| 'label' \\| 'transient') =>_ _IRenderer_\n\n手动指定渲染器\n\nG6 采用了分层渲染的方式，分为 `background`、`main`、`label`、`transient` 四层，用户可以通过该配置项分别设置每层画布的渲染器。\n\n**示例**: 使用 SVG 渲染器进行渲染\n\n```javascript\nimport { Renderer as SVGRenderer } from '@antv/g-svg';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  renderer: () => new SVGRenderer(),\n});\n```\n\n## padding\n\n> _number \\| number[]_\n\n画布内边距\n\n通常在自适应时，会根据内边距进行适配。可以是单个数值（四边相同）或者数组形式（按顺序指定上、右、下、左的内边距）。\n\n**示例：**\n\n```javascript\n// 单个数值\nconst graph1 = new Graph({\n  padding: 20, // 四边均为 20 像素的内边距\n});\n\n// 数组形式\nconst graph2 = new Graph({\n  padding: [20, 40, 20, 40], // 上、右、下、左的内边距\n});\n```\n\n## rotation\n\n> _number_ **默认值:** `0`\n\n旋转角度（以弧度为单位）\n\n## x\n\n> _number_\n\n视口 x 坐标，设置视口的初始水平位置。\n\n## y\n\n> _number_\n\n视口 y 坐标，设置视口的初始垂直位置。\n\n## zoom\n\n> _number_ **默认值:** `1`\n\n设置视口的初始缩放级别，1 表示 100%（原始大小）。\n\n## zoomRange\n\n> _[number, number]_ **默认值:** `[0.01, 10]`\n\n缩放范围，限制用户可以缩放的最小和最大比例。\n\n## animation\n\n> _boolean \\| [AnimationEffectTiming](#animationeffecttiming)_\n\n启用或关闭全局动画\n\n为动画配置项时，会启用动画，并将该动画配置作为全局动画的基础配置。\n\n#### AnimationEffectTiming\n\n| 属性       | 描述                 | 类型                                                                | 默认值      | 必选 |\n| ---------- | -------------------- | ------------------------------------------------------------------- | ----------- | ---- |\n| delay      | 动画延迟时间         | number                                                              | -           |      |\n| direction  | 动画方向             | `'alternate'` \\| `'alternate-reverse'` \\| `'normal'` \\| `'reverse'` | `'forward'` |      |\n| duration   | 动画持续时间         | number                                                              | -           |      |\n| easing     | 动画缓动函数         | string                                                              | -           |      |\n| fill       | 动画结束后的填充模式 | `'auto'` \\| `'backwards'` \\| `'both'` \\| `'forwards'` \\| `'none'`   | `'none'`    |      |\n| iterations | 动画迭代次数         | number                                                              | -           |      |\n\n**示例：**\n\n```javascript\n// 简单启用\nconst graph1 = new Graph({\n  animation: true,\n});\n\n// 详细配置\nconst graph2 = new Graph({\n  animation: {\n    duration: 500, // 动画持续时间（毫秒）\n    easing: 'ease-in-out', // 缓动函数\n  },\n});\n```\n\n## data\n\n> [GraphData](#graphdata)\n\n数据。\n\n#### GraphData\n\n| 属性   | 描述     | 类型                      | 默认值 | 必选 |\n| ------ | -------- | ------------------------- | ------ | ---- |\n| nodes  | 节点数据 | [NodeData](#nodedata)[]   | -      | ✓    |\n| edges  | 边数据   | [EdgeData](#edgedata)[]   | -      | ✓    |\n| combos | 组合数据 | [ComboData](#combodata)[] | -      | ✓    |\n\n#### NodeData\n\n| 属性     | 描述                                                                                         | 类型           | 默认值 | 必选 |\n| -------- | -------------------------------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id       | 节点的唯一标识符，用于区分不同的节点                                                         | string         | -      | ✓    |\n| type     | 节点类型，内置节点类型名称或者自定义节点的名称                                               | string         | -      |      |\n| data     | 节点数据，用于存储节点的自定义数据，例如节点的名称、描述等。可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style    | 节点样式，包括位置、大小、颜色等视觉属性                                                     | object         | -      |      |\n| states   | 节点初始状态，如选中、激活、悬停等                                                           | string[]       | -      |      |\n| combo    | 所属的组合 ID，用于组织节点的层级关系，如果没有则为 null                                     | string \\| null | -      |      |\n| children | 子节点 ID 集合，仅在树图场景下使用                                                           | string[]       | -      |      |\n\n#### EdgeData\n\n| 属性   | 描述                                                             | 类型     | 默认值 | 必选 |\n| ------ | ---------------------------------------------------------------- | -------- | ------ | ---- |\n| source | 边起始节点 ID                                                    | string   | -      | ✓    |\n| target | 边目标节点 ID                                                    | string   | -      | ✓    |\n| id     | 边的唯一标识符                                                   | string   | -      |      |\n| type   | 边类型，内置边类型名称或者自定义边的名称                         | string   | -      |      |\n| data   | 边数据，用于存储边的自定义数据，可以在样式映射中通过回调函数获取 | object   | -      |      |\n| style  | 边样式，包括线条颜色、宽度、箭头等视觉属性                       | object   | -      |      |\n| states | 边初始状态                                                       | string[] | -      |      |\n\n#### ComboData\n\n| 属性   | 描述                                                                 | 类型           | 默认值 | 必选 |\n| ------ | -------------------------------------------------------------------- | -------------- | ------ | ---- |\n| id     | 组合的唯一标识符                                                     | string         | -      | ✓    |\n| type   | 组合类型，内置组合类型名称或者自定义组合名称                         | string         | -      |      |\n| data   | 组合数据，用于存储组合的自定义数据，可以在样式映射中通过回调函数获取 | object         | -      |      |\n| style  | 组合样式                                                             | object         | -      |      |\n| states | 组合初始状态                                                         | string[]       | -      |      |\n| combo  | 组合的父组合 ID。如果没有父组合，则为 null                           | string \\| null | -      |      |\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  data: {\n    nodes: [\n      { id: 'node1', style: { x: 100, y: 100 } },\n      { id: 'node2', style: { x: 200, y: 200 } },\n    ],\n    edges: [{ id: 'edge1', source: 'node1', target: 'node2' }],\n    combos: [{ id: 'combo1', style: { x: 150, y: 150 } }],\n  },\n});\n```\n\n- 阅读 [数据](/manual/data) 深入了解图数据，包括不限于数据格式、如何操作数据等。\n\n## node\n\n> [NodeOptions](#nodeoptions)\n\n节点配置项。\n\n#### NodeOptions\n\n| 属性      | 描述                                         | 类型                                                  | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ----------------------------------------------------- | -------- | ---- |\n| type      | 节点类型，内置节点类型名称或自定义节点的名称 | [Type](/manual/element/node/base-node#type)           | `circle` |      |\n| style     | 节点样式，包括颜色、大小等                   | [Style](/manual/element/node/base-node#style)         | -        |      |\n| state     | 定义节点在不同状态下的样式                   | [State](/manual/element/node/base-node#state)         | -        |      |\n| palette   | 定义节点的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/node/base-node#palette)     | -        |      |\n| animation | 定义节点的动画效果                           | [Animation](/manual/element/node/base-node#animation) | -        |      |\n\n详见 [Node](/manual/element/node/base-node)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  node: {\n    type: 'circle', // 节点类型\n    style: {\n      fill: '#e6f7ff', // 填充色\n      stroke: '#91d5ff', // 边框色\n      lineWidth: 1, // 边框宽度\n      r: 20, // 半径\n      labelText: (d) => d.id, // 标签文本\n    },\n    // 节点状态样式\n    state: {\n      hover: {\n        lineWidth: 2,\n        stroke: '#69c0ff',\n      },\n      selected: {\n        fill: '#bae7ff',\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## edge\n\n> [EdgeOptions](#edgeoptions)\n\n边配置项\n\n#### EdgeOptions\n\n| 属性      | 描述                                   | 类型                                                  | 默认值 | 必选 |\n| --------- | -------------------------------------- | ----------------------------------------------------- | ------ | ---- |\n| type      | 边类型，内置边类型名称或自定义边的名称 | [Type](/manual/element/edge/base-edge#type)           | `line` |      |\n| style     | 边样式，包括颜色、大小等               | [Style](/manual/element/edge/base-edge#style)         | -      |      |\n| state     | 定义边在不同状态下的样式               | [State](/manual/element/edge/base-edge#state)         | -      |      |\n| palette   | 定义边的色板，用于根据不同数据映射颜色 | [Palette](/manual/element/edge/base-edge#palette)     | -      |      |\n| animation | 定义边的动画效果                       | [Animation](/manual/element/edge/base-edge#animation) | -      |      |\n\n详见 [Edge](/manual/element/edge/base-edge)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  edge: {\n    type: 'polyline', // 边类型\n    style: {\n      stroke: '#91d5ff', // 边的颜色\n      lineWidth: 2, // 边的宽度\n      endArrow: true, // 是否有箭头\n    },\n    // 边的状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 3,\n      },\n    },\n  },\n});\n```\n\n## combo\n\n> [ComboOptions](#combooptions)\n\n组合配置项\n\n| 属性      | 描述                                         | 类型                                                    | 默认值   | 必选 |\n| --------- | -------------------------------------------- | ------------------------------------------------------- | -------- | ---- |\n| type      | 组合类型，内置组合类型名称或自定义组合的名称 | [Type](/manual/element/combo/base-combo#type)           | `circle` |      |\n| style     | 组合样式，包括颜色、大小等                   | [Style](/manual/element/combo/base-combo#style)         | -        |      |\n| state     | 定义组合在不同状态下的样式                   | [State](/manual/element/combo/base-combo#state)         | -        |      |\n| palette   | 定义组合的色板，用于根据不同数据映射颜色     | [Palette](/manual/element/combo/base-combo#palette)     | -        |      |\n| animation | 定义组合的动画效果                           | [Animation](/manual/element/combo/base-combo#animation) | -        |      |\n\n详见 [Combo](/manual/element/combo/base-combo)\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  combo: {\n    type: 'circle', // 组合类型\n    style: {\n      fill: '#f0f0f0', // 背景色\n      stroke: '#d9d9d9', // 边框色\n      lineWidth: 1, // 边框宽度\n    },\n    // 组合状态样式\n    state: {\n      selected: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n    },\n  },\n});\n```\n\n## layout\n\n> _CustomLayoutOptions \\| CustomLayoutOptions[]_\n\n布局配置项，可以是对象（普通布局）或数组（流水线布局）。\n\n**示例**:\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force', // 力导向布局\n    preventOverlap: true, // 防止节点重叠\n    nodeStrength: -50, // 节点之间的斥力\n    edgeStrength: 0.5, // 边的弹性系数\n    iterations: 200, // 迭代次数\n    animation: true, // 启用布局动画\n  },\n});\n```\n\n## theme\n\n> _false \\| 'light' \\| 'dark' \\| string_\n\n设置图表的主题，可以是内置的 `'light'`、`'dark'` 主题，也可以是自定义主题的名称。设为 `false` 则不使用任何主题。\n\n## behaviors\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置图表的交互行为，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  behaviors: [\n    'drag-canvas', // 使用默认配置启用画布拖拽\n    'zoom-canvas', // 使用默认配置启用画布缩放\n    {\n      type: 'drag-element', // 自定义配置拖拽元素\n      key: 'drag-node-only',\n      enable: (event) => event.targetType === 'node', // 只允许拖拽节点\n    },\n    function () {\n      console.log(this); // 输出 graph 实例\n      return {\n        type: 'hover-activate',\n      };\n    },\n  ],\n});\n```\n\n- 查看 [交互总览](/manual/behavior/overview) 深入了解交互原理\n- 浏览 [内置交互](/manual/behavior/auto-adapt-label) 获取所有内置交互列表及其配置选项\n\n## plugins\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n设置图表的插件，可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  container: 'container',\n  plugins: [\n    'minimap', // 启用小地图，使用默认配置\n    {\n      type: 'grid', // 启用网格背景\n      key: 'grid-plugin',\n      line: {\n        stroke: '#d9d9d9',\n        lineWidth: 1,\n      },\n    },\n    {\n      type: 'toolbar', // 启用工具栏\n      key: 'graph-toolbar',\n      position: 'top-right', // 位置\n    },\n  ],\n});\n```\n\n- 查看 [插件总览](/manual/plugin/overview) 深入了解插件原理\n- 浏览 [内置插件](/manual/plugin/background) 获取所有内置插件列表及其配置项\n\n## transforms\n\n> _(string \\| [CustomExtensionOptions](#customextensionoptions) \\| ((this:Graph) =>CustomExtensionOptions))[]_\n\n配置数据处理，用于在渲染前对数据进行处理，不会影响原始数据。可以是字符串（使用默认配置）、对象（自定义配置）或函数（动态配置、函数内可访问图实例）。\n\n**示例：**\n\n```javascript\nconst graph = new Graph({\n  transforms: [\n    'process-parallel-edges', // 处理平行边，使用默认配置\n    {\n      type: 'map-node-size', // 根据节点数据映射节点大小\n      field: 'value', // 使用 value 字段的值\n      max: 50, // 最大半径\n      min: 20, // 最小半径\n    },\n  ],\n});\n```\n\n- 查看 [数据处理总览](/manual/transform/overview) 深入了解数据处理原理\n- 浏览 [内置数据处理](/manual/transform/map-node-size) 获取所有内置数据处理列表及其配置项\n\n#### CustomExtensionOptions\n\n```typescript\ninterface CustomExtensionOption extends Record<string, any> {\n  /** 拓展类型 */\n  type: string;\n  /** 拓展 key，即唯一标识 */\n  key?: string;\n}\n```\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/introduction.en.md) -->\n---\ntitle: Introduction\norder: 0\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 is a graph visualization engine. It provides capabilities for graph drawing, layout, analysis, interaction, animation, and other aspects of graph visualization. It aims to offer developers a set of tools that are easy to use, professionally reliable, and highly customizable for graph visualization development.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Rich Elements</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ elements to meet the needs of common scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Flexible Interactions</h4>\n\n<p style=\"text-align: center;\">Built-in 10+ interactions that can be freely combined according to different scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High-Performance Layout Algorithms</h4>\n\n<p style=\"text-align: center;\">High-performance layouts, built-in 10+ common graph layouts, with support for WebGPU and WASM computational acceleration.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Multicolor Themes for Various Scenarios</h4>\n\n<p style=\"text-align: center;\"><img height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D Scenes</h4>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><img width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">Supports 3D elements and layouts to create immersive graph visualization scenarios.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">High Customizability</h4>\n\n<p style=\"text-align: center;\">Elements, layouts, interactions, and plugins are all customizable, enabling every creative idea you have.</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">Start Your G6 Journey in Just 3 Minutes</h4>\n\n<p style=\"text-align: center;\">Click to enter 👉 <a href=\"/manual/getting-started/quick-start\">Quick Start</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n\n\n<!-- Skill/Rule: Manual Skill (packages/site/docs/manual/introduction.zh.md) -->\n---\ntitle: 简介\norder: 0\nsidebar: false\n---\n\n![](https://user-images.githubusercontent.com/6113694/45008751-ea465300-b036-11e8-8e2a-166cbb338ce2.png)\n\n[![Build Status](https://github.com/antvis/g6/workflows/build/badge.svg?branch=v5)](https://github.com/antvis//actions)\n[![Coverage Status](https://img.shields.io/coveralls/github/antvis/G6/v5.svg)](https://coveralls.io/github/antvis/G6?branch=v5)\n![typescript](https://img.shields.io/badge/language-typescript-red.svg)\n![MIT](https://img.shields.io/badge/license-MIT-000000.svg)\n[![npm package](https://img.shields.io/npm/v/@antv/g6.svg)](https://www.npmjs.com/package/@antv/g6)\n[![NPM downloads](http://img.shields.io/npm/dm/@antv/g6.svg)](https://npmjs.org/package/@antv/g6)\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/antvis/g6.svg)](http://isitmaintained.com/project/antvis/g6 'Percentage of issues still open')\n\n<h3 style=\"text-align: center;\">AntV G6</h3>\n\n<h3 style=\"text-align: center;\"><image width=\"500\" src=\"https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zTjwQaXokeQAAAAAAAAAAABkARQnAQ\" /></h3>\n\n<p style=\"text-align: center;\">G6 是一个图可视化引擎。它提供了图的绘制、布局、分析、交互、动画等图可视化能力。旨在为开发者提供一套简单易用、专业可靠、可高度定制的图可视化开发工具</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">丰富元素</h4>\n\n<p style=\"text-align: center;\">内置 10+ 元素，满足常规场景需求</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">灵活交互</h4>\n\n<p style=\"text-align: center;\">内置 10+ 交互，并可根据不同场景自由组合</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高性能布局算法</h4>\n\n<p style=\"text-align: center;\">高性能布局，内置 10+ 常用的图布局，支持 WebGPU、 WASM 计算加速</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">多色主题，适用多种场景</h4>\n\n<p style=\"text-align: center;\"><image height=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*QjJoSbD7GTwAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">3D 场景</h4>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*IUOnSbLisyoAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\"><image width=\"400\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*BK0OSYplirUAAAAAAAAAAAAADmJ7AQ/original\"></p>\n\n<p style=\"text-align: center;\">支持 3D 元素、布局，打造沉浸式的图可视化场景</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">高可定制性</h4>\n\n<p style=\"text-align: center;\">元素、布局、交互、插件统统可定制，实现你的每一个创意</p>\n\n<h4 style=\"text-align: center; color: #678ff3;\">仅需 3 分钟，开启 G6 之旅</h4>\n\n<p style=\"text-align: center;\">点击进入👉 <a href=\"/manual/getting-started/quick-start\">快速开始</a></p>\n\n<div>\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YXHtRZUKAZcAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VChnTLySxScAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tqlbS7ukmYUAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*I5uDQZWTzMsAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*hnLoRJR8EvMAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8LqvQJ09-EEAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*UgMZS6vrUlgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SDQKSb8gcxgAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZC1CT7q0fM4AAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YMxxTZwt54UAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h3eWT4loiTwAAAAAAAAAAAAADmJ7AQ/original\" />\n<image width=\"200\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*XTcoRKPMDloAAAAAAAAAAAAADmJ7AQ/original\" />\n</div>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/AntvDagreLayout.en.md) -->\n---\ntitle: AntvDagre Layout\norder: 2\n---\n\n## Overview\n\nAntvDagre builds upon the original [dagre](https://github.com/dagrejs/dagre/wiki) layout and adds more useful options, such as `nodeOrder`, `edgeLabelSpace`, and more. The `dagre` layout itself is a hierarchical layout suitable for directed acyclic graphs (DAGs), which can automatically handle node direction and spacing, and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## Options\n\n> For more native `dagre` options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout). Here, only some core and new options are listed.\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Diagram\" />\n\n| Property       | Description                                                                                                                                                                                        | Type                                                | Default | Required |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------- | -------- |\n| type           | Layout type                                                                                                                                                                                        | `antv-dagre`                                        | -       | ✓        |\n| rankdir        | Layout direction, options                                                                                                                                                                          | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`    |          |\n| align          | Node alignment, options                                                                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`    |          |\n| nodesep        | Node spacing (px). For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing.                                                                                             | number                                              | 50      |          |\n| nodesepFunc    | Callback for node spacing (px), allows different spacing for different nodes. For `TB` or `BT`, it's horizontal spacing; for `LR` or `RL`, it's vertical spacing. Takes precedence over `nodesep`. | (d?: Node) => number                                |         |          |\n| ranksep        | Rank spacing (px). For `TB` or `BT`, it's vertical spacing between adjacent ranks; for `LR` or `RL`, it's horizontal spacing.                                                                      | number                                              | 50      |          |\n| ranksepFunc    | Callback for rank spacing (px), allows different spacing for different ranks. For `TB` or `BT`, it's vertical spacing; for `LR` or `RL`, it's horizontal spacing. Takes precedence over `ranksep`. | (d?: Node) => number                                |         |          |\n| ranker         | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                                                                         | `network-simplex` \\| `tight-tree` \\| `longest-path` | -       |          |\n| nodeSize       | Specify node size for all nodes or each node, used for occupying space and spacing calculation                                                                                                     | Size \\| ((nodeData: Node) => Size)                  | -       |          |\n| controlPoints  | Whether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that consumes `style.controlPoints` as control points                 | boolean                                             | false   |          |\n| begin          | Top-left alignment position of the layout                                                                                                                                                          | [number, number] \\| [number, number, number]        | -       |          |\n| sortByCombo    | Whether to sort nodes in the same rank based on `parentId` in each node's data to avoid Combo overlap                                                                                              | boolean                                             | false   |          |\n| edgeLabelSpace | Whether to reserve space for edge labels                                                                                                                                                           | boolean                                             | true    |          |\n| nodeOrder      | Reference array for node order in the same rank, storing node ids                                                                                                                                  | string[]                                            | -       |          |\n| radial         | Whether to use radial layout based on `dagre`                                                                                                                                                      | boolean                                             | -       |          |\n| focusNode      | Focus node, only effective when `radial` is true                                                                                                                                                   | ID \\| Node \\| null                                  | -       |          |\n| preset         | Reference node positions for layout calculation, usually used to keep transitions smooth when switching data                                                                                       | NodeData[]                                          | -       |          |\n\n> Note: In G6, the control points computed by `antv-dagre` are written into `edge.style.controlPoints`.\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\nNode alignment: U = upper, D = down, L = left, R = right\n\n- `UL`: align to upper left\n- `UR`: align to upper right\n- `DL`: align to lower left\n- `DR`: align to lower right\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\nLayout direction. T = top, B = bottom, L = left, R = right\n\n- `TB`: top to bottom\n- `BT`: bottom to top\n- `LR`: left to right\n- `RL`: right to left\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\nLayout mode\n\n### ranksep\n\n> _number_ **Default:** 50\n\nRank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. `ranksepFunc` has higher priority.\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\nCallback for rank spacing (px)\n\nFor 'TB' or 'BT', it's vertical spacing; for 'LR' or 'RL', it's horizontal spacing. Takes precedence over nodesep if set.\n\n### nodesep\n\n> _number_ **Default:** 50\n\nNode spacing (px)\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. `nodesepFunc` has higher priority.\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\nCallback for node spacing (px), allows different spacing for different nodes\n\nFor 'TB' or 'BT', it's horizontal spacing; for 'LR' or 'RL', it's vertical spacing. Takes precedence over nodesep if set.\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\nTop-left alignment position of the layout\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\nWhether to keep edge control points. Only effective when using built-in polyline edges (`type: 'polyline-edge'`) or any edge that uses `style.controlPoints` as control points. Adds `style.controlPoints` to edge data.\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\nWhether to reserve space for edge labels\n\nThis affects whether a dummy node is added in the middle of the edge.\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\nFocus node, only effective when `radial` is true\n\n- ID: node id\n- Node: node instance\n- null: cancel focus\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\nReference array for node order in the same rank, stores node ids\n\nIf not specified, dagre's default order is used.\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\nSpecify node size for all or each node.\n\nUsed for collision detection to prevent node overlap\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\nReference node positions for layout calculation\n\nUsually for smooth transitions when switching data. In G6, if updating data, the existing layout result is used as input.\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout based on dagre\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\nWhether to sort nodes in the same rank by their parentId to prevent Combo overlap\n\nRecommended to enable when using Combo\n\n## Suitable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, node direction and spacing are automatically handled\n- **Dependency Graphs**: Display dependencies between packages or modules\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks\n\n## Related Documentation\n\n> The following documents can help you better understand the Dagre layout\n\n- [Graph Layout Algorithms: In-depth Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/AntvDagreLayout.zh.md) -->\n---\ntitle: AntV Dagre 布局 AntvDagre\norder: 2\n---\n\n## 概述\n\nAntvDagre 在原先[dagre](https://github.com/dagrejs/dagre/wiki)布局的基础上增加了更多有用的设置项，比如`nodeOrder`、`edgeLabelSpace`等等。 `dagre`布局本身一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'antv-dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n    controlPoints: false,\n  },\n});\n```\n\n## 配置项\n\n> 更多`dagre`原生配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)，这里仅列出部分核心配置和新增的配置\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性           | 描述                                                                                                                                               | 类型                                                | 默认值 | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------ | ---- |\n| type           | 布局类型                                                                                                                                           | `antv-dagre`                                        | -      | ✓    |\n| rankdir        | 布局方向，可选值                                                                                                                                   | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`   |      |\n| align          | 节点对齐方式，可选值                                                                                                                               | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`   |      |\n| nodesep        | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                                 | number                                              | 50     |      |\n| nodesepFunc    | 节点间距（px）的回调函数，优先级高于 `nodesep`                                                                                                     | (d?: Node) => number                                | -      |      |\n| ranksep        | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                               | number                                              | 50     |      |\n| ranksepFunc    | 层间距（px）的回调函数，优先级高于 `ranksep`                                                                                                       | (d?: Node) => number                                | -      |      |\n| ranker         | 为每个节点分配等级的算法，共支持三种算法：`longest-path`、`tight-tree`、`network-simplex`                                                          | `network-simplex` \\| `tight-tree` \\| `longest-path` | -      |      |\n| nodeSize       | 统一指定或为每个节点指定节点大小，用于占位与间距计算                                                                                               | Size \\| ((nodeData: Node) => Size)                  | -      |      |\n| controlPoints  | 是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'）时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效 | boolean                                             | false  |      |\n| begin          | 布局的左上角对齐位置                                                                                                                               | [number, number] \\| [number, number, number]        | -      |      |\n| sortByCombo    | 同一层节点是否根据每个节点数据中的 `parentId` 进行排序，以防止 Combo 重叠                                                                          | boolean                                             | false  |      |\n| edgeLabelSpace | 是否为边的 label 预留位置                                                                                                                          | boolean                                             | true   |      |\n| nodeOrder      | 同层节点顺序的参考数组，存放节点 id 值                                                                                                             | string[]                                            | -      |      |\n| radial         | 是否基于 `dagre` 进行辐射布局                                                                                                                      | boolean                                             | -      |      |\n| focusNode      | 关注的节点，仅在 `radial` 为 true 时生效                                                                                                           | ID \\| Node \\| null                                  | -      |      |\n| preset         | 布局计算时参考的节点位置，一般用于切换数据时保证重新布局的连续性                                                                                   | NodeData[]                                          | -      |      |\n\n> 补充：在 G6 中，`antv-dagre` 计算得到的控制点会被写入边的 `style.controlPoints`。\n\n### align\n\n> _DagreAlign_ **Default:** `UL`\n\n节点对齐方式 U：upper（上）；D：down（下）；L：left（左）；R：right（右）\n\n- `UL`:对齐到左上角\n- `UR`:对齐到右上角\n- `DL`:对齐到左下角\n- `DR`:对齐到右下角\n\n### rankdir\n\n> _DagreRankdir_ **Default:** `TB`\n\n布局的方向。T：top（上）；B：bottom（下）；L：left（左）；R：right（右）\n\n- `TB`:从上至下布局\n- `BT`:从下至上布局\n- `LR`:从左至右布局\n- `RL`:从右至左布局\n\n### ranker\n\n> _`network-simplex` \\| `tight-tree` \\| `longest-path`_\n\n布局的模式\n\n### ranksep\n\n> _number_ **Default:** 50\n\n层间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。ranksepFunc 拥有更高的优先级\n\n### ranksepFunc\n\n> _(d?: Node) => number_\n\n层间距（px）的回调函数\n\n在 rankdir 为 'TB' 或 'BT' 时是竖直方向相邻层间距；在 rankdir 为 'LR' 或 'RL' 时代表水平方向相邻层间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### nodesep\n\n> _number_ **Default:** 50\n\n节点间距（px）\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。nodesepFunc 拥有更高的优先级\n\n### nodesepFunc\n\n> _(d?: Node) => number_\n\n节点间距（px）的回调函数，通过该参数可以对不同节点设置不同的节点间距\n\n在 rankdir 为 'TB' 或 'BT' 时是节点的水平间距；在 rankdir 为 'LR' 或 'RL' 时代表节点的竖直方向间距。优先级高于 nodesep，即若设置了 nodesepFunc，则 nodesep 不生效\n\n### begin\n\n> _[number, number] \\| [number, number, number]_ **Default:** undefined\n\n布局的左上角对齐位置\n\n### controlPoints\n\n> _boolean_ **Default:** false\n\n是否保留边的控制点，仅在边配置中使用了内置折线（type: 'polyline-edge'） 时，或任何将自定义消费了 `style.controlPoints` 字段作为控制点位置的边时生效。本质上就是给边数据增加了 `style.controlPoints`\n\n### edgeLabelSpace\n\n> _boolean_ **Default:** true\n\n是否为边的label留位置\n\n这会影响是否在边中间添加dummy node\n\n### focusNode\n\n> _ID \\| Node \\| null_\n\n关注的节点，注意，仅在`radial` 为 true 时生效\n\n- ID: 节点 id\n- Node: 节点实例\n- null: 取消关注\n\n### nodeOrder\n\n> _string[]_ **Default:** undefined\n\n同层节点顺序的参考数组，存放节点 id 值\n\n若未指定，则将按照 dagre 本身机制排列同层节点顺序\n\n### nodeSize\n\n> _Size \\| ((nodeData: Node) => Size)_ **Default:** undefined\n\n统一指定或为每个节点指定节点大小。\n\n用于防止节点重叠时的碰撞检测\n\n### preset\n\n> _OutNode[]_ **Default:** undefined\n\n布局计算时参考的节点位置\n\n一般用于切换数据时保证重新布局的连续性。在 G6 中，若是更新数据，则将自动使用已存在的布局结果数据作为输入\n\n### radial\n\n> _boolean_\n\n是否基于 dagre 进行辐射布局\n\n### sortByCombo\n\n> _boolean_ **Default:** false\n\n同一层节点是否根据每个节点数据中的 parentId 进行排序，以防止 Combo 重叠\n\n建议在有 Combo 的情况下配置\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解 Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/BaseLayout.en.md) -->\n---\ntitle: Common Layout Configuration Options\norder: 1\n---\n\nThis article introduces the common attribute configurations for built-in layouts.\n\n## General Configuration\n\n| Property               | Description                                                                             | Type                                                  | Default    | Required |\n| ---------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------- | -------- |\n| type                   | Layout type, name of built-in or custom layout                                          | [Type](#Type)                                         | -          | ✓        |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in the layout (takes effect when preLayout is true) | boolean                                               | false      |          |\n| nodeFilter             | Nodes participating in the layout                                                       | (node: NodeData) => boolean                           | () => true |          |\n| comboFilter            | Combos participating in the layout                                                      | (combo: ComboData) => boolean                         | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements                           | boolean                                               | false      |          |\n| enableWorker           | Whether to run the layout in a WebWorker                                                | boolean                                               | -          |          |\n| iterations             | Number of iterations for iterative layout                                               | number                                                | -          |          |\n| animation              | Whether to enable layout animation                                                      | boolean                                               | false      |          |\n| width                  | Width of the layout area, defaults to the current container width                       | number                                                | -          |          |\n| height                 | Height of the layout area, defaults to the current container height                     | number                                                | -          |          |\n| center                 | Layout center point                                                                     | [number, number] \\| [number, number, number]          | -          |          |\n| node                   | Node field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |          |\n| edge                   | Edge field mapping, used to map business fields to layout fields                        | (datum) => ({ id?, source?, target? })                | -          |          |\n\nAdditional notes:\n\n- `width` / `height` / `center` are common layout fields uniformly supported by `@antvis/layout`.\n- `node` / `edge` are used to adapt non-standard business fields such as custom `id` / `source` / `target`.\n- `iterations` is the step count used by the G6 runtime to drive iterative layouts, and is not the same as some layouts' internal algorithm parameters.\n\n### Type\n\nSpecifies the layout type, either the name of a built-in layout type or a custom layout.\n\n```js {4}\nconst graph = new Graph({\n  // Other configurations...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\nOptional values include:\n\n- `antv-dagre`: [Custom layout based on dagre](/en/manual/layout/antv-dagre-layout)\n- `circular`: [Circular layout](/en/manual/layout/circular-layout)\n- `combo-combined`: [Layout suitable for combinations](/en/manual/layout/combo-combined-layout)\n- `concentric`: [Concentric layout](/en/manual/layout/concentric-layout)\n- `d3-force`: [Force-directed layout based on D3](/en/manual/layout/d3-force-layout)\n- `d3-force-3d`: [3D Force-directed layout](/en/manual/layout/d3-force3-d-layout)\n- `dagre`: [Dagre layout](/en/manual/layout/dagre-layout)\n- `fishbone`: [Fishbone layout](/en/manual/layout/fishbone)\n- `force`: [Force-directed layout](/en/manual/layout/force-layout)\n- `force-atlas2`: [ForceAtlas2 layout](/en/manual/layout/force-atlas2-layout)\n- `fruchterman`: [Fruchterman layout](/en/manual/layout/fruchterman-layout)\n- `grid`: [Grid layout](/en/manual/layout/grid-layout)\n- `mds`: [MDS layout for high-dimensional data](/en/manual/layout/mds-layout)\n- `radial`: [Radial layout](/en/manual/layout/radial-layout)\n- `random`: [Random layout](/en/manual/layout/random-layout)\n- `snake`: [Snake layout](/en/manual/layout/snake)\n- `compact-box`: [Compact box tree layout](/en/manual/layout/compact-box-layout)\n- `dendrogram`: [Dendrogram layout](/en/manual/layout/dendrogram-layout)\n- `mindmap`: [Mindmap layout](/en/manual/layout/mindmap-layout)\n- `indented`: [Indented tree layout](/en/manual/layout/indented-layout)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/BaseLayout.zh.md) -->\n---\ntitle: 布局通用配置项\norder: 1\n---\n\n本文介绍内置布局通用属性配置。\n\n## 通用配置\n\n| 属性                   | 描述                                                  | 类型                                                  | 默认值     | 必选 |\n| ---------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ---------- | ---- |\n| type                   | 布局类型，内置布局或自定义布局的名称                  | [Type](#Type)                                         | -          | ✓    |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（当 preLayout 为 true 时生效） | boolean                                               | false      |      |\n| nodeFilter             | 参与该布局的节点                                      | (node: NodeData) => boolean                           | () => true |      |\n| comboFilter            | 参与该布局的combo元素                                 | (combo: ComboData) => boolean                         | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                    | boolean                                               | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                           | boolean                                               | -          |      |\n| iterations             | 迭代布局的迭代次数                                    | number                                                | -          |      |\n| animation              | 是否启用布局动画                                      | boolean                                               | false      |      |\n| width                  | 布局区域宽度，默认使用当前容器宽度                    | number                                                | -          |      |\n| height                 | 布局区域高度，默认使用当前容器高度                    | number                                                | -          |      |\n| center                 | 布局中心点                                            | [number, number] \\| [number, number, number]          | -          |      |\n| node                   | 节点字段映射，用于把业务字段映射为布局字段            | (datum) => ({ id?, x?, y?, z?, parentId?, isCombo? }) | -          |      |\n| edge                   | 边字段映射，用于把业务字段映射为布局字段              | (datum) => ({ id?, source?, target? })                | -          |      |\n\n补充说明：\n\n- `width` / `height` / `center` 是 `@antvis/layout` 统一支持的通用布局字段。\n- `node` / `edge` 用于适配非标准 `id/source/target` 业务数据。\n- `iterations` 是 G6 运行时用于驱动迭代布局的步数，不等同于某些布局内部自己的算法参数。\n\n### Type\n\n指定布局类型，内置布局类型名称或自定义布局的名称。\n\n```js {4}\nconst graph = new Graph({\n  // 其他配置...\n  layout: {\n    type: 'antv-dagre',\n  },\n});\n```\n\n可选值有：\n\n- `antv-dagre`：[基于 dagre 定制的布局](/manual/layout/antv-dagre-layout)\n- `circular`：[环形布局](/manual/layout/circular-layout)\n- `combo-combined`：[适用于存在组合的布局](/manual/layout/combo-combined-layout)\n- `concentric`：[同心圆布局](/manual/layout/concentric-layout)\n- `d3-force`[基于 D3 的力导向布局](/manual/layout/d3-force-layout)\n- `d3-force-3d`：[3D力导向布局](/manual/layout/d3-force3-d-layout)\n- `dagre`：[dagre 布局](/manual/layout/dagre-layout)\n- `fishbone`：[鱼骨布局](/manual/layout/fishbone)\n- `force`：[力导向布局](/manual/layout/force-layout)\n- `force-atlas2`：[ForceAtlas2 布局](/manual/layout/force-atlas2-layout)\n- `fruchterman`：[Fruchterman 布局](/manual/layout/fruchterman-layout)\n- `grid`：[网格布局](/manual/layout/grid-layout)\n- `mds`：[高维数据降维算法布局](/manual/layout/mds-layout)\n- `radial`：[径向布局](/manual/layout/radial-layout)\n- `random`：[随机布局](/manual/layout/random-layout)\n- `snake`：[蛇形布局](/manual/layout/snake)\n- `compact-box`：[紧凑树布局](/manual/layout/compact-box-layout)\n- `dendrogram`：[树状布局](/manual/layout/dendrogram-layout)\n- `mindmap`：[思维导图布局](/manual/layout/mindmap-layout)\n- `indented`：[缩进树布局](/manual/layout/indented-layout)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/CircularLayout.en.md) -->\n---\ntitle: Circular Layout\norder: 3\n---\n\n## Overview\n\nCircular layout arranges nodes evenly or at intervals on a circle, and also supports spiral layouts by configuring different startRadius and endRadius. See more circular layout [examples](en/examples#layout-circular) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n**Circular layout**:\n\n- Suitable for networks with equal relationships and no hierarchical structure\n\n**Spiral layout**:\n\n- Suitable for implicit hierarchies or time series graphs (such as organizational charts, propagation networks)\n\n## Basic Usage\n\nOther settings use the default configuration (layout width and height default to the entire canvas container)\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## Options\n\n| Property    | Description                                                                                                       | Type                                          | Default                                   | Required |\n| ----------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------- | -------- |\n| type        | Layout type                                                                                                       | circular                                      | -                                         | ✓        |\n| angleRatio  | How many 2\\*PI between the first and last node                                                                    | number                                        | 1                                         |          |\n| center      | Center of the layout                                                                                              | [number, number]\\|[number, number, number]    | [`layout width` / 2, `layout height` / 2] |          |\n| clockwise   | Whether to arrange clockwise                                                                                      | boolean                                       | true                                      |          |\n| divisions   | Number of segments on the ring (segments will be evenly distributed, effective when endRadius - startRadius != 0) | number                                        | 1                                         |          |\n| nodeSize    | Node size (diameter), used for collision detection                                                                | Size \\| ((nodeData: Node) => Size)            | 10                                        |          |\n| nodeSpacing | Minimum spacing between rings, used to adjust radius                                                              | number \\| ((nodeData: Node) => number)        | 10                                        |          |\n| ordering    | Node ordering on the ring, [see details](#ordering)                                                               | `topology` \\| `topology-directed` \\| `degree` | -                                         |          |\n| radius      | Circle radius, if set, spiral layout configs `startRadius` and `endRadius` are ignored, [see details](#radius)    | number                                        | -                                         |          |\n| startAngle  | Start angle of the layout                                                                                         | number                                        | 0                                         |          |\n| endAngle    | End angle of the layout                                                                                           | number                                        | 2 \\* Math.PI                              |          |\n| startRadius | Start radius for spiral layout, [usage](#spiral-layout)                                                           | number                                        | -                                         |          |\n| endRadius   | End radius for spiral layout                                                                                      | number                                        | -                                         |          |\n| width       | Layout width                                                                                                      | number                                        | canvas width                              |          |\n| height      | Layout height                                                                                                     | number                                        | canvas height                             |          |\n\n### ordering\n\nNode ordering on the ring\n\n- `topology`: topological order\n- `topology-directed`: topological order (directed graph)\n- `degree`: order by degree\n\nIf not set (`null`), the order in the array is used directly\n\n### radius\n\nIf radius, startRadius, and endRadius are not set, the default is `Math.min(layout width, layout height) / 2`, i.e., fills the entire layout area\n\n## Code Examples\n\n### Basic Circular Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### Spiral Layout\n\n```javascript\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/CircularLayout.zh.md) -->\n---\ntitle: 环形布局 Circular\norder: 3\n---\n\n## 概述\n\n环形布局是一种把节点均匀或者按间隔放置在圆上的布局，也支持通过配置 startRadius 和 endRadius 为不一样的值实现螺旋状布局。参考更多环形布局[样例](/examples#layout-circular)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n**环形布局**:\n\n- 适用于平等关系网络、无层级结构的图\n\n**螺旋状布局**:\n\n- 适用于隐式层级或时间序列图（如组织架构、传播网络）\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n## 配置项\n\n| 属性        | 描述                                                                                | 类型                                          | 默认值                           | 必选 |\n| ----------- | ----------------------------------------------------------------------------------- | --------------------------------------------- | -------------------------------- | ---- |\n| type        | 布局类型                                                                            | circular                                      | -                                | ✓    |\n| angleRatio  | 从第一个节点到最后节点之间相隔多少个 2\\*PI                                          | number                                        | 1                                |      |\n| center      | 布局的中心                                                                          | [number, number]\\|[number, number, number]    | [`布局宽度` / 2, `布局高度` / 2] |      |\n| clockwise   | 是否顺时针排列                                                                      | boolean                                       | true                             |      |\n| divisions   | 节点在环上的分段数（几个段将均匀分布，在 endRadius - startRadius != 0 时生效）      | number                                        | 1                                |      |\n| nodeSize    | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                      | Size \\| ((nodeData: Node) => Size)            | 10                               |      |\n| nodeSpacing | 环与环之间最小间距，用于调整半径                                                    | number \\| ((nodeData: Node) => number)        | 10                               |      |\n| ordering    | 节点在环上排序的依据，[说明](#ordering)                                             | `topology` \\| `topology-directed` \\| `degree` | -                                |      |\n| radius      | 圆的半径，设置了则螺旋状布局的配置`startRadius`、`endRadius`不生效，[说明](#radius) | number                                        | -                                |      |\n| startAngle  | 布局的开始角度                                                                      | number                                        | 0                                |      |\n| endAngle    | 布局的结束角度                                                                      | number                                        | 2 \\* Math.PI                     |      |\n| startRadius | 螺旋状布局的开始半径，[用法](#螺旋状布局)                                           | number                                        | -                                |      |\n| endRadius   | 螺旋状布局的结束半径                                                                | number                                        | -                                |      |\n| width       | 布局的宽度                                                                          | number                                        | 画布宽度                         |      |\n| height      | 布局的高度                                                                          | number                                        | 画布高度                         |      |\n\n### ordering\n\n节点在环上排序的依据\n\n- `topology`: 按照拓扑排序\n- `topology-directed`: 按照拓扑排序（有向图）\n- `degree`: 按照度数大小排序\n\n不配置（`null`）则直接使用数组中的顺序\n\n### radius\n\n如果radius、startRadius、endRadius都没配置，则默认为最终计算出来的`Math.min(布局宽度, 布局高度) / 2`，即布满整个布局区域\n\n## 代码示例\n\n### 基础环形布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n### 螺旋状布局\n\n```javascript\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'circular',\n    startRadius: 10,\n    endRadius: 300,\n  },\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'center',\n      data,\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelFill: '#fff',\n          labelPlacement: 'center',\n        },\n      },\n      layout: {\n        type: 'circular',\n        startRadius: 10,\n        endRadius: 300,\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ComboCombinedLayout.en.md) -->\n---\ntitle: ComboCombined Layout\norder: 4\n---\n\n## Overview\n\nComboCombined composite layout is suitable for graph data with composite group structures. It supports flexible configuration of the layout for elements inside combos as well as the layout between the outermost combos and nodes. By default, the internal elements use the Concentric layout, and the outer layout uses the gForce force-directed layout, balancing layout effect and overall stability. See more ComboCombined layout [examples](/en/examples#layout-combo-layout) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts).\n\n## Usage Scenarios\n\n- User profile analysis: Analyze user behavior and product relationships, use user interest circles as combos, display specific products and behavior tags as internal nodes, and help operators identify user consumption paths.\n- Supply chain management graph: Divide suppliers, manufacturers, warehouses, and distributors into combos by role or region, display resources, personnel, or equipment as internal nodes, and clearly show the internal structure of each link in the supply chain.\n\n## Options\n\n| Property     | Description                                                                                                                                        | Type                                                                                       | Default      | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------ | -------- |\n| type         | Layout type                                                                                                                                        | `combo-combined`                                                                           | -            | ✓        |\n| center       | Layout center                                                                                                                                      | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | Graph center |          |\n| layout       | Layout configuration. Can be fixed, or returned dynamically based on `comboId`                                                                     | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -            |          |\n| nodeSize     | Node size (diameter), used for collision detection                                                                                                 | `number` \\| `number[]` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number     | -            |          |\n| nodeSpacing  | Spacing between nodes                                                                                                                              | `number` \\| (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number                   | -            |          |\n| comboSpacing | Spacing between combos                                                                                                                             | `number` \\| (d?: unknown) => number                                                        | -            |          |\n| comboPadding | Padding value inside the combo, used only for force calculation, not for rendering. It is recommended to set the same value as the visual padding. | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -            |          |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\nIn `5.1`, it is recommended to use a single `layout` field to choose layouts for different levels, instead of configuring `innerLayout` and `outerLayout` separately.\n\n**Example**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ComboCombinedLayout.zh.md) -->\n---\ntitle: 复合布局 ComboCombined\norder: 4\n---\n\n## 概述\n\nComboCombined 复合布局适用于复合分组结构的图数据展示场景，支持灵活配置 Combo 内部元素的布局以及最外层 Combo 和节点之间的布局。 默认情况内部元素采用 Concentric 同心圆布局，外部布局采用 gForce 力导向布局，兼顾布局效果与整体稳定性。参考更多 ComboCombined 复合布局[样例](/examples#layout-combo-layout)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/combo-combined.ts)\n\n## 使用场景\n\n- 用户画像分析: 分析用户行为与商品关系，将用户兴趣圈层作为 Combo，内部节点展示具体商品和行为标签，帮助运营人员识别用户消费路径。\n- 供应链管理图：供应商、制造商、仓储、分销商按角色或区域划分 Combo，内部节点展示资源、人员或设备，清晰展示供应链各环节内部结构。\n\n## 配置项\n\n| 属性         | 描述                                                                                                | 类型                                                                                       | 默认值 | 必选 |\n| ------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------ | ---- |\n| type         | 布局类型                                                                                            | `combo-combined`                                                                           | -      | ✓    |\n| center       | 布局中心                                                                                            | [`PointTuple`](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L829) | 图中心 |      |\n| layout       | 布局配置。可固定指定，也可根据 `comboId` 动态返回                                                   | `string` \\| `object` \\| `(comboId?: string) => string \\| object`                           | -      |      |\n| nodeSize     | 节点大小（直径）。用于碰撞检测                                                                      | `number` \\| `number[]` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number        | -      |      |\n| nodeSpacing  | 节点间距                                                                                            | `number` \\| (d?: [NodeData](/manual/data#节点数据nodedata)) => number                      | -      |      |\n| comboSpacing | Combo 之间的间距                                                                                    | `number` \\| (d?: unknown) => number                                                        | -      |      |\n| comboPadding | Combo 内部的 padding 值，不用于渲染，仅用于计算力。推荐设置为与视图上 Combo 内部 padding 值相同的值 | `((d?: unknown) => number)` \\| `number` \\| `number[]` \\| `undefined`                       | -      |      |\n\n### layout\n\n> _`string | object | (comboId?: string) => string | object`_\n\n5.1 中推荐使用单个 `layout` 字段为不同层级选择布局，而不是分别配置 `innerLayout` 和 `outerLayout`。\n\n**示例**:\n\n```ts\nnew Graph({\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) => (comboId ? { type: 'grid' } : { type: 'force' }),\n  },\n});\n```\n\n## 示例代码\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/combo.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      layout: {\n        type: 'combo-combined',\n        comboPadding: 2,\n      },\n      node: {\n        style: {\n          size: 20,\n          labelText: (d) => d.id,\n        },\n        palette: {\n          type: 'group',\n          field: (d) => d.combo,\n        },\n      },\n      edge: {\n        style: (model) => {\n          const { size, color } = model.data;\n          return {\n            stroke: color || '#99ADD1',\n            lineWidth: size || 1,\n          };\n        },\n      },\n      behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n      autoFit: 'view',\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/CompactBoxLayout.en.md) -->\n---\ntitle: CompactBox Layout\norder: 5\n---\n\n## Overview\n\nThe CompactBox layout is suitable for visualizing structured tree data. It is evolved from the classic [Reingold–Tilford tidy layout algorithm](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf), and considers the bounding box of each tree node during layout, effectively maintaining the compactness and hierarchical clarity of the tree structure. See more CompactBox layout [examples](/en/examples#layout-compact-box) and [source code](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox Tidy Tree Layout Example'/>\n\n## Usage Scenarios\n\n- Decision trees: The compact tree layout can visually and intuitively display each decision path.\n- Knowledge graphs: Show hierarchical relationships and connections between concepts. The compact layout can present complex knowledge networks in limited space.\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## Options\n\n| Property  | Description                                                                                                   | Type                                                         | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------- | -------- |\n| type      | Layout type                                                                                                   | `compact-box`                                                | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                       | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                   | `LR`    |          |\n| getSide   | Set whether the node is on the left or right of the root. Only works for `H` direction. [See below](#getside) | (d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string |         |          |\n| getId     | Callback for node id                                                                                          | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => string |         |          |\n| getWidth  | Callback for node width                                                                                       | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHeight | Callback for node height                                                                                      | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getHGap   | Callback for horizontal gap                                                                                   | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| getVGap   | Callback for vertical gap                                                                                     | (d?: [NodeData](/en/manual/data#节点数据nodedata)) => number |         |          |\n| radial    | Whether to enable radial layout, [see below](#radial)                                                         | boolean                                                      | false   |          |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\nTree layout direction\n\n- `TB`: Root at the top, layout downwards\n- `BT`: Root at the bottom, layout upwards\n- `LR`: Root at the left, layout to the right\n- `RL`: Root at the right, layout to the left\n- `H`: Root in the middle, horizontal symmetric layout. You can use `getSide` to specify the left/right logic for each node\n- `V`: Root in the middle, vertical symmetric layout\n\n### getSide\n\n> _(d: { data?: [NodeData](/en/manual/data#节点数据nodedata) }) => string_\n\nSet whether the node is on the left or right of the root. Only works for `H` direction. If not set, the algorithm will automatically assign left/right. See [getSide auto logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n({ data }) => {\n  // data is a node\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => string_\n\nCallback for node id\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node width\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for node height\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for horizontal gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/en/manual/data#节点数据nodedata)) => number_\n\nCallback for vertical gap\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\nWhether to use radial layout. If `radial` is `true`, it is recommended to set `direction` to `'LR'` or `'RL'`.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/CompactBoxLayout.zh.md) -->\n---\ntitle: 紧凑树布局 CompactBox\norder: 5\n---\n\n## 概述\n\n紧凑树布局适用于结构化树形数据的展示，基于经典的 [Reingold–Tilford tidy 布局算法](http://emr.cs.iit.edu/~reingold/tidier-drawings.pdf) 演进而来，通过布局时综合考虑每个树节点的包围盒，有效保持树结构的紧凑性与层次清晰。参考更多 CompactBox 布局[样例](/examples#layout-compact-box)和[源码](https://github.com/antvis/hierarchy/blob/master/src/compact-box.js)\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' width=650 alt='CompactBox 紧凑树布局示例'/>\n\n## 使用场景\n\n- 决策树: 通过紧凑树布局可简单直观的图形化展示每个决策路径\n- 知识图谱: 展示概念之间的层级关系和连接，紧凑布局可以在有限空间内呈现复杂的知识网络\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'compact-box',\n    direction: 'LR',\n    getHeight: () => 16,\n    getWidth: () => 16,\n    getVGap: () => 16,\n    getHGap: () => 40,\n  },\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                                                                                    | 类型                                                      | 默认值 | 必选 |\n| --------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                                | `compact-box`                                             | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                          | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V`                | `LR`   |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在 `H` 布局方向上生效 | (d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string |        |      |\n| getId     | 节点 id 的回调函数                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => string |        |      |\n| getWidth  | 计算每个节点的宽度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHeight | 计算每个节点的高度                                                                                      | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getHGap   | 计算每个节点的水平间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| getVGap   | 计算每个节点的垂直间隙                                                                                  | (d?: [NodeData](/manual/data#节点数据nodedata)) => number |        |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)                                                                     | boolean                                                   | false  |      |\n\n### direction\n\n> `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` **Default:** `LR`\n\n树布局方向\n\n- `TB`：根节点在上，往下布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*KrAqTrFbNjMAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `BT`：根节点在下，往上布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vNmOTJ4q0uwAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n- `LR`：根节点在左，往右布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ffD6S74MXw4AAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `RL`：根节点在右，往左布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*vTg2SJbtj_sAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `H`：根节点在中间，水平对称布局。可传入 `getSide` 方法指定每个节点的左右分布逻辑\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0GsIQISvieYAAAAAAAAAAABkARQnAQ' width=150 alt='水平布局'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n  <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=150 alt='垂直布局'/>\n\n### getSide\n\n> _(d: { data?: [NodeData](/manual/data#节点数据nodedata) }) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在 `direction` 为 `H` 时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考 [getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n({ data }) => {\n  // data 是一个节点\n  if (data.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### getId\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => string_\n\n节点 id 的回调函数\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  return d.id + '_node';\n};\n```\n\n### getWidth\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: [NodeData](/manual/data#节点数据nodedata)) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### radial\n\n> _boolean_\n\n是否按照辐射状布局。若 `radial` 为 `true`，建议 `direction` 设置为 `'LR'` 或 `'RL'`\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*E0c8TIYRPYoAAAAAAAAAAABkARQnAQ' width=200 alt='img'/>\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\n/**\n * If the node is a leaf node\n * @param {*} d - node data\n * @returns {boolean} - whether the node is a leaf node\n */\nfunction isLeafNode(d) {\n  return !d.children || d.children.length === 0;\n}\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data: treeToGraphData(data),\n      behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand'],\n      node: {\n        style: {\n          labelText: (d) => d.id,\n          labelPlacement: (d) => (isLeafNode(d) ? 'right' : 'left'),\n          labelBackground: true,\n          ports: [{ placement: 'right' }, { placement: 'left' }],\n        },\n        animation: {\n          enter: false,\n        },\n      },\n      edge: {\n        type: 'cubic-horizontal',\n        animation: {\n          enter: false,\n        },\n      },\n      layout: {\n        type: 'compact-box',\n        direction: 'LR',\n        getHeight: function getHeight() {\n          return 32;\n        },\n        getWidth: function getWidth() {\n          return 32;\n        },\n        getVGap: function getVGap() {\n          return 10;\n        },\n        getHGap: function getHGap() {\n          return 100;\n        },\n      },\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ConcentricLayout.en.md) -->\n---\ntitle: Concentric Layout\norder: 6\n---\n\n## Overview\n\nThe concentric layout arranges nodes in layers according to a certain sorting rule, with each layer of nodes placed around a common center. See more concentric layout [examples](/en/examples#layout-concentric) or [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts).\n\n## Usage Scenarios\n\n- Layered data visualization, such as permission structures, organizational charts, etc., with the center as the top-level role and outer rings as lower-level nodes.\n- Visualization of ranking analysis results, with high-importance nodes in the center and low-importance nodes on the periphery, quickly expressing the relative influence of nodes in the graph.\n\n## Options\n\n| Property       | Description                                                                                                                                                                 | Type                                               | Default                                                   | Required |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------- | -------- | --------- | --- |\n| type           | Layout type                                                                                                                                                                 | `concentric`                                       | -                                                         | ✓        |\n| center         | Center position of the circular layout, defaults to the center of the container                                                                                             | [number, number] \\| [number, number, number]       | -                                                         |          |\n| clockwise      | Whether to arrange nodes clockwise                                                                                                                                          | boolean                                            | false                                                     |          |\n| equidistant    | Whether the distance between rings is equal                                                                                                                                 | boolean                                            | false                                                     |          |\n| width          | Layout width, defaults to container width                                                                                                                                   | number                                             | -                                                         |          |\n| height         | Layout height, defaults to container height                                                                                                                                 | number                                             | -                                                         |          |\n| sortBy         | The property to sort by (node attribute name). The higher the value, the closer to the center. If set to 'degree', nodes with higher degree are placed closer to the center | string                                             | `degree`                                                  |          |\n| maxLevelDiff   | Maximum attribute difference in the same layer. If undefined, set to maxValue / 4, where maxValue is the maximum value of the sorting property                              | number                                             | undefined                                                 |          |\n| nodeSize       | Node size (diameter), used for collision detection                                                                                                                          | number \\| number[] \\| ((nodeData: Node) => number) | 30                                                        |          |\n| nodeSpacing    | Minimum spacing between rings, used to adjust the radius                                                                                                                    | number \\| number[] \\| ((node?: Node) => number)    | 10                                                        |          |\n| preventOverlap | Whether to prevent overlap. Must be used with nodeSize or data.size. Only works if node size is set in data or in this layout config.                                       | boolean                                            | false                                                     |          |\n| startAngle     | The angle (in radians) to start laying out nodes                                                                                                                            | number                                             | 3 / 2 \\* Math.PI                                          |          |\n| sweep          | The angle difference between the first and last node in the same layer. If undefined, it is set to `2 _ Math.PI _ (1 - 1 /                                                  | level.nodes                                        | )`, where `level.nodes` is the set of nodes in that layer | number   | undefined |     |\n\n## Example Code\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: 'Center', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ConcentricLayout.zh.md) -->\n---\ntitle: 同心圆布局 Concentric\norder: 6\n---\n\n## 概述\n\n同心圆布局是一种将节点根据某种排序规则分层，并以圆心为中心、沿圆周排列每层节点的布局方式。参考更多同心圆布局[样例](/examples#layout-concentric)或[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/circular.ts)。\n\n## 使用场景\n\n- 分层数据可视化，如权限控制结构、组织架构图等，中心是顶级角色，外圈为下级节点。\n- 排序分析结果可视化，高重要度放中心，低重要度放外围，快速表达图中节点的相对影响力。\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                        | 类型                                               | 默认值           | 必选 |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------- | ---- |\n| type           | 布局类型                                                                                                                                                                                                    | `concentric`                                       | -                | ✓    |\n| center         | 圆形布局的中心位置，默认为当前容器的中心位置                                                                                                                                                                | [number, number] \\| [number, number, number]       | -                |      |\n| clockwise      | 是否按照顺时针排列                                                                                                                                                                                          | boolean                                            | false            |\n| equidistant    | 环与环之间的距离是否相等                                                                                                                                                                                    | boolean                                            | false            |      |\n| width          | 布局的宽度，默认使用容器宽度                                                                                                                                                                                | number                                             | -                |      |\n| height         | 布局的高度，默认使用容器高度                                                                                                                                                                                | number                                             | -                |      |\n| sortBy         | 指定排序的依据（节点属性名）<br>数值越高则该节点被放置得越中心。若为 degree，则会计算节点的度数，度数越高，节点将被放置得越中心                                                                             | string                                             | `degree`         |      |\n| maxLevelDiff   | 同一层节点的最大属性差值<br>若为 undefined，则将会被设置为 maxValue / 4 ，其中 maxValue 为最大的排序依据的属性值。例如，若 sortBy 为 'degree'，则 maxValue 为所有节点中度数最大的节点的度数                 | number                                             | undefined        |      |\n| nodeSize       | 节点大小（直径）。用于防止节点重叠时的碰撞检测                                                                                                                                                              | number \\| number[] \\| ((nodeData: Node) => number) | 30               |      |\n| nodeSpacing    | 环与环之间最小间距，用于调整半径                                                                                                                                                                            | number \\| number[] \\| ((node?: Node) => number)    | 10               |      |\n| preventOverlap | 是否防止重叠<br>必须配合 nodeSize 属性或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测                        | boolean                                            | false            |      |\n| startAngle     | 开始布局节点的弧度                                                                                                                                                                                          | number                                             | 3 / 2 \\* Math.PI |      |\n| sweep          | 同一层中第一个节点与最后一个节点之间的弧度差<br>若为 undefined ，则将会被设置为 2 \\* Math.PI \\* (1 - 1 / \\|level.nodes\\|) ，其中 level.nodes 为该算法计算出的每一层的节点，\\|level.nodes\\| 代表该层节点数量 | number                                             | undefined        |      |\n\n## 代码示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'center', data: { label: '中心', level: 0 } },\n\n      { id: 'level1-0', data: { label: 'L1-0', level: 1 } },\n      { id: 'level1-1', data: { label: 'L1-1', level: 1 } },\n      { id: 'level1-2', data: { label: 'L1-2', level: 1 } },\n      { id: 'level1-3', data: { label: 'L1-3', level: 1 } },\n      { id: 'level1-4', data: { label: 'L1-4', level: 1 } },\n      { id: 'level1-5', data: { label: 'L1-5', level: 1 } },\n\n      { id: 'level2-0', data: { label: 'L2-0', level: 2 } },\n      { id: 'level2-1', data: { label: 'L2-1', level: 2 } },\n      { id: 'level2-2', data: { label: 'L2-2', level: 2 } },\n      { id: 'level2-3', data: { label: 'L2-3', level: 2 } },\n      { id: 'level2-4', data: { label: 'L2-4', level: 2 } },\n      { id: 'level2-5', data: { label: 'L2-5', level: 2 } },\n      { id: 'level2-6', data: { label: 'L2-6', level: 2 } },\n      { id: 'level2-7', data: { label: 'L2-7', level: 2 } },\n      { id: 'level2-8', data: { label: 'L2-8', level: 2 } },\n      { id: 'level2-9', data: { label: 'L2-9', level: 2 } },\n      { id: 'level2-10', data: { label: 'L2-10', level: 2 } },\n      { id: 'level2-11', data: { label: 'L2-11', level: 2 } },\n    ],\n    edges: [\n      { id: 'e-center-level1-0', source: 'center', target: 'level1-0' },\n      { id: 'e-center-level1-1', source: 'center', target: 'level1-1' },\n      { id: 'e-center-level1-2', source: 'center', target: 'level1-2' },\n      { id: 'e-center-level1-3', source: 'center', target: 'level1-3' },\n      { id: 'e-center-level1-4', source: 'center', target: 'level1-4' },\n      { id: 'e-center-level1-5', source: 'center', target: 'level1-5' },\n\n      { id: 'e-level1-0-level2-0', source: 'level1-0', target: 'level2-0' },\n      { id: 'e-level1-0-level2-1', source: 'level1-0', target: 'level2-1' },\n      { id: 'e-level1-1-level2-2', source: 'level1-1', target: 'level2-2' },\n      { id: 'e-level1-1-level2-3', source: 'level1-1', target: 'level2-3' },\n      { id: 'e-level1-2-level2-4', source: 'level1-2', target: 'level2-4' },\n      { id: 'e-level1-2-level2-5', source: 'level1-2', target: 'level2-5' },\n      { id: 'e-level1-3-level2-6', source: 'level1-3', target: 'level2-6' },\n      { id: 'e-level1-3-level2-7', source: 'level1-3', target: 'level2-7' },\n      { id: 'e-level1-4-level2-8', source: 'level1-4', target: 'level2-8' },\n      { id: 'e-level1-4-level2-9', source: 'level1-4', target: 'level2-9' },\n      { id: 'e-level1-5-level2-10', source: 'level1-5', target: 'level2-10' },\n      { id: 'e-level1-5-level2-11', source: 'level1-5', target: 'level2-11' },\n    ],\n  },\n  layout: {\n    type: 'concentric',\n    nodeSize: 32,\n    sortBy: 'degree',\n    preventOverlap: true,\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  animation: false,\n});\n\ngraph.render();\n```\n\n</details>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/custom-layout.en.md) -->\n---\ntitle: Custom Layout\norder: 22\n---\n\n## Overview\n\nIn G6, layouts are divided into two types: 'iterative layout' and 'non-iterative layout'. An iterative layout refers to a layout algorithm that iterates multiple times until convergence, while a non-iterative layout refers to a layout algorithm that executes only once.\n\n## Implement Layout\n\n### Non-Iterative Layout\n\nImplementing a non-iterative layout is relatively straightforward; you only need to implement the `execute` method in `BaseLayout`. Below is a simple implementation of a custom layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\nIn the code above, we implemented a simple layout algorithm that arranges nodes along a diagonal line starting from the top-left corner.\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=info}\n\nThe `execute` method returns a GraphData object, which only needs to contain the basic information of the elements (such as id, source, target) and the properties added by the layout (such as x, y, control points of edges, etc.), and does not need to contain other unnecessary information.\nIf you only need to layout the nodes, you can return only the node information and do not need to return the edge information.\n:::\n\n### Iterative Layout\n\nThe implementation of an iterative layout also requires inheriting from `BaseLayout`, but in addition to `execute`, you also need to implement the `tick` and `stop` methods. The `tick` method is used to iterate the layout to a specified number of rounds, and the `stop` method is used to stop the layout iteration.\n\nIn addition, in iterative layouts, you need to call `options.onTick` each time the layout iterates to trigger the graph update.\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\nBelow is a simple implementation of an iterative layout:\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\nIn this example, we have implemented a simple iterative layout algorithm that toggles the x-coordinate of the nodes between 50 and 150 every 200 milliseconds and arranges them in order along the y-axis according to the sequence of the nodes.\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## Register Layout\n\nYou can register through the `register` method provided by G6. For more details, please refer to [Register Layout](/en/manual/core-concept/layout#register-layout)\n\n## Configure Layout\n\nThe type and parameters of the layout can be configured in `options.layout`. For more details, please refer to [Configure Layout](/en/manual/core-concept/layout#configure-layout)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/custom-layout.zh.md) -->\n---\ntitle: 自定义布局\norder: 22\n---\n\n## 概述\n\nG6 中布局分为`迭代布局`和`非迭代布局`两种，迭代布局是指布局算法会迭代多次直到收敛，非迭代布局是指布局算法只执行一次。\n\n## 实现布局\n\n### 非迭代布局\n\n实现一个非迭代布局相对简单，只需要实现 `BaseLayout` 中的 `execute` 方法即可，下面是一个简单的自定义布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData } from '@antv/g6';\n\nclass DiagonalLayout extends BaseLayout {\n  id = 'diagonal-layout';\n\n  async execute(data: GraphData): Promise<GraphData> {\n    const { nodes = [] } = data;\n    return {\n      nodes: nodes.map((node, index) => ({\n        id: node.id,\n        style: {\n          x: 50 * index + 25,\n          y: 50 * index + 25,\n        },\n      })),\n    };\n  }\n}\n```\n\n在上面的代码中，我们实现了一个简单的布局算法，将节点从左上角沿对角线排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/non-iterative-layout.md\"></embed>\n\n:::info{title=提示}\n`execute` 方法返回的是一个 GraphData 对象，里面仅需要包含元素的基本信息（如 id、source、target）以及布局新增的属性（如 x、y、边的控制点等），不需要包含其他无用的信息。\n如果仅需要对节点进行布局，可以只返回节点信息，不需要返回边的信息。\n:::\n\n### 迭代布局\n\n迭代布局的实现同样需要继承 `BaseLayout`，但是除 `execute` 外还需要实现 `tick` 和 `stop` 方法，`tick` 方法用于将布局迭代到指定轮次，`stop` 方法用于停止布局迭代。\n\n此外，迭代布局中需要在每次迭代调用 `options.onTick` 以触发图的更新。\n\n```typescript\ntype onTick = (data: GraphData) => void;\n```\n\n下面是一个简单的迭代布局实现：\n\n```typescript\nimport { BaseLayout } from '@antv/g6';\nimport type { GraphData, BaseLayoutOptions } from '@antv/g6';\n\ninterface TickTockLayoutOptions extends BaseLayoutOptions {\n  onTick: (data: GraphData) => void;\n}\n\nclass TickTockLayout extends BaseLayout<TickTockLayoutOptions> {\n  public id = 'custom-layout';\n\n  private tickCount = 0;\n\n  private data?: GraphData;\n\n  private timer?: number;\n\n  private resolve?: () => void;\n\n  private promise?: Promise<void>;\n\n  async execute(data: GraphData, options: TickTockLayoutOptions): Promise<GraphData> {\n    const { onTick } = { ...this.options, ...options };\n\n    this.tickCount = 0;\n    this.data = data;\n\n    this.promise = new Promise((resolve) => {\n      this.resolve = resolve;\n    });\n\n    this.timer = window.setInterval(() => {\n      onTick(this.simulateTick());\n      if (this.tickCount === 10) this.stop();\n    }, 200);\n\n    await this.promise;\n\n    return this.simulateTick();\n  }\n\n  simulateTick = () => {\n    const x = this.tickCount++ % 2 === 0 ? 50 : 150;\n\n    return {\n      nodes: (this?.data?.nodes || []).map((node, index) => ({\n        id: node.id,\n        style: { x, y: (index + 1) * 30 },\n      })),\n    };\n  };\n\n  tick = () => {\n    return this.simulateTick();\n  };\n\n  stop = () => {\n    clearInterval(this.timer);\n    this.resolve?.();\n  };\n}\n```\n\n在这个例子中，我们实现了一个简单的迭代布局算法，每 200ms 将节点的 x 坐标在 50 和 150 之间切换，并按照节点顺序在 y 方向上排列。\n\n<embed src=\"@/common/manual/custom-extension/layout/iterative-layout.md\"></embed>\n\n## 注册布局\n\n通过 G6 提供的 register 方法注册即可，详见[注册布局](/manual/layout/overview#注册布局)\n\n## 配置布局\n\n可在 `options.layout` 中配置布局的类型和参数，详见[配置布局](/manual/layout/overview#配置布局)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/D3Force3DLayout.en.md) -->\n---\ntitle: 3D Force-Directed Layout\norder: 7\n---\n\n## Overview\n\nThe D3Force3D layout is a 3D extension based on [d3-force](https://d3js.org/d3-force), which simulates physical forces in three-dimensional space to achieve automatic layout. Compared to 2D layouts, it adds force effects in the Z-axis direction, allowing richer data relationships to be displayed in 3D space.\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D Force-Directed Layout Illustration\" />\n\n## Core Concepts\n\n### Force System\n\nD3Force3D extends the traditional 2D force-directed layout with the following forces:\n\n- **3D Centering Force**: Pulls nodes toward the center point in 3D space\n- **3D Collision Force**: Prevents node overlap in 3D space\n- **3D Radial Force**: Attracts nodes to a sphere in 3D space\n- **3D Axis Forces**: Applies forces along the X, Y, and Z axes\n\n### Iteration System\n\nThe layout is computed through iterations, mainly involving the following parameters:\n\n- **alpha**: The current energy value of the iteration, controlling node movement speed\n- **alphaDecay**: The decay rate of the energy value\n- **alphaMin**: The minimum energy value; iteration stops below this value\n- **velocityDecay**: The velocity decay factor\n\n## Options\n\n| Property        | Description                                                      | Type                                                                       | Default       | Required |\n| --------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------- | -------- |\n| type            | Layout type                                                      | string                                                                     | `d3-force-3d` | ✓        |\n| nodeSize        | Node size (diameter), used for collision detection               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -             |          |\n| iterations      | Number of force iterations; higher means more precise but slower | number                                                                     | -             |          |\n| numDimensions   | Number of dimensions (2 or 3)                                    | number                                                                     | 3             |          |\n| forceSimulation | Custom force simulation method                                   | Simulation<NodeDatum, EdgeDatum>                                           | -             |          |\n| onTick          | Callback for each iteration                                      | (data: LayoutMapping) => void                                              | -             |          |\n| randomSource    | Random number generator                                          | () => number                                                               | -             |          |\n\n### Iteration Control\n\n| Property      | Description                   | Type   | Default | Required |\n| ------------- | ----------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold | number | 1       |          |\n| alphaDecay    | Convergence decay rate (0-1)  | number | 0.028   |          |\n| alphaMin      | Stop iteration threshold      | number | 0.001   |          |\n| alphaTarget   | Target convergence threshold  | number | 0       |          |\n| velocityDecay | Velocity decay factor         | number | 0.4     |          |\n\n### Force Model Options\n\n#### Centering Force (center)\n\n| Property        | Description         | Type   | Default | Required |\n| --------------- | ------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate | number | 0       |          |\n| center.y        | Center y coordinate | number | 0       |          |\n| center.z        | Center z coordinate | number | 0       |          |\n| center.strength | Force strength      | number | 1       |          |\n\n#### Collision Force (collide)\n\n| Property           | Description          | Type                                                                       | Default | Required |\n| ------------------ | -------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| collide.radius     | Collision radius     | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10      |          |\n| collide.strength   | Force strength       | number                                                                     | 1       |          |\n| collide.iterations | Collision iterations | number                                                                     | 1       |          |\n\n#### Link Force (link)\n\n| Property        | Description           | Type                                                                       | Default | Required |\n| --------------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| link.id         | Edge id generator     | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |          |\n| link.distance   | Ideal edge length     | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |          |\n| link.strength   | Force strength        | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |          |\n| link.iterations | Link force iterations | number                                                                     | 1       |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                  | Type                                                                       | Default  | Required |\n| -------------------- | ---------------------------- | -------------------------------------------------------------------------- | -------- | -------- |\n| manyBody.strength    | Force strength               | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy          | number                                                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum interaction distance | number                                                                     | 1        |          |\n| manyBody.distanceMax | Maximum interaction distance | number                                                                     | Infinity |          |\n\n#### Radial Force (radial)\n\n| Property        | Description     | Type                                                                       | Default | Required |\n| --------------- | --------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| radial.strength | Force strength  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1     |          |\n| radial.radius   | Target radius   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100     |          |\n| radial.x        | Sphere center x | number                                                                     | 0       |          |\n| radial.y        | Sphere center y | number                                                                     | 0       |          |\n| radial.z        | Sphere center z | number                                                                     | 0       |          |\n\n#### Axis Forces (x, y, z)\n\nEach axis can be configured separately:\n\n| Property   | Description           | Type                                                                       | Default | Required |\n| ---------- | --------------------- | -------------------------------------------------------------------------- | ------- | -------- |\n| x.strength | X-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| x.x        | Target x coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.strength | Y-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| y.y        | Target y coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.strength | Z-axis force strength | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n| z.z        | Target z coordinate   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -       |          |\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/D3Force3DLayout.zh.md) -->\n---\ntitle: 3D D3力导向布局 D3Force3D\norder: 7\n---\n\n## 概述\n\nD3Force3D 布局是基于 [d3-force](https://d3js.org/d3-force) 的三维扩展版本，通过在三维空间中模拟物理力的作用来实现自动布局。相比二维布局，它增加了 Z 轴方向的力作用，能够在三维空间中展现更丰富的数据关系。\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original\" alt=\"3D 力导向布局示意图\" />\n\n## 核心概念\n\n### 力系统\n\nD3Force3D 在传统二维力导向布局的基础上，扩展了以下力的作用：\n\n- **三维中心力**：将节点拉向三维空间的中心点\n- **三维碰撞力**：在三维空间中防止节点重叠\n- **三维径向力**：将节点吸引到三维空间中的球面上\n- **三维坐标力**：分别在 X、Y、Z 三个方向上施加作用力\n\n### 迭代系统\n\n布局计算通过迭代来实现，主要涉及以下参数：\n\n- **alpha**：当前迭代的活力值，控制节点移动速度\n- **alphaDecay**：活力值的衰减率\n- **alphaMin**：最小活力值，低于此值停止迭代\n- **velocityDecay**：速度衰减因子\n\n## 配置项\n\n| 属性            | 描述                                         | 类型                                                                       | 默认值        | 必选 |\n| --------------- | -------------------------------------------- | -------------------------------------------------------------------------- | ------------- | ---- |\n| type            | 布局类型                                     | string                                                                     | `d3-force-3d` | ✓    |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠   | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10            |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大 | number                                                                     | -             |      |\n| numDimensions   | 维度数量，固定为 3                           | number                                                                     | 3             |      |\n| forceSimulation | 自定义力模拟方法                             | Simulation<NodeDatum, EdgeDatum>                                           | -             |      |\n| onTick          | 每次迭代的回调函数                           | (data: LayoutMapping) => void                                              | -             |      |\n| randomSource    | 随机数生成函数                               | () => number                                                               | -             |      |\n\n### 迭代控制\n\n| 属性          | 描述                  | 类型   | 默认值 | 必选 |\n| ------------- | --------------------- | ------ | ------ | ---- |\n| alpha         | 当前迭代收敛阈值      | number | 1      |      |\n| alphaDecay    | 收敛阈值衰减率（0-1） | number | 0.028  |      |\n| alphaMin      | 停止迭代的阈值        | number | 0.001  |      |\n| alphaTarget   | 目标收敛阈值          | number | 0      |      |\n| velocityDecay | 速度衰减因子          | number | 0.4    |      |\n\n### 力模型配置\n\n#### 中心力（center）\n\n| 属性            | 描述          | 类型   | 默认值 | 必选 |\n| --------------- | ------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标 | number | 0      |      |\n| center.y        | 中心点 y 坐标 | number | 0      |      |\n| center.z        | 中心点 z 坐标 | number | 0      |      |\n| center.strength | 力的强度      | number | 1      |      |\n\n#### 碰撞力（collide）\n\n| 属性               | 描述               | 类型                                                                       | 默认值 | 必选 |\n| ------------------ | ------------------ | -------------------------------------------------------------------------- | ------ | ---- |\n| collide.radius     | 碰撞半径           | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 10     |      |\n| collide.strength   | 力的强度           | number                                                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数 | number                                                                     | 1      |      |\n\n#### 链接力（link）\n\n| 属性            | 描述             | 类型                                                                       | 默认值  | 必选 |\n| --------------- | ---------------- | -------------------------------------------------------------------------- | ------- | ---- |\n| link.id         | 边的 id 生成函数 | (edge: EdgeDatum, index: number, edges: EdgeDatum[]) => string             | edge.id |      |\n| link.distance   | 理想边长         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 30      |      |\n| link.strength   | 力的强度         | number \\| ((edge: EdgeDatum, index: number, edges: EdgeDatum[]) => number) | 1       |      |\n| link.iterations | 链接力的迭代次数 | number                                                                     | 1       |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                      | 类型                                                                       | 默认值   | 必选 |\n| -------------------- | ------------------------- | -------------------------------------------------------------------------- | -------- | ---- |\n| manyBody.strength    | 力的强度                  | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数 | number                                                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离              | number                                                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离              | number                                                                     | Infinity |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述        | 类型                                                                       | 默认值 | 必选 |\n| --------------- | ----------- | -------------------------------------------------------------------------- | ------ | ---- |\n| radial.strength | 力的强度    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 0.1    |      |\n| radial.radius   | 目标半径    | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | 100    |      |\n| radial.x        | 球心 x 坐标 | number                                                                     | 0      |      |\n| radial.y        | 球心 y 坐标 | number                                                                     | 0      |      |\n| radial.z        | 球心 z 坐标 | number                                                                     | 0      |      |\n\n#### 坐标力（x、y、z）\n\n每个方向的力可以单独配置：\n\n| 属性       | 描述             | 类型                                                                       | 默认值 | 必选 |\n| ---------- | ---------------- | -------------------------------------------------------------------------- | ------ | ---- |\n| x.strength | X 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| x.x        | 目标 x 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.strength | Y 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| y.y        | 目标 y 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.strength | Z 轴方向的力强度 | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n| z.z        | 目标 z 坐标      | number \\| ((node: NodeDatum, index: number, nodes: NodeDatum[]) => number) | -      |      |\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/D3ForceLayout.en.md) -->\n---\ntitle: D3 Force-Directed Layout\norder: 8\n---\n\n## Overview\n\nThe D3Force layout is a force-directed layout based on [d3-force](https://d3js.org/d3-force). It simulates physical forces (such as attraction, repulsion, collision, etc.) to make the graph reach a stable state with minimal energy.\n\nThe main features of this layout are:\n\n1. **Automatic arrangement**: No need to manually set node positions, the system will automatically find suitable positions\n2. **Real-time adjustment**: When you drag a node, other nodes will adjust their positions in real time\n3. **Flexible configuration**:\n   - You can adjust the attraction and repulsion between nodes\n   - You can set the ideal length of edges\n   - You can fix the positions of important nodes\n4. **Animation effect**: Nodes move with smooth animation, making changes more natural\n\n<img alt=\"D3Force layout diagram\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Core Concepts\n\n### Force System\n\nThe D3Force layout simulates five different forces to achieve automatic layout. Imagine a physical world where these forces act simultaneously and eventually reach equilibrium:\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> Note: The arrows of different colors in the diagram represent different types of forces. In the actual layout, these forces are invisible and also affected by other forces.\n\n- **Link Force**: Imagine nodes connected by rubber bands, which pull connected nodes to a suitable distance. The tightness of the rubber band is the force strength, and the ideal length is the distance we set.\n- **Many-Body Force**: Similar to magnets, it allows all nodes to attract or repel each other. When the force strength is negative, nodes repel each other (like like poles of magnets); when positive, they attract (like opposite poles). This force determines the density of the graph.\n- **Center Force**: Like all nodes are tied to the center of the canvas by an invisible string. This force prevents nodes from drifting too far and keeps the graph centered.\n- **Collision Force**: Treats nodes as solid balls. When nodes get too close, they automatically bounce apart. This force mainly prevents node overlap and improves readability.\n- **Radial Force**: Imagine an invisible ring that attracts nodes to the ring. By setting the radius and force strength, nodes can form a beautiful circular layout.\n\n### Iteration System\n\nLayout calculation is an iterative process with two key concepts:\n\n#### Alpha Value (Energy)\n\nLike the \"energy\" of the layout, it determines how vigorously nodes move:\n\n- **Initial state**: Alpha = 1, nodes move vigorously\n- **During calculation**: Alpha gradually decreases, node movement slows\n- **End state**: When Alpha < alphaMin, nodes stop moving\n\n#### Iterations\n\nControls the number of times forces are applied in each calculation:\n\n- **Effect**: The larger the value, the more precise the layout, but the slower the computation\n- **Adjustment**:\n  - Simple graphs: use the default value\n  - Complex graphs: increase the number of iterations as needed\n  - Real-time interaction: use fewer iterations\n\n> Tip: Iterations and alpha value work together. Increasing iterations makes each step more precise, while alpha controls the overall progress.\n\n## Options\n\n| Property        | Description                                        | Type                                       | Default    | Required |\n| --------------- | -------------------------------------------------- | ------------------------------------------ | ---------- | -------- |\n| type            | Layout type                                        | string                                     | 'd3-force' | ✓        |\n| centerX         | Layout center x coordinate                         | number                                     | width / 2  |          |\n| centerY         | Layout center y coordinate                         | number                                     | height / 2 |          |\n| centerStrength  | Center force strength                              | number                                     | -          |          |\n| nodeSize        | Node size (diameter), for collision detection      | number \\| ((node, index, nodes) => number) | 10         |          |\n| nodeSpacing     | Extra spacing between nodes                        | number \\| ((node, index, nodes) => number) | 0          |          |\n| iterations      | Number of force iterations, higher is more precise | number                                     | -          |          |\n| onTick          | Callback for each iteration, for real-time results | (data: LayoutMapping) => void              | -          |          |\n| forceSimulation | Custom force simulation, defaults to d3.js method  | Simulation<NodeDatum, EdgeDatum>           | -          |          |\n| randomSource    | Function to generate random numbers                | () => number                               | -          |          |\n\n### Iteration Control\n\n| Property      | Description                                          | Type   | Default | Required |\n| ------------- | ---------------------------------------------------- | ------ | ------- | -------- |\n| alpha         | Current convergence threshold, controls activity     | number | 1       |          |\n| alphaMin      | Minimum threshold to stop, when alpha < this, stop   | number | 0.001   |          |\n| alphaDecay    | Decay rate of alpha, [0, 1], 0.028 ≈ 300 iterations  | number | 0.028   |          |\n| alphaTarget   | Target alpha, system tries to converge to this value | number | 0       |          |\n| velocityDecay | Velocity decay factor, higher means slower movement  | number | 0.4     |          |\n\n### Force Model Options\n\n#### Link Force (link)\n\n| Property        | Description                                  | Type                                       | Default     | Required |\n| --------------- | -------------------------------------------- | ------------------------------------------ | ----------- | -------- |\n| link.id         | Function to generate edge id                 | (edge, index, edges) => string             | (e) => e.id |          |\n| link.distance   | Ideal edge length                            | number \\| ((edge, index, edges) => number) | 30          |          |\n| link.strength   | Force strength, higher means closer to ideal | number \\| ((edge, index, edges) => number) | 1           |          |\n| link.iterations | Number of link force iterations              | number                                     | 1           |          |\n\n#### Many-Body Force (manyBody)\n\n| Property             | Description                                                     | Type                                       | Default  | Required |\n| -------------------- | --------------------------------------------------------------- | ------------------------------------------ | -------- | -------- |\n| manyBody.strength    | Force strength, negative for repulsion, positive for attraction | number \\| ((node, index, nodes) => number) | -30      |          |\n| manyBody.theta       | Barnes-Hut accuracy, smaller is more accurate                   | number                                     | 0.9      |          |\n| manyBody.distanceMin | Minimum distance, prevents excessive force                      | number                                     | 1        |          |\n| manyBody.distanceMax | Maximum distance, beyond which no force is applied              | number                                     | Infinity |          |\n\n#### Center Force (center)\n\n| Property        | Description                                   | Type   | Default | Required |\n| --------------- | --------------------------------------------- | ------ | ------- | -------- |\n| center.x        | Center x coordinate                           | number | -       |          |\n| center.y        | Center y coordinate                           | number | -       |          |\n| center.strength | Force strength, higher means closer to center | number | -       |          |\n\n> Note: In `5.1`, `centerX` / `centerY` are the recommended shortcut fields. If you configure the `center` force directly, it follows the native `d3-force` style.\n\n#### Collision Force (collide)\n\n| Property           | Description                                     | Type                                       | Default | Required |\n| ------------------ | ----------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| collide.radius     | Collision radius, nodes repel if closer         | number \\| ((node, index, nodes) => number) | 10      |          |\n| collide.strength   | Force strength, higher means stronger repulsion | number                                     | 1       |          |\n| collide.iterations | Number of collision iterations                  | number                                     | 1       |          |\n\n#### Radial Force (radial)\n\n| Property        | Description                                   | Type                                       | Default | Required |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ------- | -------- |\n| radial.strength | Force strength, higher means closer to radius | number \\| ((node, index, nodes) => number) | 0.1     |          |\n| radial.radius   | Target radius, nodes are attracted to circle  | number \\| ((node, index, nodes) => number) | 100     |          |\n| radial.x        | Center x coordinate                           | number                                     | 0       |          |\n| radial.y        | Center y coordinate                           | number                                     | 0       |          |\n\n#### X Axis Force (x)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| x.strength | Force strength in x direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| x.x        | Target x coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n#### Y Axis Force (y)\n\n| Property   | Description                               | Type                                       | Default | Required |\n| ---------- | ----------------------------------------- | ------------------------------------------ | ------- | -------- |\n| y.strength | Force strength in y direction             | number \\| ((node, index, nodes) => number) | -       |          |\n| y.y        | Target y coordinate, nodes attracted here | number \\| ((node, index, nodes) => number) | -       |          |\n\n## Code Examples\n\n### Prevent Node Overlap\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\nSee [Example - Prevent Node Overlap in Force-Directed Layout](/en/examples/layout/force-directed/#prevent-overlap)\n\n### Team Clustering Layout\n\nThis example shows how to use force-directed layout for team clustering, where nodes of different teams automatically cluster together.\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // Team A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // Team B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // Team C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // Team A internal connections\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // Team B internal connections\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // Team C internal connections\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // Few connections between teams\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// Create mock data with nodes from different teams\nconst data = {\n  nodes: [\n    // Team A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // Team B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // Team C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // Team A internal connections\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // Team B internal connections\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // Team C internal connections\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // Few connections between teams\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // Different colors for different teams\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // Configure link force - nodes within the same team are closer\n    link: {\n      distance: (d) => {\n        // Shorter distance within the same team\n        if (d.source.team === d.target.team) return 50;\n        // Longer distance between teams\n        return 200;\n      },\n      strength: (d) => {\n        // Stronger connection within the same team\n        if (d.source.team === d.target.team) return 0.7;\n        // Weaker connection between teams\n        return 0.1;\n      },\n    },\n    // Configure many-body force - control repulsion between nodes\n    manyBody: {\n      strength: (d) => {\n        // Team leader nodes (ending with 1) have stronger repulsion\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // Configure collision force - prevent node overlap\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // Configure center force - keep the graph centered\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\nMain configuration notes:\n\n- `link.distance`: Shorter within teams, longer between teams\n- `link.strength`: Stronger within teams, weaker between teams\n- `manyBody.strength`: Controls repulsion between nodes\n- `collide`: Prevents node overlap\n- `center`: Keeps the layout centered\n\nSee also [Customize parameters for different nodes](/en/examples/layout/force-directed/#functional-params).\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/D3ForceLayout.zh.md) -->\n---\ntitle: D3力导向布局 D3Force\norder: 8\n---\n\n## 概述\n\nD3Force 布局是基于 [d3-force](https://d3js.org/d3-force) 实现的力导向布局。它通过模拟物理力的作用（如引力、斥力、碰撞等），使图布局达到一个能量最小的稳定状态。\n\n这种布局的主要特点是：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的理想长度\n   - 可以固定某些重要节点的位置\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img alt=\"D3Force 布局示意图\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 核心概念\n\n### 力系统 Force System\n\nD3Force 布局通过模拟五种不同的力来实现自动布局。想象一个物理世界，这些力同时作用，最终达到平衡：\n\n<img width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*p5L2S6gtZ2AAAAAAAAAAAAAAemJ7AQ/original\" alt=\"force\" />\n\n> 注：图中不同颜色的箭头代表不同类型的力，实际布局中这些力是无形的，同时也会受其他力影响。\n\n- **链接力**（Link Force）：想象节点之间连着橡皮筋，可以把相连的节点拉到合适的距离。橡皮筋的松紧度就是力的强度（strength），理想长度就是我们设置的距离（distance）。\n- **多体力**（Many-Body Force）：类似磁铁的效果，可以让所有节点互相吸引或排斥。力的强度为负值时节点会互相排斥（像相同磁极），为正值时会互相吸引（像相反磁极）。这个力决定了图的疏密程度。\n- **中心力**（Center Force）：就像所有节点都被一根看不见的绳子拴在画布中心。这个力可以防止节点飘得太远，让整个图保持在画布的中心位置。\n- **碰撞力**（Collision Force）：让节点变成有实体大小的小球，当节点太近时会自动弹开。这个力主要用来防止节点重叠，提高图的可读性。\n- **径向力**（Radial Force）：想象有一个看不见的圆环，这个力会把节点吸引到圆环上。通过设置圆的半径和力的强度，可以让节点形成漂亮的环形布局。\n\n### 迭代系统（Iteration System）\n\n布局计算是一个反复调整的过程，包含两个关键概念：\n\n#### Alpha 值（活力值）\n\n就像布局的\"能量\"，决定节点移动的剧烈程度：\n\n- **初始状态**：Alpha = 1，节点移动剧烈\n- **计算过程**：Alpha 值逐渐降低，节点移动变缓\n- **结束状态**：当 Alpha < alphaMin 时，节点停止移动\n\n#### 迭代次数（Iterations）\n\n控制每次计算时力的作用次数：\n\n- **作用**：值越大，布局越精确，但计算越慢\n- **调节**：\n  - 简单图：使用默认值即可\n  - 复杂图：可以适当增加迭代次数\n  - 实时交互：建议使用较小的迭代次数\n\n> 提示：迭代次数（iterations）和活力值（alpha）是相互配合的。增加迭代次数可以让每一步计算更精确，而活力值则控制整体计算的进度。\n\n## 配置项\n\n| 属性            | 描述                                          | 类型                                       | 默认值     | 必选 |\n| --------------- | --------------------------------------------- | ------------------------------------------ | ---------- | ---- |\n| type            | 布局类型                                      | string                                     | 'd3-force' | ✓    |\n| centerX         | 布局中心点 x 坐标                             | number                                     | width / 2  |      |\n| centerY         | 布局中心点 y 坐标                             | number                                     | height / 2 |      |\n| centerStrength  | 中心力强度                                    | number                                     | -          |      |\n| nodeSize        | 节点大小（直径），用于碰撞检测防止节点重叠    | number \\| ((node, index, nodes) => number) | 10         |      |\n| nodeSpacing     | 节点间额外间距                                | number \\| ((node, index, nodes) => number) | 0          |      |\n| iterations      | 力的迭代次数，值越大布局越精确但性能消耗越大  | number                                     | -          |      |\n| onTick          | 每次迭代的回调函数，用于实时获取布局结果      | (data: LayoutMapping) => void              | -          |      |\n| forceSimulation | 自定义力模拟方法，若不指定则使用 d3.js 的方法 | Simulation<NodeDatum, EdgeDatum>           | -          |      |\n| randomSource    | 用于生成随机数的函数                          | () => number                               | -          |      |\n\n### 迭代控制\n\n| 属性          | 描述                                                   | 类型   | 默认值 | 必选 |\n| ------------- | ------------------------------------------------------ | ------ | ------ | ---- |\n| alpha         | 当前迭代的收敛阈值，控制布局的活跃程度                 | number | 1      |      |\n| alphaMin      | 停止迭代的最小阈值，当 alpha 小于该值时停止迭代        | number | 0.001  |      |\n| alphaDecay    | 收敛阈值的衰减率，范围 [0, 1]，0.028 对应约 300 次迭代 | number | 0.028  |      |\n| alphaTarget   | 目标收敛阈值，系统会尝试将 alpha 收敛到该值            | number | 0      |      |\n| velocityDecay | 速度衰减因子，值越大节点运动越缓慢                     | number | 0.4    |      |\n\n### 力模型配置\n\n#### 链接力（link）\n\n| 属性            | 描述                               | 类型                                       | 默认值      | 必选 |\n| --------------- | ---------------------------------- | ------------------------------------------ | ----------- | ---- |\n| link.id         | 边的 id 生成函数                   | (edge, index, edges) => string             | (e) => e.id |      |\n| link.distance   | 理想边长，边会趋向于该长度         | number \\| ((edge, index, edges) => number) | 30          |      |\n| link.strength   | 力的强度，值越大边长越接近理想边长 | number \\| ((edge, index, edges) => number) | 1           |      |\n| link.iterations | 链接力的迭代次数                   | number                                     | 1           |      |\n\n#### 多体力（manyBody）\n\n| 属性                 | 描述                                                  | 类型                                       | 默认值   | 必选 |\n| -------------------- | ----------------------------------------------------- | ------------------------------------------ | -------- | ---- |\n| manyBody.strength    | 力的强度，负值为斥力，正值为引力                      | number \\| ((node, index, nodes) => number) | -30      |      |\n| manyBody.theta       | Barnes-Hut 算法的精度参数，值越小越精确但性能消耗越大 | number                                     | 0.9      |      |\n| manyBody.distanceMin | 最小作用距离，防止力过大                              | number                                     | 1        |      |\n| manyBody.distanceMax | 最大作用距离，超过该距离的节点不产生力                | number                                     | Infinity |      |\n\n#### 中心力（center）\n\n| 属性            | 描述                               | 类型   | 默认值 | 必选 |\n| --------------- | ---------------------------------- | ------ | ------ | ---- |\n| center.x        | 中心点 x 坐标                      | number | -      |      |\n| center.y        | 中心点 y 坐标                      | number | -      |      |\n| center.strength | 力的强度，值越大节点越趋向于中心点 | number | -      |      |\n\n> 补充：5.1 中推荐优先使用 `centerX` / `centerY` 作为快捷配置；如果直接配置 `center` force，则按 d3-force 原生写法生效。\n\n#### 碰撞力（collide）\n\n| 属性               | 描述                                   | 类型                                       | 默认值 | 必选 |\n| ------------------ | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| collide.radius     | 碰撞半径，小于该距离的节点会产生排斥力 | number \\| ((node, index, nodes) => number) | 10     |      |\n| collide.strength   | 力的强度，值越大排斥效果越明显         | number                                     | 1      |      |\n| collide.iterations | 碰撞检测的迭代次数                     | number                                     | 1      |      |\n\n#### 径向力（radial）\n\n| 属性            | 描述                                   | 类型                                       | 默认值 | 必选 |\n| --------------- | -------------------------------------- | ------------------------------------------ | ------ | ---- |\n| radial.strength | 力的强度，值越大节点越趋向于目标半径   | number \\| ((node, index, nodes) => number) | 0.1    |      |\n| radial.radius   | 目标半径，节点会被吸引到该半径的圆周上 | number \\| ((node, index, nodes) => number) | 100    |      |\n| radial.x        | 圆心 x 坐标                            | number                                     | 0      |      |\n| radial.y        | 圆心 y 坐标                            | number                                     | 0      |      |\n\n#### X 轴力（x）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| x.strength | X 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| x.x        | 目标 x 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n#### Y 轴力（y）\n\n| 属性       | 描述                                | 类型                                       | 默认值 | 必选 |\n| ---------- | ----------------------------------- | ------------------------------------------ | ------ | ---- |\n| y.strength | Y 轴方向的力强度                    | number \\| ((node, index, nodes) => number) | -      |      |\n| y.y        | 目标 y 坐标，节点会被吸引到这个位置 | number \\| ((node, index, nodes) => number) | -      |      |\n\n## 代码示例\n\n### 防止节点重叠\n\n```js\n{\n  layout: {\n    type: 'd3-force',\n    collide: {\n      // Prevent nodes from overlapping by specifying a collision radius for each node.\n      radius: (d) => d.size / 2,\n    },\n  },\n}\n```\n\n效果见 [示例 - 力导向布局防止节点重叠](/examples/layout/force-directed/#prevent-overlap)\n\n### 团队聚类布局\n\n该示例展示了如何使用力导向布局实现团队聚类效果，不同团队的节点会自动聚集在一起。\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      // 团队 A\n      { id: 'A1', team: 'A', label: 'A1', size: 30 },\n      { id: 'A2', team: 'A', label: 'A2', size: 20 },\n      { id: 'A3', team: 'A', label: 'A3', size: 20 },\n      { id: 'A4', team: 'A', label: 'A4', size: 20 },\n      // 团队 B\n      { id: 'B1', team: 'B', label: 'B1', size: 30 },\n      { id: 'B2', team: 'B', label: 'B2', size: 20 },\n      { id: 'B3', team: 'B', label: 'B3', size: 20 },\n      { id: 'B4', team: 'B', label: 'B4', size: 20 },\n      // 团队 C\n      { id: 'C1', team: 'C', label: 'C1', size: 30 },\n      { id: 'C2', team: 'C', label: 'C2', size: 20 },\n      { id: 'C3', team: 'C', label: 'C3', size: 20 },\n      { id: 'C4', team: 'C', label: 'C4', size: 20 },\n    ],\n    edges: [\n      // 团队 A 内部连接\n      { source: 'A1', target: 'A2' },\n      { source: 'A1', target: 'A3' },\n      { source: 'A1', target: 'A4' },\n      // 团队 B 内部连接\n      { source: 'B1', target: 'B2' },\n      { source: 'B1', target: 'B3' },\n      { source: 'B1', target: 'B4' },\n      // 团队 C 内部连接\n      { source: 'C1', target: 'C2' },\n      { source: 'C1', target: 'C3' },\n      { source: 'C1', target: 'C4' },\n      // 团队间的少量连接\n      { source: 'A1', target: 'B1' },\n      { source: 'B1', target: 'C1' },\n    ],\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\n// 创建模拟数据，包含不同团队的节点\nconst data = {\n  nodes: [\n    // 团队 A\n    { id: 'A1', team: 'A', label: 'A1', size: 30 },\n    { id: 'A2', team: 'A', label: 'A2', size: 20 },\n    { id: 'A3', team: 'A', label: 'A3', size: 20 },\n    { id: 'A4', team: 'A', label: 'A4', size: 20 },\n    // 团队 B\n    { id: 'B1', team: 'B', label: 'B1', size: 30 },\n    { id: 'B2', team: 'B', label: 'B2', size: 20 },\n    { id: 'B3', team: 'B', label: 'B3', size: 20 },\n    { id: 'B4', team: 'B', label: 'B4', size: 20 },\n    // 团队 C\n    { id: 'C1', team: 'C', label: 'C1', size: 30 },\n    { id: 'C2', team: 'C', label: 'C2', size: 20 },\n    { id: 'C3', team: 'C', label: 'C3', size: 20 },\n    { id: 'C4', team: 'C', label: 'C4', size: 20 },\n  ],\n  edges: [\n    // 团队 A 内部连接\n    { source: 'A1', target: 'A2' },\n    { source: 'A1', target: 'A3' },\n    { source: 'A1', target: 'A4' },\n    // 团队 B 内部连接\n    { source: 'B1', target: 'B2' },\n    { source: 'B1', target: 'B3' },\n    { source: 'B1', target: 'B4' },\n    // 团队 C 内部连接\n    { source: 'C1', target: 'C2' },\n    { source: 'C1', target: 'C3' },\n    { source: 'C1', target: 'C4' },\n    // 团队间的少量连接\n    { source: 'A1', target: 'B1' },\n    { source: 'B1', target: 'C1' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: (d) => {\n        // 不同团队使用不同颜色\n        const colors = {\n          A: '#FF6B6B',\n          B: '#4ECDC4',\n          C: '#45B7D1',\n        };\n        return colors[d.team];\n      },\n      labelText: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#fff',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#aaa',\n    },\n  },\n  layout: {\n    type: 'd3-force',\n    // 配置链接力 - 团队内部节点更靠近\n    link: {\n      distance: (d) => {\n        // 同一团队内的连接距离更短\n        if (d.source.team === d.target.team) return 50;\n        // 不同团队间的连接距离更长\n        return 200;\n      },\n      strength: (d) => {\n        // 同一团队内的连接强度更大\n        if (d.source.team === d.target.team) return 0.7;\n        // 不同团队间的连接强度更小\n        return 0.1;\n      },\n    },\n    // 配置多体力 - 控制节点间的排斥力\n    manyBody: {\n      strength: (d) => {\n        // 团队领导节点（编号1）的排斥力更强\n        if (d.label.endsWith('1')) return -100;\n        return -30;\n      },\n    },\n    // 配置碰撞力 - 防止节点重叠\n    collide: {\n      radius: 35,\n      strength: 0.8,\n    },\n    // 配置中心力 - 保持图形在画布中心\n    center: {\n      strength: 0.05,\n    },\n  },\n  behaviors: ['drag-element-force'],\n});\n\ngraph.render();\n```\n\n</details>\n\n主要配置说明：\n\n- `link.distance`：团队内部距离短，团队间距离长\n- `link.strength`：团队内部连接强度大，团队间连接强度小\n- `manyBody.strength`：控制节点间排斥力\n- `collide`：防止节点重叠\n- `center`：保持整体布局在画布中心\n\n还可以参考 [定制不同节点的参数](/examples/layout/force-directed/#functional-params) 示例。\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/DagreLayout.en.md) -->\n---\ntitle: Dagre Layout\norder: 9\n---\n\n# Dagre Layout\n\n## Overview\n\nDagre is a hierarchical layout suitable for directed acyclic graphs (DAGs). It can automatically handle the direction and spacing between nodes and supports both horizontal and vertical layouts. See more Dagre layout [examples](/en/examples#layout-dagre), [source code](https://github.com/dagrejs/dagre/blob/master/lib/layout.js), and [official documentation](https://github.com/dagrejs/dagre/wiki).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre Layout'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## Options\n\n> For more options, refer to the [official documentation](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre Layout Options Illustration\" />\n\n| Property        | Description                                                                                                                                | Type                                                | Default           | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- | ----------------- | -------- |\n| type            | Layout type                                                                                                                                | `dagre`                                             | -                 | ✓        |\n| rankdir         | Layout direction, options                                                                                                                  | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |          |\n| align           | Node alignment, options                                                                                                                    | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |          |\n| nodesep         | Node spacing (px). For `TB` or `BT`, it is the horizontal spacing; for `LR` or `RL`, it is the vertical spacing                            | number                                              | 50                |          |\n| ranksep         | Rank spacing (px). For `TB` or `BT`, it is the vertical spacing between adjacent ranks; for `LR` or `RL`, it is the horizontal spacing     | number                                              | 100               |          |\n| ranker          | Algorithm for assigning ranks to nodes: `longest-path`, `tight-tree`, or `network-simplex`                                                 | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |          |\n| directed        | Whether to treat the graph as directed                                                                                                     | boolean                                             | true              |          |\n| compound        | Whether to support nested structures                                                                                                       | boolean                                             | true              |          |\n| multigraph      | Whether to allow multi-edges                                                                                                               | boolean                                             | true              |          |\n| nodeSize        | G6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |          |\n| edgeMinLen      | Minimum number of ranks crossed by an edge                                                                                                 | number \\| (edge) => number                          | 1                 |          |\n| edgeWeight      | Edge weight, used to affect optimization priority                                                                                          | number \\| (edge) => number                          |                   |          |\n| edgeLabelSize   | Edge label size, used to reserve layout space                                                                                              | number[] \\| (edge) => number[]                      |                   |          |\n| edgeLabelPos    | Edge label position                                                                                                                        | string \\| (edge) => string                          |                   |          |\n| edgeLabelOffset | Offset between the label and the edge                                                                                                      | number \\| (edge) => number                          |                   |          |\n\n> Note: `dagre` does not require configuring `controlPoints` separately. G6 automatically converts the polyline points returned by the layout into `style.controlPoints` on the edge.\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`, **Default**: `TB`\n\nLayout direction\n\n- `TB`: Top to Bottom;\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='Top to Bottom Layout'/>\n\n- `BT`: Bottom to Top;\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='Bottom to Top Layout'/>\n\n- `LR`: Left to Right;\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='Left to Right Layout'/>\n\n- `RL`: Right to Left.\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='Right to Left Layout'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`, **Default**: `UL`\n\nNode alignment\n\n- `UL`: Upper Left\n- `UR`: Upper Right\n- `DL`: Down Left\n- `DR`: Down Right\n\n### nodesep\n\n> number, **Default**: 50\n\nNode spacing (px). For `TB` or `BT`, it's the horizontal spacing; for `LR` or `RL`, it's the vertical spacing\n\n### ranksep\n\n> number, **Default**: 50\n\nRank spacing (px). For `TB` or `BT`, it's the vertical spacing between ranks; for `LR` or `RL`, it's the horizontal spacing between ranks\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`, **Default**: `network-simplex`\n\nAlgorithm for assigning ranks to nodes, supports three algorithms:\n\n- `longest-path`: Uses DFS to recursively find the longest path for each node. Simple and fast, but may result in many long edges.\n- `tight-tree`: An optimization algorithm to reduce the number of long edges. It first uses `longest-path` to compute initial ranks, then adjusts slack edges to build a feasible tree.\n- `network-simplex`: Based on [A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf), iteratively modifies node ranks to minimize slack edges.\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6 custom property, specify node size for all or each node. If a single number, width and height are the same; if array: `[width, height]`\n\n```js\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n## Applicable Scenarios\n\n- **Flowcharts**: Suitable for displaying flowcharts, automatically handling direction and spacing between nodes.\n- **Dependency Graphs**: Display dependencies between packages or modules.\n- **Task Scheduling Graphs**: Show dependencies and execution order between tasks.\n\n## Related Documentation\n\n> The following documents can help you better understand Dagre layout\n\n- [Graph Layout Algorithms｜Detailed Dagre Layout](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [In-depth Interpretation of Dagre Layout Algorithm](https://www.yuque.com/antv/g6-blog/xxp5nl)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/DagreLayout.zh.md) -->\n---\ntitle: Dagre 布局\norder: 9\n---\n\n## 概述\n\nDagre 是一种层次化布局，适用于有向无环图（DAG）的布局场景，能够自动处理节点之间的方向和间距，支持水平和垂直布局。参考更多 Dagre 布局[样例](/examples#layout-dagre)或[源码](https://github.com/dagrejs/dagre/blob/master/lib/layout.js)以及[官方文档](https://github.com/dagrejs/dagre/wiki)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*2uMmRo5wYPUAAAAAAAAAAABkARQnAQ' width=350 alt='Dagre布局'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dagre',\n    rankdir: 'TB',\n    align: 'UL',\n    nodesep: 50,\n    ranksep: 50,\n  },\n});\n```\n\n## 配置项\n\n> 更多配置项可参考[官方文档](https://github.com/dagrejs/dagre/wiki#configuring-the-layout)\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01OpQHBZ1HcpZuWZLS7_!!6000000000779-0-tps-1274-1234.jpg\" width=\"400\" alt=\"Dagre 布局配置项图解\" />\n\n| 属性            | 描述                                                                                                                                            | 类型                                                | 默认值            | 必选 |\n| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ----------------- | ---- |\n| type            | 布局类型                                                                                                                                        | `dagre`                                             | -                 | ✓    |\n| rankdir         | 布局方向，可选值                                                                                                                                | `TB` \\| `BT` \\| `LR` \\| `RL`                        | `TB`              |      |\n| align           | 节点对齐方式，可选值                                                                                                                            | `UL` \\| `UR` \\| `DL` \\| `DR`                        | `UL`              |      |\n| nodesep         | 节点间距（px）。在 rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在 rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距                              | number                                              | 50                |      |\n| ranksep         | 层间距（px）。在 rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在 rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距                            | number                                              | 100               |      |\n| ranker          | 为每个节点分配等级的算法，共支持三种算法，分别是：`longest-path`、`tight-tree`、`network-simplex`                                               | `network-simplex` \\| `tight-tree` \\| `longest-path` | `network-simplex` |      |\n| directed        | 是否按有向图处理                                                                                                                                | boolean                                             | true              |      |\n| compound        | 是否支持嵌套结构                                                                                                                                | boolean                                             | true              |      |\n| multigraph      | 是否允许多重边                                                                                                                                  | boolean                                             | true              |      |\n| nodeSize        | G6 自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个 number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]` | number \\| number[] \\| () => (number \\| number[])    | [0, 0]            |      |\n| edgeMinLen      | 边跨越的最小层数                                                                                                                                | number \\| (edge) => number                          | 1                 |      |\n| edgeWeight      | 边权重，用于影响优化优先级                                                                                                                      | number \\| (edge) => number                          |                   |      |\n| edgeLabelSize   | 边标签尺寸，用于预留空间                                                                                                                        | number[] \\| (edge) => number[]                      |                   |      |\n| edgeLabelPos    | 边标签位置                                                                                                                                      | string \\| (edge) => string                          |                   |      |\n| edgeLabelOffset | 标签与边的偏移                                                                                                                                  | number \\| (edge) => number                          |                   |      |\n\n> 补充：`dagre` 不需要单独配置 `controlPoints`，G6 会把布局输出的折线点自动转换为边的 `style.controlPoints`。\n\n### rankdir\n\n> `TB` | `BT` | `LR` | `RL`， **Default**: `TB`\n\n布局方向\n\n- `TB`：从上到下；\n\n<img src='https://img.alicdn.com/imgextra/i3/O1CN01ulI3Se1DeQUfhQ29v_!!6000000000241-0-tps-1092-1218.jpg' width=170 alt='：从上到下布局'/>\n\n- `BT`：从下到上；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01IfytBS1EOE6NXVprx_!!6000000000341-0-tps-1004-1236.jpg' width=170 alt='从下到上布局'/>\n\n- `LR`：从左到右；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01tpEdMJ1MsTBKpoP6r_!!6000000001490-0-tps-1452-786.jpg' width=170 alt='从左到右布局'/>\n\n- `RL`：从右到左。\n\n<img src='https://img.alicdn.com/imgextra/i4/O1CN01Lw8JHC27j71xd0wl9_!!6000000007832-0-tps-1460-848.jpg' width=170 alt='水平布局'/>\n\n### align\n\n> `UL` | `UR` | `DL` | `DR`， **Default**: `UL`\n\n节点对齐方式\n\n- `UL`：左上对齐\n- `UR`：右上对齐\n- `DL`：左下对齐\n- `DR`：右下对齐\n\n### nodesep\n\n> number， **Default**: 50\n\n节点间距（px）。在rankdir 为 `TB` 或 `BT` 时是节点的水平间距；在rankdir 为 `LR` 或 `RL` 时代表节点的竖直方向间距\n\n### ranksep\n\n> number， **Default**: 50\n\n层间距（px）。在rankdir 为 `TB` 或 `BT` 时是竖直方向相邻层间距；在rankdir 为 `LR` 或 `RL` 时代表水平方向相邻层间距\n\n### ranker\n\n> `network-simplex` | `tight-tree` | `longest-path`， **Default**: `network-simplex`\n\n为每个节点分配层级的算法，共支持三种算法，分别是：\n\n- `longest-path`： 最长路径算法，使用DFS深度优先搜索，递归查找每个节点的最长路径。优点是计算简单速度快，但会导致长边过多；\n- `tight-tree`： 紧凑树算法，一种优化算法，目的是减少长边的数量。先用最长路径算法`longest-path`计算出初始层级，然后调整松弛边的长度，从而构建可行树。\n- `network-simplex`： 网络单形法，参考算法[A Technique for Drawing Directed Graphs](https://www.graphviz.org/documentation/TSE93.pdf)，核心思想是迭代修改节点的层级，缩小松弛边。\n\n### nodeSize\n\n> number \\| number[] \\| () => (number \\| number[])\n\nG6自定义属性，统一指定或为每个节点指定节点大小。如果仅返回单个number，则表示节点的宽度和高度相同；如果返回一个数组，则形如：`[width, height]`\n\n```js\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 20;\n  return [10, 20];\n};\n```\n\n### controlPoints\n\n> boolean， **Default**: false\n\n是否保留边的控制点。\n\n## 布局适用场景\n\n- **流程图**：适合展示流程图，节点之间的方向和间距会自动处理；\n- **依赖关系图**：展示软件包或模块之间的依赖关系；\n- **任务调度图**：展示任务之间的依赖关系和执行顺序。\n\n## 相关文档\n\n> 以下文档可以帮助你更好地理解Dagre 布局\n\n- [图布局算法｜详解 Dagre 布局](https://mp.weixin.qq.com/s/EdyTfFUH7fyMefNSBXI2nA)\n- [深入解读Dagre布局算法](https://www.yuque.com/antv/g6-blog/xxp5nl)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/DendrogramLayout.en.md) -->\n---\ntitle: Dendrogram Layout\norder: 10\n---\n\n## Overview\n\nThe dendrogram layout is suitable for visualizing hierarchical clustering data. Its feature is that all child nodes are laid out on the same level, node size is not considered, and each node is treated as 1px.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='Dendrogram Layout Example'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"Dendrogram Layout Options Illustration\" />\n\n| Property  | Description                                            | Type                                       | Default | Required |\n| --------- | ------------------------------------------------------ | ------------------------------------------ | ------- | -------- |\n| type      | Layout type                                            | `dendrogram`                               | -       | ✓        |\n| direction | Layout direction, [options](#direction)                | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`    |          |\n| nodeSep   | Node spacing, distance between nodes on the same level | number                                     | 20      |          |\n| rankSep   | Rank spacing, distance between different levels        | number                                     | 200     |          |\n| radial    | Whether to enable radial layout, [see below](#radial)  | boolean                                    | false   |          |\n\n### direction\n\nTree layout direction options:\n\n- `TB`: Root at the top, layout downward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB direction'/>\n\n- `BT`: Root at the bottom, layout upward\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT direction'/>\n\n- `LR`: Root at the left, layout to the right\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR direction'/>\n\n- `RL`: Root at the right, layout to the left\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL direction'/>\n\n- `H`: Root in the middle, horizontal symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H direction'/>\n\n- `V`: Root in the middle, vertical symmetric layout\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V direction'/>\n\n### radial\n\nWhether to enable radial layout mode. When enabled, nodes are distributed radially around the root node.\n\nIf `radial` is set to `true`, it is recommended to set `direction` to `'LR'` or `'RL'` for best results.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='Radial Layout'/>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/DendrogramLayout.zh.md) -->\n---\ntitle: 生态树 Dendrogram\norder: 10\n---\n\n## 概述\n\n生态树布局适用于层次聚类数据的可视化，其特点是所有子节点布局在同一层级，不考虑节点大小，每个节点被当成 1px 处理。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' width=400 alt='生态树布局示例'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'dendrogram',\n    direction: 'LR',\n    nodeSep: 30,\n    rankSep: 250,\n    radial: false,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*tTShQLD_dGoAAAAAAAAAAAAAemJ7AQ/original\" width=\"400\" alt=\"生态树配置项图解\" />\n\n| 属性      | 描述                                           | 类型                                       | 默认值 | 必选 |\n| --------- | ---------------------------------------------- | ------------------------------------------ | ------ | ---- |\n| type      | 布局类型                                       | `dendrogram`                               | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                 | `LR` \\| `RL` \\| `TB` \\| `BT` \\| `H` \\| `V` | `LR`   |      |\n| nodeSep   | 节点间距，即同一层级节点之间的距离，单位为像素 | number                                     | 20     |      |\n| rankSep   | 层级间距，即不同层级之间的距离，单位为像素     | number                                     | 200    |      |\n| radial    | 是否启用辐射状布局，[说明](#radial)            | boolean                                    | false  |      |\n\n### direction\n\n树布局的方向，有以下选项：\n\n- `TB`：根节点在上，往下布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*krAnRrLTEnEAAAAAAAAAAABkARQnAQ' width=115 alt='TB方向'/>\n\n- `BT`：根节点在下，往上布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*0HRyS64i7QoAAAAAAAAAAABkARQnAQ' width=115 alt='BT方向'/>\n\n- `LR`：根节点在左，往右布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*T5KZTJdA2OUAAAAAAAAAAABkARQnAQ' width=55 alt='LR方向'/>\n\n- `RL`：根节点在右，往左布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*q7QJQ5RbQ5kAAAAAAAAAAABkARQnAQ' width=55 alt='RL方向'/>\n\n- `H`：根节点在中间，水平对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*tzIfRJ5CuR8AAAAAAAAAAABkARQnAQ' width=85 alt='H方向'/>\n\n- `V`：根节点在中间，垂直对称布局\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*B9sjToOzCiAAAAAAAAAAAABkARQnAQ' width=115 alt='V方向'/>\n\n### radial\n\n是否启用辐射状布局模式。启用后，节点将以根节点为中心呈辐射状分布。\n\n若 `radial` 设置为 `true`，建议将 `direction` 设置为 `'LR'` 或 `'RL'` 以获得最佳效果。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*AhopQI5j-bcAAAAAAAAAAABkARQnAQ' width=175 alt='辐射状布局'/>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/Fishbone.en.md) -->\n---\ntitle: Fishbone Layout\norder: 11\n---\n\n## Overview\n\nFishbone layout is a graphical layout specifically designed for representing hierarchical data. By simulating the shape of a fishbone, it arranges data nodes according to their hierarchy, making the hierarchical relationships of the data clearer and more intuitive. Fishbone layout is especially suitable for datasets that need to show causality, hierarchy, or classification information.\n\n## Use Cases\n\n- Displaying hierarchical data, such as organizational structures or classification systems\n- Showing problem analysis processes, such as fault analysis or quality analysis\n- Displaying decision processes, such as decision trees or factor analysis\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## Options\n\n| Property               | Description                                                                                      | Type                                                                                                                                   | Default  | Required |\n| ---------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- |\n| type                   | Layout type                                                                                      | `fishbone`                                                                                                                             | -        | ✓        |\n| direction              | Layout direction, `RL` (right to left, head on right), `LR` (left to right, head on left)        | `RL` \\| `LR`                                                                                                                           | `RL`     |          |\n| hGap                   | Horizontal gap                                                                                   | number                                                                                                                                 | -        |          |\n| vGap                   | Vertical gap                                                                                     | number                                                                                                                                 | -        |          |\n| getRibSep              | Function to get rib gap                                                                          | (node: NodeData) => number                                                                                                             | () => 60 |          |\n| width                  | Layout width                                                                                     | number                                                                                                                                 | -        |          |\n| height                 | Layout height                                                                                    | number                                                                                                                                 | -        |          |\n| nodeSize               | Node size                                                                                        | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (effective when preLayout is true)                 | boolean                                                                                                                                | -        |          |\n| nodeFilter             | Nodes to participate in this layout                                                              | (node: NodeData) => boolean                                                                                                            | -        |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements (not suitable for pipeline layout) | boolean                                                                                                                                | -        |          |\n\n## Code Example\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Real Case\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone Layout](/en/examples/layout/fishbone/#basic)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/Fishbone.zh.md) -->\n---\ntitle: 鱼骨布局 Fishbone\norder: 11\n---\n\n## 概述\n\n鱼骨布局是一种专门用于表示层次结构数据的图形布局方式。它通过模拟鱼骨的形状，将数据节点按照层次结构排列，使得数据的层次关系更加清晰直观。鱼骨布局特别适用于需要展示因果关系、层次结构或分类信息的数据集。\n\n## 使用场景\n\n- 需要展示层次结构数据，如组织结构、分类体系\n- 需要展示问题分析过程，如故障分析、质量分析\n- 需要展示决策过程，如决策树、影响因素分析\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/fishbone.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n    direction: 'LR',\n    hGap: 50,\n    vGap: 50,\n    getRibSep: () => 60,\n  },\n});\n```\n\n## 配置项\n\n| 属性                   | 描述                                                       | 类型                                                                                                                                   | 默认值   | 必选 |\n| ---------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type                   | 布局类型                                                   | `fishbone`                                                                                                                             | -        | ✓    |\n| direction              | 排布方向，`RL` 从右到左，鱼头在右；`LR` 从左到右，鱼头在左 | `RL` \\| `LR`                                                                                                                           | `RL`     |      |\n| hGap                   | 水平间距                                                   | number                                                                                                                                 | -        |      |\n| vGap                   | 垂直间距                                                   | number                                                                                                                                 | -        |      |\n| getRibSep              | 获取鱼骨间距                                               | (node: NodeData) => number                                                                                                             | () => 60 |      |\n| width                  | 布局宽度                                                   | number                                                                                                                                 | -        |      |\n| height                 | 布局高度                                                   | number                                                                                                                                 | -        |      |\n| nodeSize               | 节点大小                                                   | number \\| [number, number] \\| [number, number, number] \\| ((node: NodeData) => number \\| [number, number] \\| [number, number, number]) | -        |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局，当 preLayout 为 true 时生效        | boolean                                                                                                                                | -        |      |\n| nodeFilter             | 参与该布局的节点                                           | (node: NodeData) => boolean                                                                                                            | -        |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局，不适用于流水线布局     | boolean                                                                                                                                | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: treeToGraphData({\n    nodes: [\n      { id: 'root', data: { label: 'Root' } },\n      { id: 'child1', data: { label: 'Child 1' } },\n      { id: 'child2', data: { label: 'Child 2' } },\n      { id: 'child3', data: { label: 'Child 3' } },\n    ],\n    edges: [\n      { id: 'e1', source: 'root', target: 'child1' },\n      { id: 'e2', source: 'root', target: 'child2' },\n      { id: 'e3', source: 'root', target: 'child3' },\n    ],\n  }),\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'fishbone',\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'Quality',\n        depth: 0,\n        children: ['Machine', 'Method', 'Material', 'Man Power', 'Measurement', 'Milieu'],\n      },\n      {\n        id: 'Machine',\n        depth: 1,\n        children: ['Mill', 'Mixer', 'Metal Lathe'],\n      },\n      {\n        id: 'Mill',\n        depth: 2,\n      },\n      {\n        id: 'Mixer',\n        depth: 2,\n      },\n      {\n        id: 'Metal Lathe',\n        depth: 2,\n        children: ['Milling'],\n      },\n      {\n        id: 'Milling',\n        depth: 3,\n      },\n      {\n        id: 'Method',\n        depth: 1,\n      },\n      {\n        id: 'Material',\n        depth: 1,\n        children: ['Masonite', 'Marscapone', 'Meat'],\n      },\n      {\n        id: 'Masonite',\n        depth: 2,\n        children: ['spearMint', 'pepperMint', 'test1'],\n      },\n      {\n        id: 'spearMint',\n        depth: 3,\n      },\n      {\n        id: 'pepperMint',\n        depth: 3,\n        children: ['test3'],\n      },\n      {\n        id: 'test3',\n        depth: 4,\n      },\n      {\n        id: 'test1',\n        depth: 3,\n        children: ['test4'],\n      },\n      {\n        id: 'test4',\n        depth: 4,\n      },\n      {\n        id: 'Marscapone',\n        depth: 2,\n        children: ['Malty', 'Minty'],\n      },\n      {\n        id: 'Malty',\n        depth: 3,\n      },\n      {\n        id: 'Minty',\n        depth: 3,\n      },\n      {\n        id: 'Meat',\n        depth: 2,\n        children: ['Mutton'],\n      },\n      {\n        id: 'Mutton',\n        depth: 3,\n      },\n      {\n        id: 'Man Power',\n        depth: 1,\n        children: ['Manager', \"Master's Student\", 'Magician', 'Miner', 'Magister', 'Massage Artist'],\n      },\n      {\n        id: 'Manager',\n        depth: 2,\n      },\n      {\n        id: \"Master's Student\",\n        depth: 2,\n      },\n      {\n        id: 'Magician',\n        depth: 2,\n      },\n      {\n        id: 'Miner',\n        depth: 2,\n      },\n      {\n        id: 'Magister',\n        depth: 2,\n        children: ['Malpractice'],\n      },\n      {\n        id: 'Malpractice',\n        depth: 3,\n      },\n      {\n        id: 'Massage Artist',\n        depth: 2,\n        children: ['Masseur', 'Masseuse'],\n      },\n      {\n        id: 'Masseur',\n        depth: 3,\n      },\n      {\n        id: 'Masseuse',\n        depth: 3,\n      },\n      {\n        id: 'Measurement',\n        depth: 1,\n        children: ['Malleability'],\n      },\n      {\n        id: 'Malleability',\n        depth: 2,\n      },\n      {\n        id: 'Milieu',\n        depth: 1,\n        children: ['Marine'],\n      },\n      {\n        id: 'Marine',\n        depth: 2,\n      },\n    ],\n    edges: [\n      {\n        source: 'Quality',\n        target: 'Machine',\n      },\n      {\n        source: 'Quality',\n        target: 'Method',\n      },\n      {\n        source: 'Quality',\n        target: 'Material',\n      },\n      {\n        source: 'Quality',\n        target: 'Man Power',\n      },\n      {\n        source: 'Quality',\n        target: 'Measurement',\n      },\n      {\n        source: 'Quality',\n        target: 'Milieu',\n      },\n      {\n        source: 'Machine',\n        target: 'Mill',\n      },\n      {\n        source: 'Machine',\n        target: 'Mixer',\n      },\n      {\n        source: 'Machine',\n        target: 'Metal Lathe',\n      },\n      {\n        source: 'Metal Lathe',\n        target: 'Milling',\n      },\n      {\n        source: 'Material',\n        target: 'Masonite',\n      },\n      {\n        source: 'Material',\n        target: 'Marscapone',\n      },\n      {\n        source: 'Material',\n        target: 'Meat',\n      },\n      {\n        source: 'Masonite',\n        target: 'spearMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'pepperMint',\n      },\n      {\n        source: 'Masonite',\n        target: 'test1',\n      },\n      {\n        source: 'pepperMint',\n        target: 'test3',\n      },\n      {\n        source: 'test1',\n        target: 'test4',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Malty',\n      },\n      {\n        source: 'Marscapone',\n        target: 'Minty',\n      },\n      {\n        source: 'Meat',\n        target: 'Mutton',\n      },\n      {\n        source: 'Man Power',\n        target: 'Manager',\n      },\n      {\n        source: 'Man Power',\n        target: \"Master's Student\",\n      },\n      {\n        source: 'Man Power',\n        target: 'Magician',\n      },\n      {\n        source: 'Man Power',\n        target: 'Miner',\n      },\n      {\n        source: 'Man Power',\n        target: 'Magister',\n      },\n      {\n        source: 'Man Power',\n        target: 'Massage Artist',\n      },\n      {\n        source: 'Magister',\n        target: 'Malpractice',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseur',\n      },\n      {\n        source: 'Massage Artist',\n        target: 'Masseuse',\n      },\n      {\n        source: 'Measurement',\n        target: 'Malleability',\n      },\n      {\n        source: 'Milieu',\n        target: 'Marine',\n      },\n    ],\n  },\n  edge: {\n    type: 'polyline',\n    style: {\n      lineWidth: 3,\n    },\n  },\n  behaviors: ['drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nconst data = {\n  id: 'Quality',\n  children: [\n    {\n      id: 'Machine',\n      children: [{ id: 'Mill' }, { id: 'Mixer' }, { id: 'Metal Lathe', children: [{ id: 'Milling' }] }],\n    },\n    { id: 'Method' },\n    {\n      id: 'Material',\n      children: [\n        {\n          id: 'Masonite',\n          children: [\n            { id: 'spearMint' },\n            { id: 'pepperMint', children: [{ id: 'test3' }] },\n            { id: 'test1', children: [{ id: 'test4' }] },\n          ],\n        },\n        {\n          id: 'Marscapone',\n          children: [{ id: 'Malty' }, { id: 'Minty' }],\n        },\n        { id: 'Meat', children: [{ id: 'Mutton' }] },\n      ],\n    },\n    {\n      id: 'Man Power',\n      children: [\n        { id: 'Manager' },\n        { id: \"Master's Student\" },\n        { id: 'Magician' },\n        { id: 'Miner' },\n        { id: 'Magister', children: [{ id: 'Malpractice' }] },\n        {\n          id: 'Massage Artist',\n          children: [{ id: 'Masseur' }, { id: 'Masseuse' }],\n        },\n      ],\n    },\n    {\n      id: 'Measurement',\n      children: [{ id: 'Malleability' }],\n    },\n    {\n      id: 'Milieu',\n      children: [{ id: 'Marine' }],\n    },\n  ],\n};\n\nexport const layoutFishbone = async (context) => {\n  const graph = new Graph({\n    ...context,\n    container: 'container',\n    autoFit: 'view',\n    data: treeToGraphData(data),\n    node: {\n      type: 'rect',\n      style: {\n        size: [32, 32],\n        // fill: () => randomColor(),\n        label: false,\n        labelFill: '#262626',\n        labelFontFamily: 'Gill Sans',\n        labelMaxLines: 2,\n        labelMaxWidth: '100%',\n        labelPlacement: 'center',\n        labelText: (d) => d.id,\n        labelWordWrap: true,\n      },\n    },\n    edge: {\n      type: 'polyline',\n      style: {\n        lineWidth: 3,\n      },\n    },\n    layout: {\n      type: 'fishbone',\n      vGap: 48,\n      hGap: 48,\n      direction: 'RL',\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    animation: false,\n  });\n\n  await graph.render();\n\n  layoutFishbone.form = (panel) => {\n    const config = {\n      type: 'fishbone',\n      direction: 'RL',\n    };\n\n    return [\n      panel\n        .add(config, 'direction', ['LR', 'RL'])\n        .name('Direction')\n        .onChange((value) => {\n          graph.setLayout((prev) => ({ ...prev, direction: value }));\n          graph.render();\n        }),\n    ];\n  };\n\n  return graph;\n};\n\nlayoutFishbone();\n```\n\n- [Fishbone布局](/examples/layout/fishbone/#basic)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ForceAtlas2Layout.en.md) -->\n---\ntitle: ForceAtlas2 Force-directed Layout\norder: 12\n---\n\n## Overview\n\nForceAtlas2 is a force-directed layout algorithm that optimizes node positions by simulating forces in a physical system. This layout is especially suitable for visualizing large-scale network data, effectively revealing relationships and cluster structures among nodes.\n\n## Use Cases\n\n- Social network analysis: Display user relationship networks, with node degree reflecting user influence\n- Knowledge graphs: Show associations between concepts, discover knowledge domains through clustering\n- System architecture diagrams: Show dependencies between system components, highlight core components via hub mode\n\n## Online Demo\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## Options\n\n| Property       | Description                                                                                                                                                                   | Type                                | Default  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | -------- |\n| type           | Layout type, must be `force-atlas2`                                                                                                                                           | `force-atlas2`                      | -        | ✓        |\n| maxIteration   | Maximum number of iterations                                                                                                                                                  | number                              | 500      |          |\n| minMovement    | Convergence threshold                                                                                                                                                         | number                              | 0.4      |          |\n| barnesHut      | Whether to enable quadtree acceleration. When enabled, improves performance for large graphs but may affect layout quality. By default, enabled if node count > 250.          | boolean                             | -        |          |\n| dissuadeHubs   | Whether to enable hub mode. If true, nodes with higher in-degree are more likely to be placed at the center than those with high out-degree                                   | boolean                             | false    |          |\n| height         | Layout height. Defaults to container height                                                                                                                                   | number                              | -        |          |\n| kg             | Gravity coefficient. The larger the value, the more concentrated the layout is at the center                                                                                  | number                              | 1        |          |\n| kr             | Repulsion coefficient. Adjusts the compactness of the layout. The larger the value, the looser the layout                                                                     | number                              | 5        |          |\n| ks             | Controls the speed of node movement during iteration                                                                                                                          | number                              | 0.1      |          |\n| ksmax          | Maximum node movement speed during iteration                                                                                                                                  | number                              | 10       |          |\n| mode           | Clustering mode. In `linlog` mode, clusters are more compact                                                                                                                  | `normal` \\| `linlog`                | `normal` |          |\n| nodeSize       | Node size (diameter). Used for repulsion calculation when `preventOverlap` is enabled. If not set, uses `data.size` in node data                                              | Size \\| ((node?: Node) => Size)     | -        |          |\n| nodeSpacing    | Spacing between nodes                                                                                                                                                         | number \\| ((node?: Node) => number) | -        |          |\n| onTick         | Callback for each iteration                                                                                                                                                   | (data: LayoutMapping) => void       | -        |          |\n| preventOverlap | Whether to prevent node overlap. When enabled, layout considers node size to avoid overlap. Node size is specified by `nodeSize` or `data.size` in node data                  | boolean                             | false    |          |\n| prune          | Whether to enable auto-pruning. By default, enabled if node count > 100. Pruning speeds up convergence but may reduce layout quality. Set to false to disable auto-activation | boolean                             | -        |          |\n| tao            | Tolerance for stopping oscillation when layout is near convergence                                                                                                            | number                              | 0.1      |          |\n| width          | Layout width. Defaults to container width                                                                                                                                     | number                              | -        |          |\n| center         | Layout center, format [x, y]. Each node is attracted to this point, gravity controlled by `kg`. If not set, uses canvas center                                                | [number, number]                    | -        |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## Real Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2 Layout](/en/examples/layout/force-directed/#atlas2)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ForceAtlas2Layout.zh.md) -->\n---\ntitle: ForceAtlas2 力导向布局\norder: 12\n---\n\n## 概述\n\nForceAtlas2 是一种基于力导向的布局算法，它通过模拟物理系统中的力来优化节点位置。该布局特别适用于大规模网络数据的可视化，能够有效地展示节点之间的关系和聚类结构。\n\n## 使用场景\n\n- 社交网络分析：展示用户之间的关系网络，通过节点度数反映用户影响力\n- 知识图谱：展示概念之间的关联关系，通过聚类效果发现知识领域\n- 系统架构图：展示系统组件之间的依赖关系，通过 hub 模式突出核心组件\n\n## 在线体验\n\n<embed src=\"@/common/api/layout/force-atlas2.md\"></embed>\n\n## 基本用法\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n    center: [250, 250],\n  },\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                 | 类型                                | 默认值   | 必选 |\n| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------- | ---- |\n| type           | 布局类型，必须为 `force-atlas2`                                                                                                                                      | `force-atlas2`                      | -        | ✓    |\n| maxIteration   | 最大迭代次数                                                                                                                                                         | number                              | 500      |      |\n| minMovement    | 收敛阈值                                                                                                                                                             | number                              | 0.4      |      |\n| barnesHut      | 是否开启四叉树加速，开启后可以提升大规模图的布局性能，但可能会影响布局质量。默认情况下为 undefined，当节点数量大于 250 时它将会被激活。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| dissuadeHubs   | 是否开启 hub 模式。若为 true，相比与出度大的节点，入度大的节点将会有更高的优先级被放置在中心位置                                                                     | boolean                             | false    |      |\n| height         | 布局高度，默认使用容器高度                                                                                                                                           | number                              | -        |      |\n| kg             | 重力系数，`kg` 越大，布局越聚集在中心                                                                                                                                | number                              | 1        |      |\n| kr             | 斥力系数，可用于调整布局的紧凑程度。kr 越大，布局越松散                                                                                                              | number                              | 5        |      |\n| ks             | 控制迭代过程中，节点移动的速度                                                                                                                                       | number                              | 0.1      |      |\n| ksmax          | 迭代过程中，最大的节点移动的速度上限                                                                                                                                 | number                              | 10       |      |\n| mode           | 聚类模式，`linlog` 模式下，聚类将更加紧凑                                                                                                                            | `normal` \\| `linlog`                | `normal` |      |\n| nodeSize       | 节点大小（直径）。当开启 `preventOverlap` 时，用于计算节点之间的斥力。如果不设置，则使用节点数据中的 size 属性                                                       | Size \\| ((node?: Node) => Size)     | -        |      |\n| nodeSpacing    | 节点间距                                                                                                                                                             | number \\| ((node?: Node) => number) | -        |      |\n| onTick         | 每一次迭代的回调函数                                                                                                                                                 | (data: LayoutMapping) => void       | -        |      |\n| preventOverlap | 是否防止节点重叠。开启后，布局会考虑节点大小，避免节点重叠                                                                                                           | boolean                             | false    |      |\n| prune          | 是否开启自动剪枝模式。默认情况下为 undefined，当节点数量大于 100 时它将会被激活。注意，剪枝能够提高收敛速度，但可能会降低图的布局质量。设置为 false 则不会自动被激活 | boolean                             | -        |      |\n| tao            | 迭代接近收敛时停止震荡的容忍度                                                                                                                                       | number                              | 0.1      |      |\n| width          | 布局宽度，默认使用容器宽度                                                                                                                                           | number                              | -        |      |\n| center         | 布局中心点，用于指定重力的中心，格式为 [x, y]。每个节点都会受到一个指向该中心点的重力，重力大小由 `kg` 参数控制。如果不设置，则使用画布中心点                        | [number, number]                    | -        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  autoFit: 'view',\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  layout: {\n    type: 'force-atlas2',\n    preventOverlap: true,\n    kr: 20,\n  },\n  data: {\n    nodes: [\n      { id: 'node1' },\n      { id: 'node2' },\n      { id: 'node3' },\n      { id: 'node4' },\n      { id: 'node5' },\n      { id: 'node6' },\n      { id: 'node7' },\n      { id: 'node8' },\n      { id: 'node9' },\n      { id: 'node10' },\n      { id: 'node11' },\n      { id: 'node12' },\n      { id: 'node13' },\n      { id: 'node14' },\n      { id: 'node15' },\n    ],\n    edges: [\n      { source: 'node1', target: 'node2' },\n      { source: 'node2', target: 'node3' },\n      { source: 'node3', target: 'node4' },\n      { source: 'node4', target: 'node5' },\n      { source: 'node5', target: 'node6' },\n      { source: 'node6', target: 'node7' },\n      { source: 'node7', target: 'node8' },\n      { source: 'node8', target: 'node9' },\n      { source: 'node9', target: 'node10' },\n      { source: 'node10', target: 'node11' },\n      { source: 'node11', target: 'node12' },\n      { source: 'node12', target: 'node13' },\n      { source: 'node13', target: 'node14' },\n      { source: 'node14', target: 'node15' },\n      { source: 'node15', target: 'node1' },\n      { source: 'node1', target: 'node8' },\n      { source: 'node2', target: 'node9' },\n      { source: 'node3', target: 'node10' },\n      { source: 'node4', target: 'node11' },\n      { source: 'node5', target: 'node12' },\n      { source: 'node6', target: 'node13' },\n      { source: 'node7', target: 'node14' },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'view',\n      layout: {\n        type: 'force-atlas2',\n        preventOverlap: true,\n        kr: 20,\n        center: [250, 250],\n      },\n      behaviors: ['zoom-canvas', 'drag-canvas'],\n      autoResize: true,\n      zoomRange: [0.1, 5],\n    });\n\n    graph.render();\n  });\n```\n\n- [ForceAtlas2布局](/examples/layout/force-directed/#atlas2)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ForceLayout.en.md) -->\n---\ntitle: Force-directed Layout\norder: 13\n---\n\n## Overview\n\nForce-directed layout is a graph layout algorithm based on physical simulation that determines node positions by simulating attraction and repulsion forces between nodes. This layout is particularly suitable for displaying complex relationship networks, such as social networks and knowledge graphs.\n\nThe force-directed layout automatically calculates and adjusts node positions to maintain appropriate distances between connected nodes while minimizing edge crossings. During the layout process, it simulates a physical system where nodes repel each other like charged particles, and edges connect nodes like springs.\n\nKey features of force-directed layout include:\n\n1. **Automatic Arrangement**: No need to manually set node positions, the system automatically finds suitable positions\n2. **Real-time Adjustment**: When you drag a node, other nodes will adjust their positions in real-time\n3. **Flexible Configuration**:\n   - Can adjust attraction and repulsion forces between nodes\n   - Can set edge lengths\n   - Can prevent node overlap\n4. **Animation Effects**: Smooth animations during node movement make changes more natural\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='Force-directed Layout Example'/>\n\n## Core Concepts\n\n### Basic Principles of Force-directed Layout\n\nForce-directed layout is a graph layout algorithm based on physical simulation that models nodes and edges as a physical system:\n\n- Nodes are treated as physical particles\n- Edges are treated as springs\n- The entire system reaches its lowest energy state through physical simulation\n\n### Detailed Core Forces\n\n#### Node Repulsion\n\n- **Physical Model**: Coulomb's Law\n- **Function**: Prevents node overlap and ensures more uniform node distribution, where `factor` and `coulombDisScale` control the overall strength and range of repulsion.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='Repulsion Force'/>\n\n  - k: Repulsion coefficient (`factor` / `coulombDisScale²`)\n  - q1,q2: Node strength (`nodeStrength`)\n  - r: Distance between nodes\n\n#### Edge Attraction\n\n- **Physical Model**: Hooke's Law\n- **Function**: Simulates edge tension, moving nodes along edge directions, where `edgeStrength` and `linkDistance` control edge \"stiffness\" and length.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='Edge Attraction'/>\n\n  - ka: Edge attraction strength (`edgeStrength`)\n  - L: Edge length (`linkDistance`)\n  - r: Actual edge length\n\n#### Centripetal Force\n\n- **Physical Model**: Newton's Universal Law of Gravitation\n- **Function**: Attracts nodes toward the canvas center or cluster centers, where `gravity` and `center` control gravity strength and center point position\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Centripetal Force'/>\n\n  - G: Gravitational constant (`gravity`)\n  - xc: Center point coordinates (`center`)\n  - mass: Node mass (`nodeSize`)\n\n#### Interaction of Three Forces\n\n- **Physical Model**: Force interactions, generating acceleration\n- **Function**: Repulsion, edge attraction, and centripetal force work together, affecting node movement through acceleration superposition, ultimately reaching the lowest energy state.\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='Force Interactions'/>\n\n### Physical System\n\n#### Node Velocity Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='Node Velocity Formula'/>\n\n  - v: Velocity\n  - a: Acceleration\n  - dt: Time step (`interval`)\n  - damping: Damping coefficient (`damping`)\n\n- **Function**:\n  1. Controls node movement stability\n  2. Damping coefficient prevents system oscillation\n  3. Time step affects displacement per iteration\n\n#### Node Position Formula\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='Node Position Formula'/>\n\n  - x: Node position\n  - v: Node velocity\n  - dt: Time step (`interval`)\n\n- **Function**:\n  1. Updates node position based on velocity\n  2. Ensures motion continuity\n  3. Prevents node overlap through `preventOverlap`\n\n#### Cluster Center Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='Cluster Center Calculation'/>\n\n  - n: Number of nodes in cluster\n  - (xi​,yi​): Position of each node\n\n- **Function**:\n  1. Calculates cluster center\n  2. Centripetal force pulls nodes toward their cluster center\n  3. Cluster center can change dynamically\n\n#### Cluster Strength Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='Cluster Strength Calculation'/>\n\n  - s: Cluster strength (`clusterNodeStrength`)\n  - xc​: Cluster center\n\n- **Function**:\n  1. Controls cluster compactness\n  2. Higher cluster strength means tighter clusters\n  3. Can be dynamically adjusted based on node properties\n\n#### Mass Effect on Forces\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='Mass Effect on Forces'/>\n\n  - a: Acceleration\n  - F: Force (repulsion, edge attraction, centripetal force)\n  - mass: Node mass\n\n- **Function**:\n  1. Nodes with larger mass move less\n  2. Nodes with smaller mass move more\n  3. Mass calculation can be customized through `getMass`\n\n#### Energy Calculation\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='Energy Calculation'/>\n\n  - m: Node mass\n  - v: Node velocity\n\n- **Function**:\n  1. Monitors layout convergence\n  2. System stabilizes when energy approaches zero\n\n#### System Convergence Condition\n\n- **Formula**:\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='System Convergence Condition'/>\n\n- **Function**:\n  1. Controls iteration count\n  2. Stops when movement is below threshold\n  3. Can choose between mean, maximum, or minimum through `distanceThresholdMode`\n\n### Force Interaction Diagram\n\n```mermaid\ngraph TD\n    A[Input] --> B[Initialize Parameters];\n    B --> C[Build Layout Calculation];\n    C --> D[Iterative Calculation];\n    D --> E{Converged?};\n    E -->|Yes| F[Output Layout];\n    E -->|No| G[Calculate Repulsion];\n    G --> H[Calculate Edge Attraction];\n    H --> I[Calculate Centripetal Force];\n    I --> J[Update Velocity];\n    J --> K[Update Position];\n    K --> D;\n```\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/BOu7Rbuz4MoAAAAAQjAAAAgADpdRAQFr/original' alt='Force Simulation Diagram'/>\n\n## Configuration Options\n\nBased on the physical characteristics of force-directed layout, the following configuration options are available:\n\n### Basic Configuration\n\n| Property              | Description                                                                                                                                                                                                                                        | Default Value | Required |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type                  | Layout type                                                                                                                                                                                                                                        | `force`       | ✓        |\n| dimensions            | Layout dimensions, 2 for 2D layout, 3 for 3D layout                                                                                                                                                                                                | 2             |          |\n| width                 | Layout width                                                                                                                                                                                                                                       | Canvas width  |          |\n| height                | Layout height                                                                                                                                                                                                                                      | Canvas height |          |\n| center                | Layout center point                                                                                                                                                                                                                                | Graph center  |          |\n| maxIteration          | Maximum iteration count, if 0 will auto-adjust                                                                                                                                                                                                     | 0             |          |\n| minMovement           | Stop iteration when average movement distance is less than 0.4                                                                                                                                                                                     | 0.4           |          |\n| distanceThresholdMode | Movement distance calculation mode: mean: stop when average movement distance is less than `minMovement`; max: stop when maximum movement distance is less than `minMovement`; min: stop when minimum movement distance is less than `minMovement` | `mean`        |          |\n| maxDistance           | Maximum distance                                                                                                                                                                                                                                   |               |          |\n\n### Force-related Configuration\n\n#### Repulsion Configuration\n\n| Property        | Description                                                                                         | Default Value | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| nodeStrength    | Node force, positive values represent attraction between nodes, negative values represent repulsion | 1000          |          |\n| factor          | Repulsion coefficient, larger values mean stronger repulsion                                        | 1             |          |\n| coulombDisScale | Coulomb coefficient, a factor for repulsion, larger values mean stronger repulsion between nodes    | 0.005         |          |\n\n#### Edge Attraction Configuration\n\n| Property     | Description                                                                                                    | Default Value | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| edgeStrength | Edge force (attraction) strength, fixed force or callback function to dynamically return different edge forces | 500           |          |\n| linkDistance | Edge length, fixed length or callback function to dynamically return different edge lengths                    | 200           |          |\n\n#### Centripetal Force Configuration\n\n| Property           | Description                                                                                                                                                                                                                                                          | Default Value | Required |\n| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| gravity            | Center force strength, the force attracting all nodes to the center. Larger values mean more compact layout                                                                                                                                                          | 10            |          |\n| centripetalOptions | Centripetal force configuration, including center and strength for leaf nodes, isolated nodes, and other nodes. leaf: leaf node centripetal force; single: single node centripetal force; others: other node centripetal force; center: custom center point function | [0, 0]        |          |\n\n#### Clustering Configuration\n\n| Property            | Description                                                                                                                                                                                                                                                                                                                                                   | Default Value | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| clustering          | Whether to cluster all nodes. If true, will use the field specified by nodeClusterBy in node data for clustering. centripetalOptions.single, centripetalOptions.leaf, and centripetalOptions.others will use the value returned by getClusterNodeStrength; leaf and centripetalOptions.center will use the average center of all nodes in the current cluster | `false`       |          |\n| nodeClusterBy       | Specifies the field name in node data for clustering. Takes effect when clustering is true. Automatically generates centripetalOptions, can be used with clusterNodeStrength                                                                                                                                                                                  |               |          |\n| clusterNodeStrength | Used with clustering and nodeClusterBy to specify the strength of the cluster centripetal force                                                                                                                                                                                                                                                               |               |          |\n| leafCluster         | Whether to cluster leaf nodes. If true, centripetalOptions.single will be 100; centripetalOptions.leaf will use the value returned by getClusterNodeStrength; getClusterNodeStrength.center will return the average center of all leaf nodes                                                                                                                  | false         |          |\n\n#### Performance and Optimization Configuration\n\n| Property        | Description                                                                                                                                                                                                                                                               | Default Value | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| damping         | Damping coefficient, range [0, 1]. Larger values mean slower speed decrease                                                                                                                                                                                               | 0.9           |          |\n| maxSpeed        | Maximum movement length per iteration                                                                                                                                                                                                                                     | 200           |          |\n| interval        | Controls the movement speed of each node per iteration                                                                                                                                                                                                                    | 0.02          |          |\n| preventOverlap  | Whether to prevent overlap. Must be used with nodeSize or data.size in node data. Only when data.size is set in the data or nodeSize is configured in the layout with the same value as the node size in the graph, collision detection for node overlap can be performed | true          |          |\n| nodeSize        | Node size (diameter). Used for collision detection to prevent node overlap. Fixed size or callback function to dynamically return node size                                                                                                                               |               |          |\n| nodeSpacing     | Takes effect when preventOverlap is true. Minimum spacing between node edges to prevent overlap. Can be a callback to set different spacing for different nodes                                                                                                           |               |          |\n| collideStrength | Strength of anti-overlap force, range [0, 1]                                                                                                                                                                                                                              | 1             |          |\n\n#### Other Configuration\n\n| Property  | Description                                                                                                                                                                              | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |\n| getMass   | Callback for the mass of each node. The parameter is the node's internal data, and the return value is the mass                                                                          |               |          |\n| getCenter | Callback for the x, y, and strength of the centripetal force for each node. If not specified, no extra centripetal force is applied                                                      |               |          |\n| onTick    | Callback for each iteration                                                                                                                                                              |               |          |\n| monitor   | Callback for monitoring each iteration. energy indicates the convergence energy of the layout. May incur extra computation if configured; if not configured, no computation is performed |               |          |\n\n## Code Examples\n\n### Basic Usage\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Layout width\n    width: 800,\n    // Layout height\n    height: 600,\n  },\n});\n```\n\n### Preventing Node Overlap\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n  },\n});\n```\n\n### Force-directed Layout\n\nThis example demonstrates how to create a basic force-directed graph using force-directed layout.\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // Prevent node overlap\n    preventOverlap: true,\n    // Node size\n    nodeSize: 20,\n    // Centripetal force\n    gravity: 0.9,\n    // Iteration count\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\nKey configuration explanations:\n\n- `preventOverlap`: Enable node overlap detection\n- `nodeSize`: Set node size\n- `gravity`: Set node centripetal force\n- `iterations`: Set layout calculation precision\n\nYou can also refer to [View Examples](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) for more usage examples.\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/ForceLayout.zh.md) -->\n---\ntitle: Force 力导向布局\norder: 13\n---\n\n## 概述\n\n力导向布局是一种基于物理模拟的图布局算法，它通过模拟节点间的引力和斥力来确定节点的位置。这种布局方式特别适合展示复杂的关系网络，如社交网络、知识图谱等。\n\n力导向布局会自动计算并调整节点位置，使得相连的节点保持适当的距离，同时尽量减少边的交叉。布局过程中会模拟物理系统，节点会像带电粒子一样相互排斥，边则像弹簧一样连接节点。\n\n力导向布局的主要特点包括：\n\n1. **自动排列**：不需要手动设置节点位置，系统会自动找到合适的位置\n2. **实时调整**：当你拖动某个节点时，其他节点会实时跟随调整位置\n3. **灵活配置**：\n   - 可以调整节点间的吸引力和排斥力\n   - 可以设置边的长度\n   - 可以防止节点重叠\n4. **动画效果**：节点移动时会有平滑的动画，让变化更自然\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/pdZUQIReZ_gAAAAAAAAAAAAADpdRAQFr/original' alt='力导向布局示例'/>\n\n## 核心概念\n\n### Force 力导向布局基本原理\n\n力导向布局是一种基于物理模拟的图布局算法，它将图中的节点和边模拟为物理系统：\n\n- 节点被视为物理粒子\n- 边被视为弹簧\n- 整个系统通过物理模拟达到能量最低状态\n\n### 核心力详解\n\n#### 斥力（Node Repulsion）\n\n- **物理模型**：库伦定律（Coulomb's Law）\n- **作用**：防止节点重叠，让节点分布更均匀，其中 `factor` 和 `coulombDisScale` 控制斥力的总体强度和范围。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/7udvQ5K8VvMAAAAAAAAAAAAADpdRAQFr/original' alt='斥力'/>\n\n  - k: 斥力系数（`factor` / `coulombDisScale²`）\n  - q1,q2: 节点强度(`nodeStrength`)\n  - r: 节点间距离\n\n#### 边拉力（Edge Attraction）\n\n- **物理模型**：胡克定律（Hooke's Law）\n- **作用**：模拟边的拉力，使节点沿着边的方向移动，其中 `edgeStrength` 和 `linkDistance` 控制边的“硬度”和长度。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/WY15QYfpMSAAAAAAAAAAAAAADpdRAQFr/original' alt='边拉力'/>\n\n  - ka: 边拉力强度（`edgeStrength`）\n  - L: 边的长度（`linkDistance`）\n  - r: 实际边长度\n\n#### 向心力（Gravity）\n\n- **物理模型**：牛顿万有引力定律（Newton's Universal Law of Gravitational）\n- **作用**：使节点向画布中心或者聚类中心聚集，其中 `gravity` 和 `center` 控制重力强度和中心点位置\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='向心力'/>\n\n  - G: 万有引力常数（`gravity`）\n  - xc: 中心点坐标（`center`）\n  - mass: 节点质量（`nodeSize`）\n\n#### 三种力的相互作用\n\n- **物理模型**：力的相互作用，产生加速度\n- **作用**：斥力、边拉力、向心力共同作用，通过加速度叠加影响节点运动，最终达到能量最低状态。\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/R-26R4Zc09kAAAAAQDAAAAgADpdRAQFr/original' alt='力的相互作用'/>\n\n### 物理系统\n\n#### 节点运动速度公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/4Nk0Q44tWGIAAAAAAAAAAAAADpdRAQFr/original' alt='节点运动速度公式'/>\n\n  - v: 速度\n  - a: 加速度\n  - dt: 时间步长（`interval`）\n  - damping: 阻尼系数（`damping`）\n\n- **作用**：\n  1. 控制节点移动的稳定性\n  2. 阻尼系数防止系统震荡\n  3. 时间步长影响每次迭代的位移\n\n#### 节点位置公式\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/orF2RoAlHwAAAAAAAAAAAAAADpdRAQFr/original' alt='节点位置公式'/>\n\n  - x: 节点位置\n  - v: 节点速度\n  - dt: 时间步长（`interval`）\n\n- **作用**：\n  1. 根据速度更新节点位置\n  2. 确保运动连续性\n  3. 通过 `preventOverlap` 防止节点重叠\n\n#### 聚类中心计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2jc-TrgcG20AAAAAQDAAAAgADpdRAQFr/original' alt='聚类中心计算'/>\n\n  - n: 聚类内节点数量\n  - (xi​,yi​): 每个节点的位置\n\n- **作用**：\n  1. 计算聚类中心\n  2. 向心力将节点拉向所属聚类中心\n  3. 聚类中心可动态变化\n\n#### 聚类强度计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/sVEtTLyM3rwAAAAAAAAAAAAADpdRAQFr/original' alt='聚类强度计算'/>\n\n  - s: 聚类强度（`clusterNodeStrength`）\n  - xc​: 聚类中心\n\n- **作用**：\n  1. 控制聚类的紧密程度\n  2. 聚类强度越大，聚类越紧凑\n  3. 可根据节点属性动态调整\n\n#### 质量对力的影响\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/5ckVQ6gHQygAAAAAQBAAAAgADpdRAQFr/original' alt='质量对力的影响'/>\n\n  - a: 加速度\n  - F: 力（斥力、边拉力、向心力）\n  - mass: 节点质量\n\n- **作用**：\n  1. 质量大的节点移动较小\n  2. 质量小的节点移动较大\n  3. 通过 `getMass` 可自定义质量计算\n\n#### 能量计算\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/M84ERKphqf0AAAAAAAAAAAAADpdRAQFr/original' alt='能量计算'/>\n\n  - m: 节点质量\n  - v: 节点速度\n\n- **作用**：\n  1. 监控布局收敛情况\n  2. 能量趋近于零时系统趋于稳定\n\n#### 系统收敛条件\n\n- **公式**：\n  <img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/oBHdRLKIEAcAAAAAQFAAAAgADpdRAQFr/original' alt='系统收敛条件'/>\n\n- **作用**：\n  1. 控制迭代次数\n  2. 移动量小于阈值时停止\n  3. 通过 `distanceThresholdMode` 可选择平均值、最大值或最小值\n\n### 力相互作用图\n\n<img src='https://mdn.alipayobjects.com/huamei_4greni/afts/img/2lI1RruANXoAAAAAAAAAAAAADpdRAQFr/original' alt='力作用模拟图'/>\n\n## 配置项\n\n根据上述力导向布局的物理特性，有以下配置项：\n\n### 基础配置\n\n| 属性                  | 描述                                                                                                                                                         | 默认值   | 必选 |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | ---- |\n| type                  | 布局类型                                                                                                                                                     | `force`  | ✓    |\n| dimensions            | 布局维度，2表示2D布局，3表示3D布局                                                                                                                           | 2        |      |\n| width                 | 布局宽度                                                                                                                                                     | 画布宽度 |      |\n| height                | 布局高度                                                                                                                                                     | 画布高度 |      |\n| center                | 布局的中心点                                                                                                                                                 | 图中心   |      |\n| maxIteration          | 最大迭代次数，若为 0 则将自动调整                                                                                                                            | 0        |      |\n| minMovement           | 当平均移动距离小于0.4时停止迭代                                                                                                                              | 0.4      |      |\n| distanceThresholdMode | 移动距离的计算模式：mean: 平均移动距离小于 `minMovement` 时停止迭代；max: 最大移动距离小于时 `minMovement` 时停止迭代；min: 最小移动距离小于时 `minMovement` | `mean`   |      |\n| maxDistance           | 最大距离                                                                                                                                                     |          |      |\n\n### 力相关配置\n\n#### 斥力配置\n\n| 属性            | 描述                                                               | 默认值 | 必选 |\n| --------------- | ------------------------------------------------------------------ | ------ | ---- |\n| nodeStrength    | 节点作用力，正数代表节点之间的引力作用，负数代表节点之间的斥力作用 | 1000   |      |\n| factor          | 斥力系数，数值越大，斥力越大                                       | 1      |      |\n| coulombDisScale | 库伦系数，斥力的一个系数，数字越大，节点之间的斥力越大             | 0.005  |      |\n\n#### 边拉力配置\n\n| 属性         | 描述                                                               | 默认值 | 必选 |\n| ------------ | ------------------------------------------------------------------ | ------ | ---- |\n| edgeStrength | 边的作用力（引力）大小，固定作用力或回调函数动态返回不同边的作用力 | 500    |      |\n| linkDistance | 边的长度，固定长度或回调函数动态返回不同边的长度                   | 200    |      |\n\n#### 向心力配置\n\n| 属性               | 描述                                                                                                                                                         | 默认值 | 必选 |\n| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | ---- |\n| gravity            | 向中心力大小，指所有节点被吸引到 center 的力。数字越大，布局越紧凑                                                                                           | 10     |      |\n| centripetalOptions | 向心力配置，包括叶子节点、离散点、其他节点的向心中心及向心力大小。leaf: 叶子节点向心力；single: 单点向心力；others: 其他节点向心力；center: 自定义中心点函数 | [0, 0] |      |\n\n#### 聚类配置\n\n| 属性                | 描述                                                                                                                                                                                                                                                                                                      | 默认值  | 必选 |\n| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---- |\n| clustering          | 是否需要全部节点聚类，若为 `true`，将使用 `nodeClusterBy` 配置的节点数据中的字段作为聚类依据。 `centripetalOptions.single`、`centripetalOptions.leaf`、`centripetalOptions.others` 将使用 `getClusterNodeStrength` 返回值；`leaf`、`centripetalOptions.center` 将使用当前节点所属聚类中所有节点的平均中心 | `false` |      |\n| nodeClusterBy       | 指定节点数据中的字段名称作为节点聚类的依据，`clustering` 为 true 时生效，自动生成 `centripetalOptions`，可配合 `clusterNodeStrength` 使用                                                                                                                                                                 |         |      |\n| clusterNodeStrength | 配合 `clustering` 和 `nodeClusterBy` 使用，指定聚类向心力的大小                                                                                                                                                                                                                                           |         |      |\n| leafCluster         | 是否需要叶子节点聚类，若为 `true`，则 `centripetalOptions.single` 将为 100；`centripetalOptions.leaf` 将使用 `getClusterNodeStrength` 返回值；`getClusterNodeStrength.center` 将为叶子节点返回当前所有叶子节点的平均中心                                                                                  | false   |      |\n\n#### 性能与优化配置\n\n| 属性            | 描述                                                                                                                                                                                           | 默认值 | 必选 |\n| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| damping         | 阻尼系数，取值范围 [0, 1]。数字越大，速度降低得越慢                                                                                                                                            | 0.9    |      |\n| maxSpeed        | 一次迭代的最大移动长度                                                                                                                                                                         | 200    |      |\n| interval        | 控制每个迭代节点的移动速度                                                                                                                                                                     | 0.02   |      |\n| preventOverlap  | 是否防止重叠，必须配合下面属性 `nodeSize` 或节点数据中的 `data.size` 属性，只有在数据中设置了 `data.size` 或在该布局中配置了与当前图节点大小相同的 `nodeSize` 值，才能够进行节点重叠的碰撞检测 | true   |      |\n| nodeSize        | 节点大小（直径）。用于防止节点重叠时的碰撞检测，固定大小或者回调函数动态返回节点大小                                                                                                           |        |      |\n| nodeSpacing     | `preventOverlap` 为 `true` 时生效, 防止重叠时节点边缘间距的最小值。可以是回调函数, 为不同节点设置不同的最小间距                                                                                |        |      |\n| collideStrength | 防止重叠的力强度，范围 [0, 1]                                                                                                                                                                  | 1      |      |\n\n#### 其他配置\n\n| 属性      | 描述                                                                                                                                                                                                | 默认值 | 必选 |\n| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ---- |\n| getMass   | 获取节点质量的回调函数，入参为节点内部流转数据，用于计算节点质量大小                                                                                                                                |        |      |\n| getCenter | 每个节点中心力的 x、y、强度的回调函数，若不指定，则没有额外中心力                                                                                                                                   |        |      |\n| onTick    | 每一次迭代的回调函数                                                                                                                                                                                |        |      |\n| monitor   | 每个迭代的监控信息回调，energy 表示布局的收敛能量。若配置可能带来额外的计算能量性能消耗，不配置则不计算。入参为迭代监控信息 `{ energy: number; nodes: Node[]; edges: Edge[]; iterations: number; }` |        |      |\n\n## 代码示例\n\n### 基础用法\n\n```js\nconst graph = new Graph({\n  container: 'container',\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 布局宽度\n    width: 800,\n    // 布局高度\n    height: 600,\n  },\n});\n```\n\n### 防止节点重叠\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n  },\n});\n```\n\n### 力导向布局\n\n该示例展示了如何使用力导向布局创建一个基础的力导向图。\n\n```js\nimport { Graph, NodeEvent } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'Node 1', size: 30 },\n    { id: 'node2', label: 'Node 2', size: 20 },\n    { id: 'node3', label: 'Node 3', size: 20 },\n    { id: 'node4', label: 'Node 4', size: 20 },\n    { id: 'node5', label: 'Node 5', size: 30 },\n    { id: 'node6', label: 'Node 6', size: 20 },\n  ],\n  edges: [\n    { source: 'node1', target: 'node2' },\n    { source: 'node1', target: 'node3' },\n    { source: 'node2', target: 'node4' },\n    { source: 'node3', target: 'node4' },\n    { source: 'node4', target: 'node5' },\n    { source: 'node5', target: 'node6' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  autoFit: 'view',\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n  },\n  layout: {\n    type: 'force',\n    // 防止节点重叠\n    preventOverlap: true,\n    // 节点大小\n    nodeSize: 20,\n    // 向心力\n    gravity: 0.9,\n    // 迭代次数\n    iterations: 100,\n  },\n  node: {\n    style: {\n      size: (d) => d.size,\n      fill: '#9EC9FF',\n      stroke: '#69C8FF',\n      label: (d) => d.label,\n      labelPlacement: 'center',\n      labelFill: '#333',\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#e2e2e2',\n    },\n  },\n});\n\ngraph.on(NodeEvent.CLICK, async (e) => {\n  const nodeId = e.target.id;\n  graph.updateNodeData([{ id: nodeId, size: 200 }]);\n  await graph.render();\n});\n\ngraph.render();\n```\n\n主要配置说明：\n\n- `preventOverlap`: 开启节点重叠检测\n- `nodeSize`: 设置节点大小\n- `gravity`: 设置节点向心力\n- `iterations`: 设置布局计算的精确程度\n\n还可以参考 [查看示例](https://g6.antv.antgroup.com/examples/layout/force-directed/#force) 获取更多用法。\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/FruchtermanLayout.en.md) -->\n---\ntitle: Fruchterman Force-directed Layout\norder: 14\n---\n\n## Overview\n\nThe Fruchterman layout is a force-directed layout based on the algorithm from [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf). By flexibly configuring parameters to simulate physical forces, the layout automatically reaches a stable equilibrium state with minimal energy. It supports both basic uniform distribution and cluster layouts. See more Fruchterman force-directed layout [examples](/en/examples#layout-fruchterman) and [source code](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts).\n\n## Use Cases\n\n- Basic uniform distribution: Suitable for displaying network graphs with evenly distributed nodes and clear overall structure, such as network topology and knowledge graphs.\n- Cluster layout: Suitable for visualizing data with internal aggregation or grouping, such as community structure display and association group analysis.\n\n## Options\n\n| Property     | Description                                                                                                                                                                                        | Type                                                                                                       | Default          | Required |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------- | -------- |\n| type         | Layout type                                                                                                                                                                                        | `'fruchterman'`                                                                                            | -                | ✓        |\n| height       | Layout height                                                                                                                                                                                      | `number`                                                                                                   | container height |          |\n| width        | Layout width                                                                                                                                                                                       | `number`                                                                                                   | container width  |          |\n| maxIteration | Maximum number of iterations                                                                                                                                                                       | `number`                                                                                                   | 500              |          |\n| minMovement  | Convergence threshold                                                                                                                                                                              | `number`                                                                                                   | 0.4              |          |\n| gravity      | Central force, i.e., the force attracting all nodes to the [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915). The larger the value, the more compact the layout | `number`                                                                                                   | 10               |          |\n| speed        | Node movement speed per iteration. Too high a speed may cause strong oscillation                                                                                                                   | `number`                                                                                                   | 5                |          |\n| onTick       | Callback for each iteration                                                                                                                                                                        | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -                |          |\n\n### Cluster Layout\n\n| Property       | Description                                                                               | Type      | Default     | Required |\n| -------------- | ----------------------------------------------------------------------------------------- | --------- | ----------- | -------- |\n| clustering     | Whether to use cluster layout                                                             | `boolean` | `false`     |          |\n| nodeClusterBy  | Field name in node data for clustering, effective when `clustering` is true               | `string`  | `'cluster'` |          |\n| clusterGravity | Gravity within clusters, affects cluster compactness, effective when `clustering` is true | `number`  | 10          |          |\n\n## Example Code\n\n### Basic Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### Cluster Layout\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>Show full code</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // Cluster layout parameters\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/FruchtermanLayout.zh.md) -->\n---\ntitle: Fruchterman 力导向布局\norder: 14\n---\n\n## 概述\n\nFruchterman 布局是基于 [Graph Drawing by Force-directed Placement](https://www.mathe2.uni-bayreuth.de/axel/papers/reingold:graph_drawing_by_force_directed_placement.pdf) 算法实现的一种力导向布局，通过灵活的参数配置模拟物理作用，使整个布局自动达到能量最小的稳定平衡状态，支持基础均匀分布和聚类布局。参考更多 Fruchterman 力导向布局[样例](/examples#layout-fruchterman)和[源码](https://github.com/antvis/layout/blob/v5/packages/layout/src/fruchterman.ts)\n\n## 使用场景\n\n- 基础均匀分布: 适用于展示节点均匀分布，整体结构清晰的网络关系图, 比如网络拓扑、知识图谱。\n- 聚类布局: 适用于具有内部聚合特性或分组的数据可视化展示, 比如社区结构展示、关联组分析。\n\n## 配置项\n\n| 属性         | 描述                                                                                                                                           | 类型                                                                                                       | 默认值   | 必选 |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------- | ---- |\n| type         | 布局类型                                                                                                                                       | `'fruchterman'`                                                                                            | -        | ✓    |\n| height       | 布局的高度                                                                                                                                     | `number`                                                                                                   | 容器高度 |      |\n| width        | 布局的宽度                                                                                                                                     | `number`                                                                                                   | 容器宽度 |      |\n| maxIteration | 最大迭代次数                                                                                                                                   | `number`                                                                                                   | 500      |      |\n| minMovement  | 收敛阈值                                                                                                                                       | `number`                                                                                                   | 0.4      |      |\n| gravity      | 中心力大小，指所有节点被吸引到 [center](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L915) 的力。数字越大，布局越紧凑 | `number`                                                                                                   | 10       |      |\n| speed        | 每次迭代节点移动的速度。速度太快可能会导致强烈震荡                                                                                             | `number`                                                                                                   | 5        |      |\n| onTick       | 每一次迭代的回调函数                                                                                                                           | (data: [LayoutMapping](https://github.com/antvis/layout/blob/v5/packages/layout/src/types.ts#L69)) => void | -        |      |\n\n### 聚类布局\n\n| 属性           | 描述                                                                       | 类型      | 默认值      | 必选 |\n| -------------- | -------------------------------------------------------------------------- | --------- | ----------- | ---- |\n| clustering     | 是否按照聚类布局                                                           | `boolean` | `false`     |      |\n| nodeClusterBy  | 聚类布局依据的节点数据 `data` 中的字段名，在 `clustering` 为 `true` 时生效 | `string`  | `'cluster'` |      |\n| clusterGravity | 聚类内部的重力大小，影响聚类的紧凑程度，在 `clustering` 为 `true` 时生效   | `number`  | 10          |      |\n\n## 示例代码\n\n### 基本布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0' },\n      { id: '1' },\n      { id: '2' },\n      { id: '3' },\n      { id: '4' },\n      { id: '5' },\n      { id: '6' },\n      { id: '7' },\n      { id: '8' },\n      { id: '9' },\n      { id: '10' },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '3' },\n      { source: '0', target: '4' },\n      { source: '0', target: '7' },\n      { source: '0', target: '8' },\n      { source: '0', target: '9' },\n      { source: '0', target: '10' },\n      { source: '2', target: '3' },\n      { source: '4', target: '5' },\n      { source: '4', target: '6' },\n      { source: '5', target: '6' },\n      { source: '9', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0' },\n    { id: '1' },\n    { id: '2' },\n    { id: '3' },\n    { id: '4' },\n    { id: '5' },\n    { id: '6' },\n    { id: '7' },\n    { id: '8' },\n    { id: '9' },\n    { id: '10' },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '3' },\n    { source: '0', target: '4' },\n    { source: '0', target: '7' },\n    { source: '0', target: '8' },\n    { source: '0', target: '9' },\n    { source: '0', target: '10' },\n    { source: '2', target: '3' },\n    { source: '4', target: '5' },\n    { source: '4', target: '6' },\n    { source: '5', target: '6' },\n    { source: '9', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 5,\n    speed: 5,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n### 聚类布局\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 500,\n  height: 250,\n  data: {\n    nodes: [\n      { id: '0', data: { cluster: 'a' } },\n      { id: '1', data: { cluster: 'a' } },\n      { id: '2', data: { cluster: 'a' } },\n      { id: '3', data: { cluster: 'a' } },\n      { id: '4', data: { cluster: 'a' } },\n      { id: '5', data: { cluster: 'b' } },\n      { id: '6', data: { cluster: 'b' } },\n      { id: '7', data: { cluster: 'b' } },\n      { id: '8', data: { cluster: 'c' } },\n      { id: '9', data: { cluster: 'c' } },\n      { id: '10', data: { cluster: 'c' } },\n    ],\n    edges: [\n      { source: '0', target: '1' },\n      { source: '0', target: '2' },\n      { source: '0', target: '4' },\n      { source: '0', target: '6' },\n      { source: '2', target: '3' },\n      { source: '2', target: '4' },\n      { source: '3', target: '4' },\n      { source: '5', target: '6' },\n      { source: '6', target: '7' },\n      { source: '7', target: '8' },\n      { source: '8', target: '9' },\n      { source: '8', target: '10' },\n    ],\n  },\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n<details><summary>展开查看完整代码</summary>\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: '0', data: { cluster: 'a' } },\n    { id: '1', data: { cluster: 'a' } },\n    { id: '2', data: { cluster: 'a' } },\n    { id: '3', data: { cluster: 'a' } },\n    { id: '4', data: { cluster: 'a' } },\n    { id: '5', data: { cluster: 'b' } },\n    { id: '6', data: { cluster: 'b' } },\n    { id: '7', data: { cluster: 'b' } },\n    { id: '8', data: { cluster: 'c' } },\n    { id: '9', data: { cluster: 'c' } },\n    { id: '10', data: { cluster: 'c' } },\n  ],\n  edges: [\n    { source: '0', target: '1' },\n    { source: '0', target: '2' },\n    { source: '0', target: '4' },\n    { source: '0', target: '6' },\n    { source: '2', target: '3' },\n    { source: '2', target: '4' },\n    { source: '3', target: '4' },\n    { source: '5', target: '6' },\n    { source: '6', target: '7' },\n    { source: '7', target: '8' },\n    { source: '8', target: '9' },\n    { source: '8', target: '10' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => `${d.data.cluster}-${d.id}`,\n    },\n    palette: {\n      type: 'group',\n      field: 'cluster',\n    },\n  },\n  edge: {\n    style: {\n      endArrow: true,\n    },\n  },\n  layout: {\n    type: 'fruchterman',\n    gravity: 6,\n    speed: 5,\n\n    // 聚类布局参数\n    clustering: true,\n    nodeClusterBy: 'cluster',\n    clusterGravity: 3,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n</details>\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/GridLayout.en.md) -->\n---\ntitle: Grid Layout\norder: 15\n---\n\n## Overview\n\nThe grid layout arranges nodes in a grid pattern, suitable for scenarios where nodes need to be arranged neatly. This layout supports automatic calculation of the number of rows and columns, or you can specify them manually. It also supports preventing node overlap.\n\n## Use Cases\n\n- Visualizing data in a matrix or table format\n\n## Online Demo\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## Options\n\n| Property              | Description                                                                                                                     | Type                                             | Default   | Required |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | -------- |\n| type                  | Layout type                                                                                                                     | `grid`                                           | -         | ✓        |\n| begin                 | Grid start position (top-left corner), default is `[0, 0]`                                                                      | [number, number]                                 | [0, 0]    |          |\n| cols                  | Number of columns. If undefined, the algorithm calculates it automatically based on node count, layout space, and rows (if set) | number                                           | undefined |          |\n| rows                  | Number of rows. If undefined, the algorithm calculates it automatically based on node count, layout space, and cols (if set)    | number                                           | 10        |          |\n| width                 | Layout area width. In G6, the container width is used as the default value                                                      | number                                           | 300       |          |\n| height                | Layout area height. In G6, the container height is used as the default value                                                    | number                                           | 300       |          |\n| condense              | If false, uses all available canvas space; if true, uses the minimum canvas space                                               | boolean                                          | false     |          |\n| nodeSize              | Node size (diameter), used for collision detection when preventing overlap                                                      | Size \\| ((nodeData: Node) => Size)               | -         |          |\n| nodeSpacing           | Node spacing, used to adjust the gap between nodes                                                                              | ((node?: Node) => number) \\| number              | -         |          |\n| position              | Specify the row and column for each node                                                                                        | (node?: Node) => { row?: number; col?: number; } | undefined |          |\n| preventOverlap        | Whether to prevent node overlap. Requires nodeSize or size property in node data                                                | boolean                                          | false     |          |\n| preventOverlapPadding | Padding when preventing overlap. Effective when preventOverlap is true                                                          | number                                           | 10        |          |\n| sortBy                | Sort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting              | string                                           | undefined |          |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\nWhether to prevent overlap\n\nMust be used with nodeSize or the size property in node data. Only when data has data.size or nodeSize is set in the layout, collision detection for node overlap can be performed.\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\nPadding when preventing overlap. Effective when preventOverlap is true.\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\nSort basis (node property name). Higher values are placed more centrally. If undefined, degree is used for sorting. In G6, the container width is used as the default value for grid layout width. When used alone, the default is 300.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Custom Configuration\n\nYou can customize the grid layout in various ways:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // Start layout from [50, 50]\n    cols: 4, // 4 columns\n    rows: 6, // 6 rows\n    width: 400, // Layout area width\n    height: 600, // Layout area height\n    preventOverlap: true, // Prevent node overlap\n    nodeSize: 30, // Node size\n    condense: true, // Use minimum space\n    sortBy: 'value', // Sort by value property\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // Property for sorting\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### Specify Node Position\n\nYou can specify the position for specific nodes using the `position` property:\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // Specify position for specific nodes\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // Top-left\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // Top-right\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // Bottom-left\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // Bottom-right\n      return undefined; // Other nodes are auto-arranged\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\nResult:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## Real Cases\n\n- [Grid Layout](/en/examples/layout/grid/#basic)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/GridLayout.zh.md) -->\n---\ntitle: 网格布局 Grid\norder: 15\n---\n\n## 概述\n\n网格布局将节点按照网格形式排列，适用于需要整齐排列节点的场景。该布局支持自动计算行列数，也可以手动指定行列数，并支持防止节点重叠。\n\n## 使用场景\n\n- 在数据可视化中需要展示矩阵或表格形式的数据关系\n\n## 在线体验\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: {\n      nodes: Array.from({ length: 25 }, (_, i) => ({\n        id: `node-${i}`,\n        data: {\n          value: Math.random() * 100,\n        },\n      })),\n      edges: Array.from({ length: 20 }, (_, i) => ({\n        id: `edge-${i}`,\n        source: `node-${Math.floor(Math.random() * 25)}`,\n        target: `node-${Math.floor(Math.random() * 25)}`,\n      })),\n    },\n    autoFit: 'view',\n    node: {\n      style: {\n        size: 20,\n        label: true,\n        labelText: (datum) => datum.id,\n        labelBackground: true,\n        icon: false,\n      },\n      palette: {\n        type: 'group',\n        field: (datum) => datum.data.value,\n        color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#bfbfbf',\n      },\n    },\n    behaviors: ['drag-canvas'],\n    layout: {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    },\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    const options = {\n      type: 'grid',\n      cols: 5,\n      rows: 5,\n      width: 400,\n      height: 400,\n      preventOverlap: true,\n      nodeSize: 30,\n      condense: false,\n    };\n\n    const optionFolder = gui.addFolder('Grid Layout Options');\n    optionFolder.add(options, 'type').disable(true);\n    optionFolder.add(options, 'cols', 2, 10, 1);\n    optionFolder.add(options, 'rows', 2, 10, 1);\n    optionFolder.add(options, 'width', 200, 600, 50);\n    optionFolder.add(options, 'height', 200, 600, 50);\n    optionFolder.add(options, 'preventOverlap');\n    optionFolder.add(options, 'nodeSize', 10, 50, 5);\n    optionFolder.add(options, 'condense');\n\n    optionFolder.onChange(({ property, value }) => {\n      graph.setLayout({\n        type: 'grid',\n        [property]: value,\n      });\n      graph.layout();\n    });\n  },\n);\n```\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [0, 0],\n    cols: 5,\n    rows: 5,\n    width: 300,\n    height: 300,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: false,\n  },\n});\n```\n\n## 配置项\n\n| 属性                  | 描述                                                                                                                             | 类型                                             | 默认值    | 必选 |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | --------- | ---- |\n| type                  | 布局类型                                                                                                                         | `grid`                                           | -         | ✓    |\n| begin                 | 网格开始位置（左上角），默认为 `[0, 0]`                                                                                          | [number, number]                                 | [0, 0]    |      |\n| cols                  | 网格的列数，为 undefined 时算法根据节点数量、布局空间、rows（若指定）自动计算                                                    | number                                           | undefined |      |\n| rows                  | 网格的行数，为 undefined 时算法根据节点数量、布局空间、cols（若指定）自动计算                                                    | number                                           | 10        |      |\n| width                 | 布局区域宽度，在 G6 中使用当前容器的宽度作为默认值                                                                               | number                                           | 300       |      |\n| height                | 布局区域高度，在 G6 中使用当前容器的高度作为默认值                                                                               | number                                           | 300       |      |\n| condense              | 为 false 时表示利用所有可用画布空间，为 true 时表示利用最小的画布空间                                                            | boolean                                          | false     |      |\n| nodeSize              | 节点大小（直径），用于防止节点重叠时的碰撞检测                                                                                   | Size \\| ((nodeData: Node) => Size)               | -         |      |\n| nodeSpacing           | 节点间距，用于调整节点之间的间隔                                                                                                 | ((node?: Node) => number) \\| number              | -         |      |\n| position              | 指定每个节点所在的行和列                                                                                                         | (node?: Node) => { row?: number; col?: number; } | undefined |      |\n| preventOverlap        | 是否防止节点重叠，需要配合 nodeSize 或节点数据中的 size 属性使用                                                                 | boolean                                          | false     |      |\n| preventOverlapPadding | 避免重叠时节点的间距 padding，preventOverlap 为 true 时生效                                                                      | number                                           | 10        |      |\n| sortBy                | 指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心 | string                                           | undefined |      |\n\n### preventOverlap\n\n> _boolean_ **Default:** `false`\n\n是否防止重叠\n\n必须配合下面属性 nodeSize 或节点数据中的 data.size 属性，只有在数据中设置了 data.size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值，才能够进行节点重叠的碰撞检测\n\n### preventOverlapPadding\n\n> _number_ **Default:** `10`\n\n避免重叠时节点的间距 padding，preventOverlap 为 true 时生效\n\n### sortBy\n\n> _string_ **Default:** `undefined`\n\n指定排序的依据（节点属性名），数值越高则该节点被放置得越中心。若为 undefined，则会计算节点的度数，度数越高，节点将被放置得越中心\n\n在 G6 中使用当前容器的宽度作为 grid 布局 width 的默认值。单独使用此布局时默认值为 300\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 自定义配置\n\n可以通过多种方式自定义网格布局：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    begin: [50, 50], // 从坐标 [50, 50] 开始布局\n    cols: 4, // 指定 4 列\n    rows: 6, // 指定 6 行\n    width: 400, // 布局区域宽度\n    height: 600, // 布局区域高度\n    preventOverlap: true, // 防止节点重叠\n    nodeSize: 30, // 节点大小\n    condense: true, // 使用最小空间\n    sortBy: 'value', // 按 value 属性排序\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100, // 用于排序的属性\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    begin: [50, 50],\n    cols: 4,\n    rows: 6,\n    width: 400,\n    height: 600,\n    preventOverlap: true,\n    nodeSize: 30,\n    condense: true,\n    sortBy: 'value',\n  },\n  data: {\n    nodes: Array.from({ length: 24 }, (_, i) => ({\n      id: `node-${i}`,\n      data: {\n        value: Math.random() * 100,\n      },\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 24)}`,\n      target: `node-${Math.floor(Math.random() * 24)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n    palette: {\n      type: 'group',\n      field: (datum) => datum.data.value,\n      color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n### 指定节点位置\n\n可以通过 `position` 属性为特定节点指定位置：\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      // 为特定节点指定位置\n      if (node.id === 'node-0') return { row: 0, col: 0 }; // 左上角\n      if (node.id === 'node-1') return { row: 0, col: 4 }; // 右上角\n      if (node.id === 'node-2') return { row: 4, col: 0 }; // 左下角\n      if (node.id === 'node-3') return { row: 4, col: 4 }; // 右下角\n      return undefined; // 其他节点自动布局\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  layout: {\n    type: 'grid',\n    cols: 5,\n    rows: 5,\n    position: (node) => {\n      if (node.id === 'node-0') return { row: 0, col: 0 };\n      if (node.id === 'node-1') return { row: 0, col: 4 };\n      if (node.id === 'node-2') return { row: 4, col: 0 };\n      if (node.id === 'node-3') return { row: 4, col: 4 };\n      return undefined;\n    },\n  },\n  data: {\n    nodes: Array.from({ length: 25 }, (_, i) => ({\n      id: `node-${i}`,\n    })),\n    edges: Array.from({ length: 20 }, (_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 25)}`,\n      target: `node-${Math.floor(Math.random() * 25)}`,\n    })),\n  },\n  node: {\n    style: {\n      size: 20,\n      label: true,\n      labelText: (datum) => datum.id,\n      labelBackground: true,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#bfbfbf',\n    },\n  },\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [Grid布局](/examples/layout/grid/#basic)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/IndentedLayout.en.md) -->\n---\ntitle: Indented Tree\norder: 16\n---\n\n# Indented Tree Layout\n\n## Overview\n\nIndented tree layout represents the hierarchy of tree nodes through indentation in the horizontal direction. Each element occupies a row or column, commonly used in file directory structures, organizational charts, and other scenarios. This layout provides a clear structure for displaying hierarchical relationships.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented Tree Layout'/>\n\n## Use Cases\n\n- File directory structure visualization\n- Organizational charts\n- Classification system display\n- Tree-like data where hierarchical relationships need to be emphasized\n\n## Configuration Items\n\n> IndentedLayout supports common layout configuration items and specific configuration items, as shown below.\n\n| Property               | Description                                                         | Type                            | Default    | Required |\n| ---------------------- | ------------------------------------------------------------------- | ------------------------------- | ---------- | -------- |\n| type                   | Layout type, must be 'indented'                                     | 'indented'                      | -          | ✓        |\n| direction              | Layout direction, see details below                                 | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |          |\n| indent                 | Column spacing, fixed value or function                             | number \\| (d?: Node) => number  | 20         |          |\n| getWidth               | Get each node's width, effective when direction='H'                 | (d?: Node) => number            | -          |          |\n| getHeight              | Get each node's height                                              | (d?: Node) => number            | -          |          |\n| getSide                | Node placement on left/right side of root, overrides direction='H'  | (d?: Node) => 'left' \\| 'right' | -          |          |\n| dropCap                | Whether the first child of each node starts on the next line        | boolean                         | true       |          |\n| isLayoutInvisibleNodes | Whether invisible nodes participate in layout (when preLayout=true) | boolean                         | false      |          |\n| nodeFilter             | Nodes participating in this layout                                  | (node: NodeData) => boolean     | () => true |          |\n| preLayout              | Use pre-layout, calculate layout before initializing elements       | boolean                         | false      |          |\n| enableWorker           | Whether to run layout in WebWorker                                  | boolean                         | -          |          |\n| iterations             | Number of iterations for iterative layout                           | number                          | -          |          |\n\n### Complex Type Explanations\n\n- **direction**\n\n  - `'LR'`: Root node on the left, layout to the right\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`: Root node on the right, layout to the left\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`: Root node in the middle, horizontal symmetric layout\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - Fixed value: Consistent indentation for all levels\n  - Function: (d?: Node) => number, customize indentation based on node\n  - Example:\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - Used to customize each node's width/height, often for content adaptation\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - Specifies which side of the root node a node should be placed, only effective when direction='H'\n  - Example:\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## Example Code\n\n> For more examples, see [Online Demo](https://g6.antv.antgroup.com/en/examples/layout/indented)\n\n### Automatic Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### Right Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'LR'\n```\n\n### Left Side Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... code as above, layout.direction: 'RL'\n```\n\n### Custom Child Node Distribution\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### No Line Break for First Child Node\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/IndentedLayout.zh.md) -->\n---\ntitle: 缩进树 Indented\norder: 16\n---\n\n## 概述\n\nIndented（缩进树）布局是一种通过水平方向的缩进量来表示树节点层级的布局方式。每个元素占据一行或一列，常用于文件目录结构、组织架构等场景。该布局结构清晰，便于展示层级关系。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*NBUzRonaOYMAAAAAAAAAAABkARQnAQ' width=175 alt='Indented 缩进树布局示意图'/>\n\n## 使用场景\n\n- 文件目录结构可视化\n- 组织架构树\n- 分类体系展示\n- 需要突出层级关系的树状数据\n\n## 配置项\n\n> IndentedLayout 支持通用布局配置项和专有配置项，详见下表。\n\n| 属性                   | 描述                                                 | 类型                            | 默认值     | 必选 |\n| ---------------------- | ---------------------------------------------------- | ------------------------------- | ---------- | ---- |\n| type                   | 布局类型，需为 'indented'                            | 'indented'                      | -          | ✓    |\n| direction              | 布局方向，根节点在左/右/中间，详见下方说明           | 'LR' \\| 'RL' \\| 'H'             | 'LR'       |      |\n| indent                 | 列间间距，支持固定值或函数                           | number \\| (d?: Node) => number  | 20         |      |\n| getWidth               | 获取每个节点宽度，仅 direction='H' 时生效            | (d?: Node) => number            | -          |      |\n| getHeight              | 获取每个节点高度                                     | (d?: Node) => number            | -          |      |\n| getSide                | 节点排布在根节点的左/右侧，设置后 direction='H' 失效 | (d?: Node) => 'left' \\| 'right' | -          |      |\n| dropCap                | 每个节点的第一个子节点是否换行                       | boolean                         | true       |      |\n| isLayoutInvisibleNodes | 不可见节点是否参与布局（preLayout=true 时生效）      | boolean                         | false      |      |\n| nodeFilter             | 参与该布局的节点                                     | (node: NodeData) => boolean     | () => true |      |\n| preLayout              | 使用前布局，在初始化元素前计算布局                   | boolean                         | false      |      |\n| enableWorker           | 是否在 WebWorker 中运行布局                          | boolean                         | -          |      |\n| iterations             | 迭代布局的迭代次数                                   | number                          | -          |      |\n\n### 复杂类型说明\n\n- **direction**\n\n  - `'LR'`：根节点在左，向右布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*mq6YSIKrAt0AAAAAAAAAAABkARQnAQ' width=110 alt='LR'/>\n  - `'RL'`：根节点在右，向左布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*VGEnRbpvxlUAAAAAAAAAAABkARQnAQ' width=90 alt='RL'/>\n  - `'H'`：根节点在中间，水平对称布局\n    <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*Vek6RqtUXNcAAAAAAAAAAABkARQnAQ' width=160 alt='H'/>\n\n- **indent**\n\n  - 固定数值：所有层级缩进一致\n  - 函数：(d?: Node) => number，可根据节点自定义缩进\n  - 示例：\n    ```js\n    (d) => {\n      if (d.parent?.id === 'testId') return d.parent.x + 50;\n      return 100;\n    };\n    ```\n\n- **getWidth/getHeight**\n\n  - 用于自定义每个节点的宽度/高度，常用于自适应内容\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 50 : 100);\n    ```\n\n- **getSide**\n  - 指定节点在根节点的哪一侧，仅 direction='H' 时生效\n  - 示例：\n    ```js\n    (d) => (d.id === 'testId' ? 'left' : 'right');\n    ```\n\n## 示例代码\n\n> 更多示例可参考 [在线 Demo](https://g6.antv.antgroup.com/examples/layout/indented)\n\n### 子节点自动分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nimport { Graph, treeToGraphData } from '@antv/g6';\n\nfetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data: treeToGraphData(data),\n      autoFit: 'view',\n      layout: {\n        type: 'indented',\n        direction: 'H',\n        indent: 80,\n        getHeight: () => 16,\n        getWidth: () => 32,\n      },\n    });\n    graph.render();\n  });\n```\n\n### 子节点右侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3PioQ4TAMx8AAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'LR'\n```\n\n### 子节点左侧分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*o6uzQ5nmXJkAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\n// ... 代码同上，layout.direction: 'RL'\n```\n\n### 自定义子节点分布\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Kc63QoxgLNYAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'H',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  getSide: (d) => {\n    if (d.id === 'Regression' || d.id === 'Classification') return 'left';\n    return 'right';\n  },\n}\n```\n\n### 首子节点不换行\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*bC-pRrO7srwAAAAAAAAAAAAADmJ7AQ/original\" width=\"300\" />\n\n```js\nlayout: {\n  type: 'indented',\n  direction: 'LR',\n  indent: 80,\n  getHeight: () => 16,\n  getWidth: () => 32,\n  dropCap: false,\n}\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/MdsLayout.en.md) -->\n---\ntitle: MDS High-dimensional Data Dimensionality Reduction Layout\norder: 17\n---\n\n# MDS High-dimensional Data Dimensionality Reduction Layout\n\n## Overview\n\nMDS (Multidimensional Scaling) is a classic dimensionality reduction algorithm. In G6, the MDS layout constructs a distance matrix between nodes and restores their relative distances in high-dimensional space as much as possible in 2D space. It is suitable for graph visualization scenarios that show similarity, distance, or structural relationships between nodes.\n\n## Use Cases\n\n- Data dimensionality reduction visualization\n- Displaying distance relationships between nodes\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## Options\n\n| Option           | Description                           | Type              | Default       | Required |\n| :--------------- | :------------------------------------ | :---------------- | :------------ | :------- |\n| **type**         | Layout type                           | `mds`             | -             | Yes      |\n| **center**       | Center position of the layout         | `[number,number]` | canvas center | No       |\n| **linkDistance** | Ideal length of edges (spring length) | `number`          | 200           | No       |\n\n**center**\n\nThe center coordinates of the layout. All nodes will be symmetrically distributed around this point.\n\n**linkDistance**\n\n> number Default: 50\n\nThe ideal distance between nodes. The larger the value, the more dispersed the nodes.\n\n## Code Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/MdsLayout.zh.md) -->\n---\ntitle: 高维数据降维布局 MDS\norder: 17\n---\n\n## 概述\n\nMDS（多维尺度分析，Multidimensional Scaling）是一种经典的降维算法。在 G6 中，MDS 布局通过构造节点间的距离矩阵，在二维空间中尽可能还原它们在高维空间中的相对距离。适用于展示节点之间相似度、距离或结构关系的图可视化场景。\n\n## 使用场景\n\n- 数据降维可视化\n- 展示节点之间的距离关系\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mds',\n    center: [300, 300],\n    linkDistance: 100,\n  },\n});\n```\n\n## 配置项\n\n| 配置项           | 描述                               | 类型              | 默认值   | 必选 |\n| :--------------- | :--------------------------------- | :---------------- | :------- | :--- |\n| **type**         | 布局类型                           | `mds`             | -        | 是   |\n| **center**       | 布局的中心位置                     | `[number,number]` | 画布中心 | 否   |\n| **linkDistance** | 边的理想长度（弹簧未受力时的长度） | `number`          | 200      | 否   |\n\n**center**\n\n布局的中心点坐标，所有节点会围绕该点对称分布。\n\n**linkDistance**\n\n> number Default: 50\n\n节点之间的理想距离，越大则节点间距离越分散。\n\n## 代码示例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: Array.from({ length: 25 }, (_, i) => ({\n    id: `node-${i}`,\n    data: {\n      value: Math.random() * 100,\n    },\n  })),\n  edges: Array.from({ length: 20 }, (_, i) => ({\n    id: `edge-${i}`,\n    source: `node-${Math.floor(Math.random() * 25)}`,\n    target: `node-${Math.floor(Math.random() * 25)}`,\n  })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'mds',\n    nodeSize: 32,\n    linkDistance: 100,\n  },\n  behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/MindmapLayout.en.md) -->\n---\ntitle: Mindmap Tree\norder: 18\n---\n\n## Overview\n\nThe mindmap tree layout is suitable for hierarchical layouts of tree structures, supporting expansion on both left and right sides. Nodes at the same depth will be placed on the same layer. Note: the layout **does** take node size into account. See more mindmap layout [examples](/en/examples#layout-mindmap) or [source code](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js).\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## Options\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"Mindmap tree options diagram\" />\n\n| Property  | Description                                                                                             | Type                                | Default | Required |\n| --------- | ------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------- | -------- |\n| type      | Layout type                                                                                             | `mindmap`                           | -       | ✓        |\n| direction | Layout direction, [options](#direction)                                                                 | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`    |          |\n| getHeight | Function to calculate the height of each node                                                           | (d?: Node) => number                |         | ✓        |\n| getWidth  | Function to calculate the width of each node                                                            | (d?: Node) => number                |         | ✓        |\n| getVGap   | Vertical gap for each node. Note: the actual vertical gap between two nodes is twice the vgap           | (d?: Node) => number                |         |          |\n| getHGap   | Horizontal gap for each node. Note: the actual horizontal gap between two nodes is twice the hgap       | (d?: Node) => number                |         |          |\n| getSide   | Set whether the node is placed on the left or right of the root. Only effective when `direction` is `H` | (d?: Node) => string                |         |          |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\nTree layout direction\n\n- `'H'`: horizontal — The children of the root node are divided into two parts and placed on the left and right sides of the root node. You can pass the `getSide` method to specify the left/right distribution logic for each node. If not provided, the first half will be placed on the right, and the second half on the left by default.\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='Horizontal layout'/>\n\n- `'LR' | 'TB'`: Children are placed on the right side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `'RL'`: Children are placed on the left side of the root node.\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='Vertical layout'/>\n\n- `BT`: Children are placed on the right side of the root node, then the entire graph is rotated 180° along the X axis.\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='Vertical layout'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\nWidth of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\nHeight of each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\nHorizontal gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\nVertical gap for each node\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\nSet whether the node is placed on the left or right of the root. Note: only effective when `direction` is `H`. If not set, the first half of the children will be placed on the right, and the second half on the left by default. See [getSide auto calculation logic](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11).\n\nExample:\n\n```javascript\n(d) => {\n  // d is a node\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### Suitable Scenarios\n\n- Data lineage graph: `direction='H'` is suitable for rendering upstream and downstream lineage of a specified node, with upstream on the left and downstream on the right of the central node.\n- Mind map: Build custom mind map components.\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/MindmapLayout.zh.md) -->\n---\ntitle: 脑图树 Mindmap\norder: 18\n---\n\n## 概述\n\n脑图树布局适用于树状结构的层次化布局，支持左右两侧展开，深度相同的节点将会被放置在同一层。需要注意：布局**会**考虑节点的大小。参考更多脑图布局[样例](/examples#layout-mindmap)或[源码](https://github.com/antvis/hierarchy/blob/master/src/mindmap.js)。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=350 alt='img'/>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'mindmap',\n    direction: 'H',\n    preLayout: false,\n    getHeight: () => 32,\n    getWidth: () => 32,\n    getVGap: () => 16,\n    getHGap: () => 72,\n  },\n});\n```\n\n## 配置项\n\n<img src=\"https://img.alicdn.com/imgextra/i4/O1CN014J5e691gxm5GSrwD2_!!6000000004209-0-tps-1163-832.jpg\" width=\"400\" alt=\"脑图树配置项图解\" />\n\n| 属性      | 描述                                                                                                  | 类型                                | 默认值 | 必选 |\n| --------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- | ------ | ---- |\n| type      | 布局类型                                                                                              | `mindmap`                           | -      | ✓    |\n| direction | 布局方向，[可选值](#direction)                                                                        | `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` | `LR`   |      |\n| getHeight | 计算每个节点的高度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getWidth  | 计算每个节点的宽度                                                                                    | (d?: Node) => number                |        | ✓    |\n| getVGap   | 每个节点的垂直间隙，注意实际两个节点间的垂直间隙是2倍的vgap                                           | (d?: Node) => number                |        |      |\n| getHGap   | 每个节点的水平间隙，注意实际两个节点间的水平间隙是2倍的hgap                                           | (d?: Node) => number                |        |      |\n| getSide   | 设置节点排布在根节点的左侧/右侧，如未设置，则算法自动分配左侧/右侧。注意：该参数仅在`H`布局方向上生效 | (d?: Node) => string                |        |      |\n\n### direction\n\n> `H` \\| `LR` \\| `RL` \\| `TB` \\| `BT` **Default:** `'LR'`\n\n树布局的方向\n\n- `'H'`：horizontal（水平）—— 根节点的子节点分成两部分横向放置在根节点左右两侧。可传入`getSide`方法指定每个节点的左右分布逻辑，不传则默认将前半部分放置在右侧，后半部分放置在左侧。\n\n<img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*J1l5RofvbP0AAAAAAAAAAABkARQnAQ' width=170 alt='水平布局'/>\n\n- `'LR' | 'TB'`：将子节点排布在根节点的右侧；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01SWsfai28ZmZu2ehyh_!!6000000007947-0-tps-1390-1254.jpg' width=150 alt='竖直布局'/>\n\n- `'RL'`：将子节点排布在根节点的左侧；\n\n<img src='https://img.alicdn.com/imgextra/i1/O1CN01DFh7iu26fcORrjGfT_!!6000000007689-0-tps-1396-1254.jpg' width=150 alt='竖直布局'/>\n\n- `BT`：将子节点排布在根节点右侧，然后将整个图沿X轴旋转180°；\n\n<img src='https://img.alicdn.com/imgextra/i2/O1CN01zppRLx1Igmbtv4EyJ_!!6000000000923-0-tps-1388-1282.jpg' width=150 alt='竖直布局'/>\n\n### getWidth\n\n> _(d?: Node) => number_\n\n每个节点的宽度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHeight\n\n> _(d?: Node) => number_\n\n每个节点的高度\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getHGap\n\n> _(d?: Node) => number_\n\n每个节点的水平间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getVGap\n\n> _(d?: Node) => number_\n\n每个节点的垂直间隙\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'testId') return 50;\n  return 100;\n};\n```\n\n### getSide\n\n> _(d?: Node) => string_\n\n设置节点排布在根节点的左侧/右侧。注意：该参数仅在`direction`为`H`时生效。如未设置，会默认将子节点前半部分放置在右侧，后半部分放置在左侧，参考[getSide自动计算逻辑](https://github.com/antvis/hierarchy/blob/d786901874f59d96c47e2a5dfe17b373eefd72e3/src/layout/separate-root.js#L11)。\n\n示例：\n\n```javascript\n(d) => {\n  // d 是一个节点\n  if (d.id === 'test-child-id') return 'right';\n  return 'left';\n};\n```\n\n### 布局适用场景\n\n- 数据血缘图：`direction='H'`很适合渲染血缘图中查看指定节点的上下游血缘的场景，上游分布在中心节点的左侧，下游分布在右侧；\n- 思维导图：构建自定义的思维导图组件。\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/overview.en.md) -->\n---\ntitle: Layout Overview\norder: 0\n---\n\n## Overview\n\nGraph layout refers to the process of arranging elements in a graph according to certain rules, such as force-directed layout based on charge elasticity models, grid layout with sequential arrangement, and tree layout based on hierarchical structures.\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## Layout Types\n\nG6 provides a variety of layout algorithms, allowing users to choose the appropriate one based on their needs:\n\n- [AntVDagreLayout](/en/manual/layout/antv-dagre-layout): Custom layout based on dagre\n- [CircularLayout](/en/manual/layout/circular-layout): Circular layout\n- [ComboCombinedLayout](/en/manual/layout/combo-combined-layout): Layout suitable for combinations\n- [ConcentricLayout](/en/manual/layout/concentric-layout): Concentric layout\n- [D3Force3DLayout](/en/manual/layout/d3-force3-d-layout): [3D Force-directed](https://github.com/vasturiano/d3-force-3d) layout\n- [D3ForceLayout](/en/manual/layout/d3-force-layout): Force-directed layout based on [D3](https://d3js.org/d3-force)\n- [DagreLayout](/en/manual/layout/dagre-layout): [dagre](https://github.com/dagrejs/dagre) layout\n- [FishboneLayout](/en/manual/layout/fishbone): Fishbone layout\n- [ForceAtlas2Layout](/en/manual/layout/force-atlas2-layout): [ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) layout\n- [ForceLayout](/en/manual/layout/force-layout): Force-directed layout\n- [FruchtermanLayout](/en/manual/layout/fruchterman-layout): [Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) layout\n- [GridLayout](/en/manual/layout/grid-layout): Grid layout\n- [MDSLayout](/en/manual/layout/mds-layout): High-dimensional data dimensionality reduction layout\n- [RadialLayout](/en/manual/layout/radial-layout): Radial layout\n- [RandomLayout](/en/manual/layout/random-layout): Random layout\n- [SnakeLayout](/en/manual/layout/snake): Snake layout\n- [CompactBoxLayout](/en/manual/layout/compact-box-layout): Compact tree layout\n- [DendrogramLayout](/en/manual/layout/dendrogram-layout): Dendrogram layout\n- [MindmapLayout](/en/manual/layout/mindmap-layout): Mindmap layout\n- [IndentedLayout](/en/manual/layout/indented-layout): Indented tree layout\n\nAmong them, `CompactBox Layout`, `Dendrogram Layout`, `Mindmap Layout`, and `Indented Layout` are types of tree layouts suitable for tree-structured graphs.\n\n## Register Layout\n\nYou can directly use built-in layouts, but if you want to use other layouts, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## Configure Layout\n\nThe `layout` configuration item can specify the graph's layout algorithm, for example:\n\n```typescript\n{\n  layout: {\n    // Specify the layout algorithm to use\n    type: 'force',\n    // Configuration items for the layout algorithm\n    gravity: 10\n    // ...\n  }\n}\n```\n\nYou can also use `graph.setLayout` to update the layout configuration after the graph is instantiated.\n\nStarting from `5.1`, layout docs align their shared fields with `@antv/layout`. Besides each layout's own algorithm parameters, you should also pay attention to common options such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`.\n\n## Layout Acceleration\n\nG6 provides accelerated versions for some layout algorithms, including executing layout algorithms in Web Workers, providing [WASM](https://webassembly.org/) versions of layout algorithms, and GPU-accelerated layout algorithms. They can be used as follows:\n\n### Execute Layout Algorithms in Web Workers\n\nExcept for tree layouts, all built-in layout algorithms in G6 support execution in Web Workers. Simply set `enableWorker` to `true`:\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### Use WASM Version Layout Algorithms\n\nCurrently supported WASM version layout algorithms include: `Fruchterman Layout`, `ForceAtlas Layout`, `Force Layout`, `Dagre Layout`.\n\nFirst, install `@antv/layout-wasm`:\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\nInitialize threads:\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... other configurations\n  },\n});\n```\n\n### Use GPU-Accelerated Layout\n\nCurrently supported GPU-accelerated layout algorithms include: `Fruchterman Layout`, `GForce Layout`.\n\nFirst, install `@antv/layout-gpu`:\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\nImport and register the layout algorithm:\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\nInitialize the graph and pass in the layout configuration:\n\n```typescript\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... other configurations\n  },\n});\n```\n\n## Execute Layout\n\nUsually, after calling `graph.render()`, G6 will automatically execute the layout algorithm.\n\nIf you need to manually execute the layout algorithm, G6 provides the following APIs:\n\n- [layout](/api/layout#graphlayoutlayoutoptions): Execute layout algorithm\n- [setLayout](/api/layout#graphsetlayoutlayout): Set layout algorithm\n- [stopLayout](/api/layout#graphstoplayout): Stop layout algorithm\n\n## Custom Layout\n\nIf the built-in layout algorithms cannot meet your needs, you can customize layout algorithms. For details, please refer to [Custom Layout](/manual/layout/custom-layout).\n\nIf you are migrating layout configuration from G6 `5.0` to `5.1`, see [Upgrade from 5.0 to 5.1 (Layout)](/en/manual/whats-new/upgrade-to-5-1).\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/overview.zh.md) -->\n---\ntitle: 布局总览\norder: 0\n---\n\n## 概述\n\n图布局是指将图中的元素按照一定的规则进行排列的过程，例如基于电荷弹性模型的力导向布局、逐次排布的网格布局、基于层次结构的树布局等。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WIhlToluHaEAAAAAAAAAAAAADmJ7AQ/original\" />\n\n## 布局类型\n\nG6 提供了多种布局算法，用户可以根据自己的需求选择合适的布局算法：\n\n- [AntVDagreLayout](/manual/layout/antv-dagre-layout)：基于 dagre 定制的布局\n- [CircularLayout](/manual/layout/circular-layout)：环形布局\n- [ComboCombinedLayout](/manual/layout/combo-combined-layout)：适用于存在组合的布局\n- [ConcentricLayout](/manual/layout/concentric-layout)：同心圆布局\n- [D3Force3DLayout](/manual/layout/d3-force3-d-layout)：[3D 力导向](https://github.com/vasturiano/d3-force-3d)布局\n- [D3ForceLayout](/manual/layout/d3-force-layout)：基于 [D3](https://d3js.org/d3-force) 的力导向布局\n- [DagreLayout](/manual/layout/dagre-layout)：[dagre](https://github.com/dagrejs/dagre) 布局\n- [FishboneLayout](/manual/layout/fishbone)：鱼骨布局\n- [ForceAtlas2Layout](/manual/layout/force-atlas2-layout)：[ForceAtlas2](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) 布局\n- [ForceLayout](/manual/layout/force-layout)：力导向布局\n- [FruchtermanLayout](/manual/layout/fruchterman-layout)：[Fruchterman](https://www.sciencedirect.com/topics/computer-science/reingold-layout) 布局\n- [GridLayout](/manual/layout/grid-layout)：网格布局\n- [MDSLayout](/manual/layout/mds-layout)：高维数据降维算法布局\n- [RadialLayout](/manual/layout/radial-layout)：径向布局\n- [RandomLayout](/manual/layout/random-layout)：随机布局\n- [SnakeLayout](/manual/layout/snake)：蛇形布局\n- [CompactBoxLayout](/manual/layout/compact-box-layout): 紧凑树布局\n- [DendrogramLayout](/manual/layout/dendrogram-layout): 树状布局\n- [MindmapLayout](/manual/layout/mindmap-layout): 思维导图布局\n- [IndentedLayout](/manual/layout/indented-layout): 缩进树布局\n\n其中 `CompactBox Layout`、`Dendrogram Layout`、`Mindmap Layout`、`Indented Layout` 是树布局的一种，适用于树状结构的图。\n\n## 注册布局\n\n你可以直接使用内置布局，如果想要使用其他布局，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomLayout } from 'package-name/or/path-to-your-custom-layout';\n\nregister(ExtensionCategory.LAYOUT, 'custom-layout', CustomLayout);\n```\n\n## 配置布局\n\n通过 `layout` 配置项可以指定图的布局算法，例如：\n\n```typescript\n{\n  layout: {\n    // 指定要使用的布局算法\n    type: 'force',\n    // 布局算法的配置项\n    gravity: 10\n    // ...\n  }\n}\n```\n\n也可在图实例化之后使用 `graph.setLayout` 来更新布局配置。\n\n5.1 开始，布局文档中的通用字段已与 `@antvis/layout` 对齐。除了各布局自己的算法参数外，也建议同时关注 `width`、`height`、`center`、`enableWorker`、`node`、`edge` 等公共配置。\n\n## 布局加速\n\nG6 对一些布局算法提供了加速版本，包括：在 Web Worker 中执行布局算法、提供 [WASM](https://webassembly.org/) 版本的布局算法、GPU 加速的布局算法等。可按照下列方式使用：\n\n### 在 Web Worker 中执行布局算法\n\n除树布局外，G6 的所有内置布局算法都支持在 Web Worker 中执行。只需将 `enableWorker` 设置为 `true` 即可：\n\n```typescript\n{\n  layout: {\n    type: 'force',\n    enableWorker: true,\n    // ...\n  }\n}\n```\n\n### 使用 WASM 版本布局算法\n\n目前支持 WASM 版本的布局算法有：`Fruchterman Layout` `ForceAtlas Layout` `Force Layout` `Dagre Layout`。\n\n首先安装 `@antv/layout-wasm`：\n\n```bash\nnpm install @antv/layout-wasm --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-wasm', FruchtermanLayout);\n```\n\n初始化线程：\n\n```typescript\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-wasm',\n    threads,\n    // ... 其他配置\n  },\n});\n```\n\n### 使用 GPU 加速布局\n\n目前支持 GPU 加速的布局算法有：`Fruchterman Layout` `GForce Layout`。\n\n首先安装 `@antv/layout-gpu`：\n\n```bash\nnpm install @antv/layout-gpu --save\n```\n\n引入并注册布局算法：\n\n```typescript\nimport { register, Graph, ExtensionCategory } from '@antv/g6';\nimport { FruchtermanLayout } from '@antv/layout-gpu';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n```\n\n初始化图并传入布局配置：\n\n```typescript\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他配置\n  },\n});\n```\n\n## 执行布局\n\n通常，在调用 `graph.render()` 后，G6 会自动执行布局算法。\n\n如果需要手动执行布局算法，G6 提供了以下 API：\n\n- [layout](/api/layout#graphlayoutlayoutoptions)：执行布局算法\n- [setLayout](/api/layout#graphsetlayoutlayout)：设置布局算法\n- [stopLayout](/api/layout#graphstoplayout)：停止布局算法\n\n## 自定义布局\n\n如果内置布局算法无法满足需求，可以自定义布局算法，具体请参考[自定义布局](/manual/layout/custom-layout)。\n\n如果你正在从 G6 `5.0` 的布局配置迁移到 `5.1`，可继续阅读 [从 5.0 升级到 5.1（布局）](/manual/whats-new/upgrade-to-5-1)。\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/RadialLayout.en.md) -->\n---\ntitle: Radial Layout\norder: 19\n---\n\n## Overview\n\nRadial layout is a graph layout algorithm that arranges nodes in concentric circles by layers. It is commonly used to display hierarchical relationships, community structures, and more. This layout supports advanced features such as node overlap prevention and group sorting, making it suitable for visualizing various network structures.\n\n## Use Cases\n\n- Displaying hierarchical structures (e.g., organizational charts, family trees)\n- Community structure analysis\n- Scenarios that need to highlight the central node and its radiating relationships\n- Complex networks requiring node grouping and sorting\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## Configuration\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // other configurations...\n});\n```\n\n## Options\n\n| Property                   | Description                                                     | Type                                             | Default  | Required |\n| -------------------------- | --------------------------------------------------------------- | ------------------------------------------------ | -------- | -------- |\n| type                       | Layout type                                                     | string                                           | `radial` | ✓        |\n| center                     | Center coordinates                                              | [number, number]                                 | -        |          |\n| focusNode                  | Radiating center node                                           | string \\| Node \\| null                           | null     |          |\n| height                     | Canvas height                                                   | number                                           | -        |          |\n| width                      | Canvas width                                                    | number                                           | -        |          |\n| nodeSize                   | Node size (diameter)                                            | number \\| number[] \\| ((nodeData: Node) => Size) | -        |          |\n| nodeSpacing                | Minimum node spacing (effective when preventing overlap)        | number \\| (nodeData: Node) => number             | 10       |          |\n| linkDistance               | Edge length                                                     | number                                           | 50       |          |\n| unitRadius                 | Radius per circle; when null, automatically computed from space | number \\| null                                   | 100      |          |\n| maxIteration               | Maximum number of iterations                                    | number                                           | 1000     |          |\n| maxPreventOverlapIteration | Max iterations for overlap prevention                           | number                                           | 200      |          |\n| preventOverlap             | Whether to prevent node overlap                                 | boolean                                          | false    |          |\n| sortBy                     | Field or sorting function for nodes in the same layer           | string \\| ((nodeData: Node) => number \\| string) | -        |          |\n| sortStrength               | Sorting strength for nodes in the same layer                    | number                                           | 10       |          |\n| strictRadial               | Strictly place nodes in the same layer on the same ring         | boolean                                          | true     |          |\n\n## Code Example\n\n### Basic Usage\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\nResult:\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"Basic Radial Layout\" style=\"max-width: 600px;\" />\n\n## Real Cases\n\n- [Basic Radial Layout](/en/examples/layout/radial/#basic)\n- [Strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#strict-prevent-overlap)\n- [Non-strict Overlap Prevention Radial Layout](/en/examples/layout/radial/#non-strict-prevent-overlap)\n- [Cluster Sorting](/en/examples/layout/radial/#cluster-sort)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/RadialLayout.zh.md) -->\n---\ntitle: 径向布局 Radial\norder: 19\n---\n\n## 概述\n\n径向（Radial）布局是一种将节点以同心圆方式分层排列的图布局算法，常用于展示层级关系、社群结构等。该布局支持节点防重叠、分组排序等高级特性，适用于多种网络结构的可视化。\n\n## 使用场景\n\n- 展示层级结构（如组织架构、家谱等）\n- 社群结构分析\n- 需要突出中心节点及其辐射关系的场景\n- 需要节点分组、排序的复杂网络\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/radial.md\"></embed>\n\n## 配置方式\n\n```js\nconst graph = new Graph({\n  layout: {\n    type: 'radial',\n    nodeSize: 32,\n    unitRadius: 100,\n    linkDistance: 200,\n  },\n  // 其他配置...\n});\n```\n\n## 配置项\n\n| 属性                       | 描述                                         | 类型                                             | 默认值   | 必选 |\n| -------------------------- | -------------------------------------------- | ------------------------------------------------ | -------- | ---- |\n| type                       | 布局类型                                     | string                                           | `radial` | ✓    |\n| center                     | 圆心坐标                                     | [number, number]                                 | -        |      |\n| focusNode                  | 辐射中心节点                                 | string \\| Node \\| null                           | null     |      |\n| height                     | 画布高度                                     | number                                           | -        |      |\n| width                      | 画布宽度                                     | number                                           | -        |      |\n| nodeSize                   | 节点大小（直径）                             | number \\| number[] \\| ((nodeData: Node) => Size) | -        |      |\n| nodeSpacing                | 节点最小间距（防重叠时生效）                 | number \\| (nodeData: Node) => number             | 10       |      |\n| linkDistance               | 边长度                                       | number                                           | 50       |      |\n| unitRadius                 | 每圈半径；为 null 时按布局空间自动计算       | number \\| null                                   | 100      |      |\n| maxIteration               | 最大迭代次数                                 | number                                           | 1000     |      |\n| maxPreventOverlapIteration | 防重叠最大迭代次数                           | number                                           | 200      |      |\n| preventOverlap             | 是否防止节点重叠                             | boolean                                          | false    |      |\n| sortBy                     | 同层节点排序字段或排序函数                   | string \\| ((nodeData: Node) => number \\| string) | -        |      |\n| sortStrength               | 同层节点排序强度                             | number                                           | 10       |      |\n| strictRadial               | 是否严格每层节点在同一圆环上（防重叠时生效） | boolean                                          | true     |      |\n\n## 代码示例\n\n### 基本用法\n\n```js\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/radial.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      data,\n      autoFit: 'center',\n      layout: {\n        type: 'radial',\n        nodeSize: 32,\n        unitRadius: 100,\n        linkDistance: 200,\n      },\n      node: {\n        style: {\n          labelFill: '#fff',\n          labelPlacement: 'center',\n          labelText: (d) => d.id,\n        },\n      },\n      behaviors: ['drag-canvas', 'drag-element'],\n    });\n    graph.render();\n  });\n```\n\n效果如下：\n\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*d3P-RK4YCDYAAAAAAAAAAAAADmJ7AQ/original\" alt=\"基本 Radial 辐射布局\" style=\"max-width: 600px;\" />\n\n## 实际案例\n\n- [基本 Radial 辐射布局](/examples/layout/radial/#basic)\n- [防止节点重叠的严格辐射布局](/examples/layout/radial/#strict-prevent-overlap)\n- [防止节点重叠的非严格辐射布局](/examples/layout/radial/#non-strict-prevent-overlap)\n- [排序聚类](/examples/layout/radial/#cluster-sort)\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/RandomLayout.en.md) -->\n---\ntitle: Random Layout\norder: 20\n---\n\n## Overview\n\n**Random Layout** is a layout method based on simple rules. Its core logic is to generate random coordinates for each node within a specified layout area (defined by the layout center, width, and height). The coordinates are completely random, and there is no node collision prevention.\n\n## Use Cases\n\nThe use cases for random layout are very limited. It is only recommended for the following scenarios:\n\n- **Initial Data Display**:\n\n  During early development, when debugging data loading logic or quickly verifying data structure, random layout can be used for preliminary validation.\n\nFor final business delivery, it is recommended to use layouts that better reflect business value, such as [AntVDagreLayout](/en/manual/layout/antv-dagre-layout), [ForceLayout](/en/manual/layout/force-layout), or [custom layouts](/en/manual/layout/custom-layout).\n\n## Basic Usage\n\nAll other configurations use defaults (the layout width and height default to the entire canvas container).\n\n```js\nconst graph = new Graph({\n  // other configurations\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## Options\n\n| Property | Description   | Type                                         | Default                                   | Required |\n| -------- | ------------- | -------------------------------------------- | ----------------------------------------- | -------- |\n| type     | Layout type   | random                                       | -                                         | ✓        |\n| center   | Layout center | [number, number] \\| [number, number, number] | [`layout width` / 2, `layout height` / 2] |          |\n| height   | Layout height | number                                       | canvas height                             |          |\n| width    | Layout width  | number                                       | canvas width                              |          |\n\n## Example\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/RandomLayout.zh.md) -->\n---\ntitle: 随机布局 Random\norder: 20\n---\n\n## 概述\n\n**随机布局（Random Layout）** 是一种基于简单规则的布局方式，其核心逻辑是为每个节点在指定布局区域（由布局中心点、宽度和高度定义）内生成随机坐标（完全随机，无节点防碰撞）。\n\n## 使用场景\n\n随机布局的使用场景非常局限，只推荐以下场景使用：\n\n- **数据初步展示**:\n\n  在开发初期调试数据加载逻辑或需要快速验证数据结构的情况下，可使用随机布局先行验证\n\n业务最终交付推荐使用更能体现业务价值的布局方式，比如 [AntVDagreLayout](/manual/layout/antv-dagre-layout) 、[ForceLayout](/manual/layout/force-layout) 或者[自定义布局](/manual/layout/custom-layout)等。\n\n## 基本用法\n\n其余均使用默认配置（布局宽高默认是整个画布容器）\n\n```js\nconst graph = new Graph({\n  // 其他配置\n  layout: {\n    type: 'random',\n  },\n});\n```\n\n## 配置项\n\n| 属性   | 描述       | 类型                                         | 默认值                           | 必选 |\n| ------ | ---------- | -------------------------------------------- | -------------------------------- | ---- |\n| type   | 布局类型   | random                                       | -                                | ✓    |\n| center | 布局的中心 | [number, number] \\| [number, number, number] | [`布局宽度` / 2, `布局高度` / 2] |      |\n| height | 布局的高度 | number                                       | 画布高度                         |      |\n| width  | 布局的宽度 | number                                       | 画布宽度                         |      |\n\n## 示例\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  autoFit: 'view',\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `${i}`,\n    })),\n  },\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  layout: {\n    type: 'random',\n  },\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/Snake.en.md) -->\n---\ntitle: Snake Layout\norder: 21\n---\n\n## Overview\n\nSnake Layout is a special type of graph layout that can more efficiently display long chain structures in a limited space. Note that the graph data must ensure that nodes are linearly arranged from the source node to the sink node, forming a clear path.\n\nNodes are arranged in an S-shape: the first node is at the start of the first row, subsequent nodes are arranged to the right in the first row until the end. At the end of the row, the next row's nodes are arranged from right to left. This process repeats until all nodes are placed.\n\n## Use Cases\n\nSuitable for scenarios that require compact presentation of linear relationships:\n\n- **Long process visualization**\n\n  Perfect for scenarios with many process steps, such as approval flows, production line procedures, logistics routes, etc.\n\n- **Hierarchical structures in limited space**\n\n  When the hierarchy is too long but the canvas is limited, rows can be folded to save space. For example, API call dependencies (client → gateway → serviceA → serviceB → database, snake layout compresses 5 layers into 2 rows), or file directory trees (deeply nested folder structures, e.g., src/components/utils/helpers/..., using snake layout to fold subdirectories horizontally).\n\n## Online Demo\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## Options\n\n> If the layout has specific properties, they are listed below. For common layout options, see [Base Layout Options](/en/manual/layout/base-layout)\n\n| Property                | Description                                                 | Type                                               | Default                                                    | Required |\n| ----------------------- | ----------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------- | -------- |\n| type                    | Layout type                                                 | snake                                              | -                                                          | ✓        |\n| [clockwise](#clockwise) | Whether nodes are arranged clockwise                        | boolean                                            | true                                                       |          |\n| colGap                  | Gap size between columns                                    | number                                             | Automatically calculated by canvas width and total columns |          |\n| cols                    | Number of columns                                           | number                                             | 5                                                          |          |\n| nodeSize                | Node size                                                   | Size \\| ((node: NodeData) => Size)                 | -                                                          |          |\n| padding                 | Padding, i.e., distance from layout area to canvas boundary | number \\| number[]                                 | 0                                                          |          |\n| rowGap                  | Gap size between rows                                       | number                                             | Automatically calculated by canvas height and total rows   |          |\n| sortBy                  | Node sorting method                                         | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | Default is the path order in the graph                     |          |\n\n### clockwise\n\n- When arranged clockwise, nodes start from the top left, the first row is arranged left to right, the second row right to left, and so on, forming an S-shaped path.\n- When arranged counterclockwise, nodes start from the top right, the first row is arranged right to left, the second row left to right, and so on, forming a reversed S-shaped path.\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Layout Skill (packages/site/docs/manual/layout/Snake.zh.md) -->\n---\ntitle: 蛇形布局 Snake\norder: 21\n---\n\n## 概览\n\n蛇形布局（Snake Layout）是一种特殊的图形布局方式，能够在较小的空间内更有效地展示长链结构。需要注意的是，其图数据需要确保节点按照从源节点到汇节点的顺序进行线性排列，形成一条明确的路径。\n\n节点按 S 字型排列，第一个节点位于第一行的起始位置，接下来的节点在第一行向右排列，直到行末尾。到达行末尾后，下一行的节点从右向左反向排列。这个过程重复进行，直到所有节点排列完毕。\n\n## 使用场景\n\n适合需要紧凑呈现线性关系的场景：\n\n- **长流程可视化**\n\n  完美适配流程步骤过多的场景，如审批流程、生产线工序、物流运输路径等。\n\n- **有限空间内的层级结构**\n\n  层级结构过长但画布受限，需通过折叠行节省空间，比如 API 调用依赖（客户端 → 网关 → 服务A → 服务B → 数据库，蛇形布局将 5 层压缩为 2 行）、文件目录树（深度嵌套的文件夹结构，如 src/components/utils/helpers/... ，用蛇形布局横向折叠子目录）。\n\n## 在线体验\n\n<embed src=\"@/common/api/layouts/snake.md\"></embed>\n\n## 配置项\n\n> 如果布局有其特定的属性，我们将在下面列出。对于所有布局的通用属性，见[布局通用配置项](/manual/layout/base-layout)\n\n| 属性                    | 描述                               | 类型                                               | 默认值                                 | 必选 |\n| ----------------------- | ---------------------------------- | -------------------------------------------------- | -------------------------------------- | ---- |\n| type                    | 布局类型                           | snake                                              | -                                      | ✓    |\n| [clockwise](#clockwise) | 节点排布方向是否顺时针             | boolean                                            | true                                   |      |\n| colGap                  | 节点列之间的间隙大小               | number                                             | 默认将根据画布宽度和节点总列数自动计算 |      |\n| cols                    | 节点列数                           | number                                             | 5                                      |      |\n| nodeSize                | 节点尺寸                           | Size \\| ((node: NodeData) => Size)                 | -                                      |      |\n| padding                 | 内边距，即布局区域与画布边界的距离 | number \\| number[]                                 | 0                                      |      |\n| rowGap                  | 节点行之间的间隙大小               | number                                             | 默认将根据画布高度和节点总行数自动计算 |      |\n| sortBy                  | 节点排序方法                       | (nodeA: NodeData, nodeB: NodeData) => -1 \\| 0 \\| 1 | 默认按照在图中的路径顺序进行展示       |      |\n\n### clockwise\n\n- 在顺时针排布时，节点从左上角开始，第一行从左到右排列，第二行从右到左排列，依次类推，形成 S 型路径。\n\n- 在逆时针排布时，节点从右上角开始，第一行从右到左排列，第二行从左到右排列，依次类推，形成反向 S 型路径。\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: new Array(16).fill(0).map((_, i) => ({ id: `${i}` })),\n  edges: new Array(15).fill(0).map((_, i) => ({ source: `${i}`, target: `${i + 1}` })),\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: {\n      labelFill: '#fff',\n      labelPlacement: 'center',\n      labelText: (d) => d.id,\n    },\n  },\n  layout: {\n    type: 'snake',\n    padding: 50,\n  },\n  behaviors: ['drag-canvas', 'drag-element'],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Background.en.md) -->\n---\ntitle: Background\norder: 1\n---\n\n## Overview\n\nSupport setting a background image for the canvas to make the canvas more hierarchical and narrative.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Setting a unified brand background color or image for charts\n- Distinguishing different functional areas through the background\n- Enhancing the visual hierarchy and aesthetics of charts\n\n## Basic Usage\n\nBelow is a simple example of initializing the Background plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // Specify an identifier for the plugin for dynamic updates\n      backgroundColor: '#f0f2f5', // Set background color\n      backgroundImage: 'url(https://example.com/bg.png)', // Set background image\n    },\n  ],\n});\n```\n\n## Configuration Options\n\nThe configuration options for the Background plugin inherit all CSS style properties ([CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)), so you can use any valid CSS property to configure the background. Here are some common configurations:\n\n| Property           | Description                   | Type   | Default Value     | Required |\n| ------------------ | ----------------------------- | ------ | ----------------- | -------- |\n| type               | Plugin type                   | string | `background`      | ✓        |\n| key                | Unique identifier for updates | string | -                 |          |\n| width              | Background width              | string | `100%`            |          |\n| height             | Background height             | string | `100%`            |          |\n| backgroundColor    | Background color              | string | -                 |          |\n| backgroundImage    | Background image              | string | -                 |          |\n| backgroundSize     | Background size               | string | `cover`           |          |\n| backgroundPosition | Background position           | string | -                 |          |\n| backgroundRepeat   | Background repeat             | string | -                 |          |\n| opacity            | Background opacity            | string | -                 |          |\n| transition         | Transition animation          | string | `background 0.5s` |          |\n| zIndex             | Stacking order                | string | -1                |          |\n\n> Note: The `zIndex` is set to -1 by default to prevent the background from covering other plugin DOM elements, such as grid lines.\n\n## Code Examples\n\n### Basic Background Color\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Using a Background Image\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Gradient Background\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamically Updating the Background\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// Subsequent updates\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## FAQs\n\n### 1. Background conflicts with other plugins?\n\nBy default, the `zIndex` of the background plugin is set to `-1` to ensure it is below other elements. If there are still conflicts, you can adjust the `zIndex` value:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // Lower z-index to avoid conflicts\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Background.zh.md) -->\n---\ntitle: 背景 Background\norder: 1\n---\n\n## 概述\n\n支持为图画布设置一个背景图片，让画布更有层次感、叙事性。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 为图表设置统一的品牌背景色或图片\n- 通过背景区分不同的功能区域\n- 增强图表的视觉层次感和美观度\n\n## 基本用法\n\n以下是一个简单的 Background 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background', // 为插件指定标识符，方便动态更新\n      backgroundColor: '#f0f2f5', // 设置背景色\n      backgroundImage: 'url(https://example.com/bg.png)', // 设置背景图\n    },\n  ],\n});\n```\n\n## 配置项\n\nBackground 插件的配置项继承了所有 CSS 样式属性（[CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration)），因此你可以使用任何合法的 CSS 属性来配置背景。以下是一些常用配置：\n\n| 属性               | 描述                         | 类型   | 默认值            | 必选 |\n| ------------------ | ---------------------------- | ------ | ----------------- | ---- |\n| type               | 插件类型                     | string | `background`      | ✓    |\n| key                | 插件唯一标识符，用于后续更新 | string | -                 |      |\n| width              | 背景宽度                     | string | `100%`            |      |\n| height             | 背景高度                     | string | `100%`            |      |\n| backgroundColor    | 背景颜色                     | string | -                 |      |\n| backgroundImage    | 背景图片                     | string | -                 |      |\n| backgroundSize     | 背景尺寸                     | string | `cover`           |      |\n| backgroundPosition | 背景位置                     | string | -                 |      |\n| backgroundRepeat   | 背景重复方式                 | string | -                 |      |\n| opacity            | 背景透明度                   | string | -                 |      |\n| transition         | 过渡动画                     | string | `background 0.5s` |      |\n| zIndex             | 层叠顺序                     | string | -1                |      |\n\n> 注意：`zIndex` 默认为 -1，这是为了避免背景覆盖其他插件的 DOM 元素，如网格线。\n\n## 代码示例\n\n### 基础背景色\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 使用背景图片\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      backgroundImage:\n        'url(https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*0Qq0ToQm1rEAAAAAAAAAAAAADmJ7AQ/original)',\n      backgroundRepeat: 'no-repeat',\n      backgroundSize: 'cover',\n      opacity: 0.2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 渐变背景\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 200,\n  plugins: [\n    {\n      type: 'background',\n      width: '300px',\n      height: '200px',\n      background: 'linear-gradient(45deg, #1890ff, #722ed1)',\n      opacity: '0.8',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新背景\n\n```js\n// 初始化时配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'background',\n      key: 'my-background',\n      backgroundColor: '#f0f2f5',\n    },\n  ],\n});\n\n// 后续更新\ngraph.updatePlugin({\n  key: 'my-background',\n  backgroundColor: '#e6f7ff',\n  transition: 'background 1s ease',\n});\n```\n\n## 常见问题\n\n### 1. 背景与其他插件冲突？\n\n默认情况下，背景插件的 `zIndex` 设为 `-1`，以确保它位于其他元素之下。如果仍有冲突，可以调整 `zIndex` 值：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'background',\n      zIndex: '-2', // 降低 z-index 避免冲突\n    },\n  ],\n});\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/BubbleSets.en.md) -->\n---\ntitle: BubbleSets\norder: 2\n---\n\n## Overview\n\nThe BubbleSets plugin represents sets and their relationships by creating bubble shapes, helping users intuitively understand logical relationships such as intersections and unions between sets. It is a tool to enhance data visualization effects, especially suitable for displaying complex data set relationships.\n\n## Use Cases\n\nThe BubbleSets plugin is mainly suitable for the following scenarios:\n\n- Displaying relationships between sets (e.g., intersections, unions)\n- Enhancing the expressive ability of data visualization\n- Identifying specific sets of nodes or edges in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the BubbleSets plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // List of node IDs to be enclosed\n      label: true, // Whether to display labels\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## Configuration Options\n\n| Property                 | Description                                                                              | Type                                                           | Default Value | Required |\n| ------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| type                     | Plugin type                                                                              | string                                                         | `bubble-sets` | ✓        |\n| key                      | Unique identifier for the plugin for subsequent updates                                  | string                                                         | -             |          |\n| members                  | Member elements, including nodes and edges, [example](#members)                          | string[]                                                       | -             | ✓        |\n| avoidMembers             | Elements to avoid, not included when drawing contours (currently supports setting nodes) | string[]                                                       | -             |          |\n| label                    | Whether to display labels                                                                | boolean                                                        | true          |          |\n| labelPlacement           | Label position                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |          |\n| labelBackground          | Whether to display background                                                            | boolean                                                        | false         |          |\n| labelPadding             | Label padding                                                                            | number \\| number[]                                             | 0             |          |\n| labelCloseToPath         | Whether the label is close to the contour, [example](#labelclosetopath)                  | boolean                                                        | true          |          |\n| labelAutoRotate          | Whether the label rotates with the contour, [example](#labelautorotate)                  | boolean                                                        | true          |          |\n| labelOffsetX             | Label x-axis offset                                                                      | number                                                         | 0             |          |\n| labelOffsetY             | Label y-axis offset                                                                      | number                                                         | 0             |          |\n| labelMaxWidth            | Maximum width of the text, automatically ellipsized if exceeded                          | number                                                         | -             |          |\n| maxRoutingIterations     | Maximum number of iterations for calculating paths between members                       | number                                                         | 100           |          |\n| maxMarchingIterations    | Maximum number of iterations for calculating contours                                    | number                                                         | 20            |          |\n| pixelGroup               | Number of pixels per potential area group, used to improve speed                         | number                                                         | 4             |          |\n| edgeR0                   | Edge radius parameter R0                                                                 | number                                                         | -             |          |\n| edgeR1                   | Edge radius parameter R1                                                                 | number                                                         | -             |          |\n| nodeR0                   | Node radius parameter R0                                                                 | number                                                         | -             |          |\n| nodeR1                   | Node radius parameter R1                                                                 | number                                                         | -             |          |\n| morphBuffer              | Morph buffer size                                                                        | number                                                         |               |          |\n| threshold                | Threshold                                                                                | number                                                         | -             |          |\n| memberInfluenceFactor    | Member influence factor                                                                  | number                                                         | -             |          |\n| edgeInfluenceFactor      | Edge influence factor                                                                    | number                                                         | -             |          |\n| nonMemberInfluenceFactor | Non-member influence factor                                                              | number                                                         | -             |          |\n| virtualEdges             | Whether to use virtual edges                                                             | boolean                                                        | -             |          |\n\n### members\n\nMember elements, including nodes and edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\nExample: Do not let the label stick to the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\nExample: Do not let the label rotate with the contour\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Usage Examples\n\n### Basic BubbleSets\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom BubbleSets Style\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // Bubble fill color\n      fillOpacity: 0.1, // Fill opacity\n      stroke: '#7e3feb', // Border color\n      strokeOpacity: 1, // Border opacity\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visualization effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // Display label\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/BubbleSets.zh.md) -->\n---\ntitle: 气泡集 BubbleSets\norder: 2\n---\n\n## 概述\n\nBubbleSets 插件通过创建气泡形状来表示集合及其关系，帮助用户直观地理解集合间的交集、并集等逻辑关系。它是一种增强数据可视化效果的工具，特别适用于展示复杂的数据集合关系。\n\n## 使用场景\n\nBubbleSets 插件主要适用于以下场景：\n\n- 展示集合间的关系（如交集、并集）\n- 增强数据可视化的表达能力\n- 在复杂网络图中标识特定节点或边的集合\n\n## 基本用法\n\n以下是一个简单的 BubbleSets 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node1', 'node2'], // 需要包裹的节点 ID 列表\n      label: true, // 是否显示标签\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/bubble-sets.md\"></embed>\n\n## 配置项\n\n| 属性                     | 描述                                                             | 类型                                                           | 默认值        | 必选 |\n| ------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | ---- |\n| type                     | 插件类型                                                         | string                                                         | `bubble-sets` | ✓    |\n| key                      | 插件唯一标识符，用于后续更新                                     | string                                                         | -             |      |\n| members                  | 成员元素，包括节点和边，[示例](#members)                         | string[]                                                       | -             | ✓    |\n| avoidMembers             | 需要避开的元素，在绘制轮廓时不会包含这些元素（目前支持设置节点） | string[]                                                       | -             |      |\n| label                    | 是否显示标签                                                     | boolean                                                        | true          |      |\n| labelPlacement           | 标签位置                                                         | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` \\| `bottom` | `bottom`      |      |\n| labelBackground          | 是否显示背景                                                     | boolean                                                        | false         |      |\n| labelPadding             | 标签内边距                                                       | number \\| number[]                                             | 0             |      |\n| labelCloseToPath         | 标签是否贴合轮廓，[示例](#labelclosetopath)                      | boolean                                                        | true          |      |\n| labelAutoRotate          | 标签是否跟随轮廓旋转，[示例](#labelautorotate)                   | boolean                                                        | true          |      |\n| labelOffsetX             | 标签 x 轴偏移量                                                  | number                                                         | 0             |      |\n| labelOffsetY             | 标签 y 轴偏移量                                                  | number                                                         | 0             |      |\n| labelMaxWidth            | 文本的最大宽度，超出会自动省略                                   | number                                                         | -             |      |\n| maxRoutingIterations     | 计算成员之间路径的最大迭代次数                                   | number                                                         | 100           |      |\n| maxMarchingIterations    | 计算轮廓的最大迭代次数                                           | number                                                         | 20            |      |\n| pixelGroup               | 每个潜在区域组的像素数，用于提高速度                             | number                                                         | 4             |      |\n| edgeR0                   | 边的半径参数 R0                                                  | number                                                         | -             |      |\n| edgeR1                   | 边的半径参数 R1                                                  | number                                                         | -             |      |\n| nodeR0                   | 节点的半径参数 R0                                                | number                                                         | -             |      |\n| nodeR1                   | 节点的半径参数 R1                                                | number                                                         | -             |      |\n| morphBuffer              | 形态缓冲区大小                                                   | number                                                         |               |      |\n| threshold                | 阈值                                                             | number                                                         | -             |      |\n| memberInfluenceFactor    | 成员影响因子                                                     | number                                                         | -             |      |\n| edgeInfluenceFactor      | 边影响因子                                                       | number                                                         | -             |      |\n| nonMemberInfluenceFactor | 非成员影响因子                                                   | number                                                         | -             |      |\n| virtualEdges             | 是否使用虚拟边                                                   | boolean                                                        | -             |      |\n\n### members\n\n成员元素，包括节点和边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### labelCloseToPath\n\n示例：不让 label 贴合轮廓\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelCloseToPath: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### labelAutoRotate\n\n示例：不让label标签跟随轮廓旋转\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelAutoRotate: false,\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 使用示例\n\n### 基础 BubbleSets\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'bubble-sets',\n      key: 'bubble-sets-a',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义 BubbleSets 样式\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      fill: '#7e3feb', // 气泡填充颜色\n      fillOpacity: 0.1, // 填充透明度\n      stroke: '#7e3feb', // 边框颜色\n      strokeOpacity: 1, // 边框透明度\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge-0',\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-1',\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        id: 'edge-2',\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        id: 'edge-3',\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        id: 'edge-4',\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        id: 'edge-5',\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      key: 'bubble-sets-a',\n      type: 'bubble-sets',\n      members: ['node-0', 'node-1', 'node-2', 'node-3'],\n      label: true, // 显示标签\n      labelText: 'cluster-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'bubble-sets-a',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'bubble-sets-b',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'bubble-sets-c',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'bubble-sets-d',\n          type: 'bubble-sets',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Contextmenu.en.md) -->\n---\ntitle: Contextmenu\norder: 3\n---\n\n## Overview\n\nThe context menu, also known as the right-click menu, is a menu that appears when a user clicks on a specific area. It supports triggering custom events before and after clicking. Through the context menu, specific element operations can be integrated, making it convenient to control a particular item when needed.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Various interactions with elements: viewing nodes, viewing edges, deleting nodes, etc.\n\n## Basic Usage\n\nBelow is a simple example of initializing the Contextmenu plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // Enable right-click menu only on nodes, by default all elements are enabled\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: 'View Details', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('Display node details');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property       | Description                                                                                                               | Type                                                                              | Default Value    | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | -------- |\n| className      | Additional class name for the menu DOM                                                                                    | string                                                                            | `g6-contextmenu` |          |\n| trigger        | How to trigger the right-click menu: `contextmenu` for right-click, `click` for click                                     | `click` \\| `contextmenu`                                                          | `contextmenu`    |          |\n| offset         | Offset of the menu display in X and Y directions                                                                          | [number, number]                                                                  | [4, 4]           |          |\n| onClick        | Callback method triggered after the menu is clicked, [example](#onclick)                                                  | (value: string, target: HTMLElement, current: Element) => void                    | -                |          |\n| getItems       | Returns the list of menu items, supports `Promise` type return value. It is a shortcut configuration for `getContent`     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |          |\n| getContent     | Returns the content of the menu, supports `Promise` type return value, can also use `getItems` for shortcut configuration | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |          |\n| loadingContent | Menu content used when `getContent` returns a `Promise`                                                                   | HTMLElement \\| string                                                             | -                |          |\n| enable         | Whether it is available, determines whether the right-click menu is supported by parameters, by default all are available | boolean \\| (event: IElementEvent) => boolean                                      | true             |          |\n\n### Item\n\nEach menu item (Item) contains the following properties:\n\n| Property | Description                          | Type     | Required |\n| -------- | ------------------------------------ | -------- | -------- |\n| name     | Name displayed for the menu item     | `string` | ✓        |\n| value    | Value corresponding to the menu item | `string` | ✓        |\n\n### onClick\n\nThis function is triggered after clicking a menu item, and the function has three parameters:\n\n- value: Corresponds to the value of the menu item\n- target: The DOM node of the menu item container\n- current: The element that triggered the menu item, for example, if it is a node, you can use `current` to get the node information (id), or to modify the element\n\n## Code Examples\n\n### Basic Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + value + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: 'View Details', value: 'detail' },\n          { name: 'Delete', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### Edge Right-click Menu\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: 'Change Start Point', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('Execute change start point operation here');\n      },\n      // Enable right-click menu only on edges\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### Asynchronous Loading of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // Enable right-click menu only on nodes\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### Dynamic Control of Menu Items\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: 'Delete Node',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: 'Move Edge',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Contextmenu.zh.md) -->\n---\ntitle: 上下文菜单 Contextmenu\norder: 3\n---\n\n## 概述\n\n上下文菜单（Contextmenu），也被称为右键菜单，是当用户在某个特定区域上点击后出现的一个菜单。支持在点击前后，触发自定义事件。通过上下文菜单，可以将一些具体元素的操作集成在其中，方便对某一项来进行需要时的单独控制。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 元素的各种交互：查看节点、查看边、删除节点等等交互操作\n\n## 基本用法\n\n以下是一个简单的 Contextmenu 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'contextmenu',\n      // 只在节点上开启右键菜单，默认全部元素都开启\n      enable: (e) => e.targetType === 'node',\n      getItems: () => {\n        return [{ name: '查看详情', value: 'detail' }];\n      },\n      onClick: (value) => {\n        if (value === 'detail') console.log('展示节点详情');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性           | 描述                                                                            | 类型                                                                              | 默认值           | 必选 |\n| -------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ---------------- | ---- |\n| className      | 给菜单的 DOM 追加的类名                                                         | string                                                                            | `g6-contextmenu` |      |\n| trigger        | 如何触发右键菜单：`contextmenu` 表示右键触发，`click` 表示点击触发              | `click` \\| `contextmenu`                                                          | `contextmenu`    |      |\n| offset         | 菜单显式 X、Y 方向的偏移量                                                      | [number, number]                                                                  | [4, 4]           |      |\n| onClick        | 当菜单被点击后，触发的回调方法，[示例](#onclick)                                | (value: string, target: HTMLElement, current: Element) => void                    | -                |      |\n| getItems       | 返回菜单的项目列表，支持 `Promise` 类型的返回值。是 `getContent` 的快捷配置     | (event: IElementEvent) => [Item](#item)[] \\| Promise<[Item](#item)[]>             | -                |      |\n| getContent     | 返回菜单的内容，支持 `Promise` 类型的返回值，也可以使用 `getItems` 进行快捷配置 | (event: IElementEvent) => HTMLElement \\| string \\| Promise<HTMLElement \\| string> | -                |      |\n| loadingContent | 当 `getContent` 返回一个 `Promise` 时，使用的菜单内容                           | HTMLElement \\| string                                                             | -                |      |\n| enable         | 是否可用，通过参数判断是否支持右键菜单，默认是全部可用                          | boolean \\| (event: IElementEvent) => boolean                                      | true             |      |\n\n### Item\n\n每个菜单项目 (Item) 包含以下属性：\n\n| 属性  | 描述             | 类型     | 必选 |\n| ----- | ---------------- | -------- | ---- |\n| name  | 菜单项显示的名字 | `string` | ✓    |\n| value | 菜单项对应的值   | `string` | ✓    |\n\n### onClick\n\n点击菜单项后会触发该函数，函数有三个参数：\n\n- value: 对应菜单项的 value\n- target: 对应菜单项容器的 dom 节点\n- current: 对应触发菜单项的元素，例如是节点则可以通过 `current` 来获取到节点的信息(id)等，或者来对元素进行修改\n\n## 代码示例\n\n### 基础右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (value, target, current) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '查看详情', value: 'detail' },\n          { name: '删除', value: 'delete' },\n        ];\n      },\n    },\n  ],\n});\n```\n\n### 边的右键菜单\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: () => {\n        return [{ name: '变更起点', value: 'change' }];\n      },\n      onClick: (value) => {\n        if (value === 'change') console.log('这里执行变更起点操作');\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'edge',\n    },\n  ],\n});\n```\n\n### 异步加载菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/contextmenu-config');\n        const items = await response.json();\n        return items;\n      },\n      // 仅在边上开启右键菜单\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n```\n\n### 动态控制菜单项\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  layout: { type: 'grid' },\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu',\n      getItems: (e) => {\n        if (e.target.id === 'node-1') {\n          return [\n            {\n              name: '删除节点',\n              value: 'delete',\n            },\n          ];\n        }\n        if (e.target.type === 'edge') {\n          return [\n            {\n              name: '移动边',\n              value: 'move',\n            },\n          ];\n        }\n        return [];\n      },\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'contextmenu',\n      trigger: 'contextmenu', // 'click' or 'contextmenu'\n      onClick: (v) => {\n        alert('You have clicked the「' + v + '」item');\n      },\n      getItems: () => {\n        return [\n          { name: '展开一度关系', value: 'spread' },\n          { name: '查看详情', value: 'detail' },\n        ];\n      },\n      enable: (e) => e.targetType === 'node',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/custom-plugin.en.md) -->\n---\ntitle: Custom Plugin\norder: 20\n---\n\n## Overview\n\nCustom plugins can implement additional features, such as adding extra components, rendering logic, etc. Custom plugins can effectively achieve functional decoupling, better manage and orchestrate code, and facilitate subsequent maintenance.\n\n## Use Cases\n\n### Add extra components, rendering logic, etc.\n\n- **Extra components**: Such as built-in plugins like `Tooltip`, `Minimap`, `Snapline`, `Grid`, `Context Menu`, `Watermark`, etc.\n- **Rendering logic**: Such as built-in plugins like `Edge Bundling`, and `Remote Data Loading` ([Example](#remote-data-loading)), etc.\n\n### When built-in plugins cannot meet the requirements\n\nWhen built-in plugins cannot fully meet business needs, users can also make adjustments and modifications through custom plugins (inheriting built-in plugins).\n\n_(If the features supported by built-in plugins are more general, or if there are bugs in built-in plugins, you are welcome to submit issues or PRs on [Github](https://github.com/antvis/G6))_\n\n## Custom Plugin Examples\n\nLike interactions, the implementation of plugins is also quite flexible, and you can implement your plugin in your preferred style.\n\nHere are a few simple custom plugin implementations:\n\n### Remote Data Loading\n\nAutomatically load remote data during graph instantiation:\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- In this example, we simulate a data loading plugin. After using this plugin, there is no need to pass data when instantiating the Graph, as the plugin will automatically load remote data.\n\n- `BasePlugin` is the base class for all plugins, and each custom plugin needs to inherit this base class.\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### Automatically Enable or Disable Animation Based on Node Count\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // Disable global animation when the number of nodes reaches this value\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- In this example, we listen to the `GraphEvent.BEFORE_RENDER` event and determine whether the current number of nodes exceeds a specified value. If so, global animation is disabled; otherwise, it is enabled.\n- `maxLength` is a defined configuration item that can be passed in when initializing the graph instance. [Plugin Configuration](#configure-plugin)\n\n## Register Plugin\n\nRegister using the method provided by G6\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## Configure Plugin\n\n- You can pass the plugin type name or configuration parameter object in `plugins`, see [Configure Plugin](/manual/plugin/overview#configuration-method)\n\n- For example, the previous [Automatically Enable or Disable Animation Based on Node Count](#automatically-enable-or-disable-animation-based-on-node-count) is configured as follows:\n\n  ```typescript\n  const graph = new Graph({\n    // Other configurations\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/custom-plugin.zh.md) -->\n---\ntitle: 自定义插件\norder: 20\n---\n\n## 概述\n\n自定义插件可以实现一些额外的功能，例如添加额外的组件、渲染逻辑等。通过自定义插件可以很好地实现功能解耦，更好地进行管理、编排代码以及后续维护。\n\n## 使用场景\n\n### 添加额外的组件、渲染逻辑等\n\n- **额外的组件**：如内置插件的`提示框`、`小地图`、`对齐线`、`网格线`、`上下文菜单`、`水印`等\n- **渲染逻辑**：如内置插件的`边绑定`，以及`远程数据加载`（[示例](#远程数据加载)）等\n\n### 内置插件无法满足需求\n\n当内置插件无法完全满足业务需求时，用户也可以通过自定义插件（继承内置插件）进行调整和修改。\n\n_（如果需要内置插件支持的特性是较通用的，或者内置插件存在 Bug ，这种时候欢迎大家到 [Github](https://github.com/antvis/G6) 提 Issue 或者 PR ）_\n\n## 自定义插件示例\n\n与交互类似，插件的实现也相当灵活，你可以以你喜欢的风格实现你的插件。\n\n下面列举几个简单的自定义插件实现：\n\n### 远程数据加载\n\n在图实例化过程中自动加载远程数据：\n\n```typescript\nimport { BasePlugin } from '@antv/g6';\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\n\ninterface RemoteDataSourceOptions extends BasePluginOptions {}\n\nclass RemoteDataSource extends BasePlugin<RemoteDataSourceOptions> {\n  constructor(context: RuntimeContext, options: RemoteDataSourceOptions) {\n    super(context, options);\n    this.loadData();\n  }\n\n  private async loadData() {\n    // mock remote data\n    const data = {\n      nodes: [\n        { id: 'node-1', x: 100, y: 100 },\n        { id: 'node-2', x: 200, y: 200 },\n      ],\n      edges: [{ source: 'node-1', target: 'node-2' }],\n    };\n\n    const { graph } = this.context;\n    graph.setData(data);\n    await graph.render();\n  }\n}\n```\n\n- 在这个例子中，我们模拟实现了一个数据加载插件，在使用该插件后，实例化 Graph 时不用再传入数据，该插件会自动加载远程数据。\n\n- `BasePlugin` 是所有插件的基类，每个自定义插件都需要继承这个基类实现。\n\n<embed src=\"@/common/manual/custom-extension/plugin/implement-plugin.md\"></embed>\n\n### 自动判断节点数量开启或关闭动画\n\n```typescript\nimport type { BasePluginOptions, RuntimeContext } from '@antv/g6';\nimport { BasePlugin, GraphEvent } from '@antv/g6';\n\ninterface AutoSwitchAnimationOptions extends BasePluginOptions {\n  maxLength: number; // 节点数量达到这个值后关闭全局动画\n}\n\nclass AutoSwitchAnimation extends BasePlugin<AutoSwitchAnimationOptions> {\n  static defaultOptions: Partial<AutoSwitchAnimationOptions> = {\n    maxLength: 1000,\n  };\n  constructor(context: RuntimeContext, options: AutoSwitchAnimationOptions) {\n    super(context, options);\n    this.bindEvents();\n  }\n  private bindEvents() {\n    const { graph } = this.context;\n    graph.on(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  private switchAnimation() {\n    const { graph } = this.context;\n    graph.setOptions({\n      animation: graph.getNodeData().length < this.options.maxLength,\n    });\n  }\n  private unbindEvents() {\n    const { graph } = this.context;\n    graph.off(GraphEvent.BEFORE_RENDER, this.switchAnimation);\n  }\n  destroy() {\n    this.unbindEvents();\n    super.destroy();\n  }\n}\n```\n\n- 在这个例子中，我们监听 `GraphEvent.BEFORE_RENDER` 事件，在响应中判断当前节点数量是否大于指定值，是的话则关闭全局动画，否则开启\n- `maxLength` 是定义的配置项，可在初始化画布实例时传入具体配置，[插件配置](#配置插件)\n\n## 注册插件\n\n通过 G6 提供的 register 方法注册即可\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n```\n\n## 配置插件\n\n- 可在 `plugins` 中传入插件类型名称或配置参数对象，详见[配置插件](/manual/plugin/overview#配置方式)\n\n- 比如前面的[自动判断节点数量开启或关闭动画](#自动判断节点数量开启或关闭动画)，配置如下：\n\n  ```typescript\n  const graph = new Graph({\n    // 其他配置\n    plugins: [\n      {\n        type: 'auto-switch-animation',\n        maxLength: 500,\n      },\n    ],\n  });\n  ```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/EdgeBundling.en.md) -->\n---\ntitle: EdgeBundling\norder: 4\n---\n\n## Overview\n\nEdge bundling is a graph visualization technique used to reduce visual clutter in complex network graphs and to reveal high-level patterns and structures in the graph. Its purpose is to bundle adjacent edges together.\n\nThe edge bundling plugin provided in G6 is based on the implementation of the [FEDB (Force-Directed Edge Bundling for Graph Visualization)](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf) paper: modeling edges as flexible springs that can attract each other and bundling them through a self-organizing process.\n\n## Use Cases\n\nThe edge bundling plugin is mainly suitable for the following scenarios:\n\n- Reducing visual clutter in complex network graphs\n- Revealing high-level patterns and structures in the graph\n- Improving the readability and aesthetics of large-scale graph data\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeBundling plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property        | Description                                                                                                                                                                                            | Type   | Default Value   | Required |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | --------------- | -------- |\n| type            | Plugin type, used to identify the plugin as an edge bundling plugin                                                                                                                                    | string | `edge-bundling` | ✓        |\n| key             | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                      | string | -               |          |\n| bundleThreshold | Edge compatibility threshold, determines which edges should be bundled together, the larger the value, the fewer edges are bundled, [example](#bundlethreshold)                                        | number | 0.6             |          |\n| cycles          | Number of simulation cycles, controls the number of execution rounds of the edge bundling simulation                                                                                                   | number | 6               |          |\n| divisions       | Initial number of cut points, in subsequent cycles, the number of cut points will gradually increase according to divRate, affecting the degree of edge subdivision                                    | number | 1               |          |\n| divRate         | Growth rate of cut points, determines the growth rate of cut points in each cycle                                                                                                                      | number | 2               |          |\n| iterations      | Specifies the number of iterations executed in the first cycle, in subsequent cycles, the number of iterations will gradually decrease according to iterRate, affecting the accuracy of the simulation | number | 90              |          |\n| iterRate        | Iteration decrement rate, controls the reduction ratio of iterations in each cycle                                                                                                                     | number | 2/3             |          |\n| K               | Edge strength, affects the attraction and repulsion between edges, [example](#k)                                                                                                                       | number | 0.1             |          |\n| lambda          | Initial step size, in subsequent cycles, the step size will double increment, affecting the magnitude of node movement during edge bundling                                                            | number | 0.1             |          |\n\n### bundleThreshold\n\nEdge compatibility threshold, determines which edges should be bundled together. The larger the value, the fewer edges are bundled, and vice versa.\n\n- A lower bundleThreshold value (e.g., 0.4) will cause more edges to be bundled together, forming a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // Lower edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge compatibility threshold\">\n\n- A higher bundleThreshold value (e.g., 0.8) will cause fewer edges to be bundled together, maintaining more independent edges.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge compatibility threshold\">\n\n### K\n\nEdge strength, affects the attraction and repulsion between edges. A higher K value will make the attraction between edges stronger, resulting in a tighter bundling effect.\n\n- A lower K value (e.g., 0.05) will make the attraction between edges weaker, resulting in a weaker bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // Lower edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Lower edge strength\">\n\n- A higher K value (e.g., 0.2) will make the attraction between edges stronger, resulting in a more pronounced bundling effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // Higher edge strength\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"Higher edge strength\">\n\n## Code Examples\n\n### Basic Edge Bundling\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['edge-bundling'],\n});\n```\n\n### Custom Styles\n\nYou can customize the parameters of edge bundling as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // Higher edge compatibility threshold\n      cycles: 8, // More simulation cycles\n      K: 0.2, // Stronger edge strength\n    },\n  ],\n});\n```\n\n### Dynamic Update of Edge Bundling\n\nUse the key identifier to dynamically update edge bundling properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// Subsequent dynamic update\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // Update edge compatibility threshold\n  cycles: 10, // Update number of simulation cycles\n});\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/EdgeBundling.zh.md) -->\n---\ntitle: 边绑定 EdgeBundling\norder: 4\n---\n\n## 概述\n\n边绑定（Edge Bundling）是一种图可视化技术，用于减少复杂网络图中的视觉混乱，并展示图中的高级别模式和结构。其目的是将相邻的边捆绑在一起。\n\nG6 中提供的边绑定插件是基于 [FEDB（Force-Directed Edge Bundling for Graph Visualization）](https://classes.engineering.wustl.edu/cse557/readings/holten-edgebundling.pdf)论文的实现：将边建模为可以相互吸引的柔性弹簧，通过自组织的方式进行捆绑。\n\n## 使用场景\n\n边绑定插件主要适用于以下场景：\n\n- 减少复杂网络图中的视觉混乱\n- 揭示图中的高级别模式和结构\n- 提高大规模图数据的可读性和美观性\n\n## 基本用法\n\n以下是一个简单的 EdgeBundling 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.6,\n      cycles: 6,\n      divisions: 3,\n      divRate: 2,\n      iterations: 90,\n      iterRate: 2 / 3,\n      K: 0.1,\n      lambda: 0.1,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性            | 描述                                                                                               | 类型   | 默认值          | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------- | ------ | --------------- | ---- |\n| type            | 插件类型，用于标识该插件为边捆绑插件                                                               | string | `edge-bundling` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                   | string | -               |      |\n| bundleThreshold | 边兼容性阈值，该值决定了哪些边应该被绑定在一起，值越大，绑定的边越少，[示例](#bundlethreshold)     | number | 0.6             |      |\n| cycles          | 模拟周期数，控制边捆绑模拟的执行轮数                                                               | number | 6               |      |\n| divisions       | 初始切割点数，在后续的周期中，切割点数将根据 divRate 逐步递增，影响边的细分程度                    | number | 1               |      |\n| divRate         | 切割点数增长率，决定了每一轮周期中切割点数的增长幅度                                               | number | 2               |      |\n| iterations      | 指定在第一个周期中执行的迭代次数，在后续的周期中，迭代次数将根据 iterRate 逐步递减，影响模拟的精度 | number | 90              |      |\n| iterRate        | 迭代次数递减率，控制每一轮周期中迭代次数的减少比例                                                 | number | 2\\/3            |      |\n| K               | 边的强度，影响边之间的吸引力和排斥力，[示例](#k)                                                   | number | 0.1             |      |\n| lambda          | 初始步长，在后续的周期中，步长将双倍递增，影响边捆绑过程中节点移动的幅度                           | number | 0.1             |      |\n\n### bundleThreshold\n\n边兼容性阈值，该值决定了哪些边应该被绑定在一起。值越大，绑定的边越少，反之则绑定的边越多。\n\n- 较低的 bundleThreshold 值（如 0.4）会使更多的边被绑定在一起，形成更明显的捆绑效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.4, // 较低的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_0iOSZnijrMAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边兼容性阈值\">\n\n- 较高的 bundleThreshold 值（如 0.8）会使较少的边被绑定在一起，保持更多的独立边。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 较高的边兼容性阈值\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*WNHMT4L4AfkAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边兼容性阈值\">\n\n### K\n\n边的强度，影响边之间的吸引力和排斥力。较高的 K 值会使边之间的吸引力更强，从而形成更紧密的捆绑效果。\n\n- 较低的 K 值（如 0.05）会使边之间的吸引力较弱，边的捆绑效果较弱。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.05, // 较低的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*wlHVSb2515gAAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较低的边强度\">\n\n- 较高的 K 值（如 0.2）会使边之间的吸引力较强，边的捆绑效果更明显。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-bundling',\n      K: 0.2, // 较高的边强度\n    },\n  ],\n});\n```\n\n效果如下：\n<img src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4DAMQLvtrk4AAAAAAAAAAAAAemJ7AQ/original\" width=\"240\" alt=\"较高的边强度\">\n\n## 代码示例\n\n### 基础边绑定\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['edge-bundling'],\n});\n```\n\n### 自定义样式\n\n您可以根据需要自定义边绑定的参数：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      bundleThreshold: 0.8, // 更高的边兼容性阈值\n      cycles: 8, // 更多模拟周期\n      K: 0.2, // 更强的边强度\n    },\n  ],\n});\n```\n\n### 动态更新边绑定\n\n使用 key 标识符可以在运行时动态更新边绑定属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'edge-bundling',\n      key: 'my-edge-bundling',\n      bundleThreshold: 0.6,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-edge-bundling',\n  bundleThreshold: 0.8, // 更新边兼容性阈值\n  cycles: 10, // 更新模拟周期数\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/circular.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      layout: {\n        type: 'circular',\n      },\n      node: { style: { size: 20 } },\n      behaviors: ['drag-canvas', 'drag-element'],\n      plugins: [\n        {\n          key: 'edge-bundling',\n          type: 'edge-bundling',\n          bundleThreshold: 0.1,\n        },\n      ],\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/EdgeFilterLens.en.md) -->\n---\ntitle: EdgeFilterLens\norder: 5\n---\n\n## Overview\n\nThe Edge Filter Lens plugin allows you to keep the edges of interest within the lens range, while other edges will not be displayed in that range. This is an important visualization exploration tool that can help users focus on edge relationships in specific areas.\n\n## Use Cases\n\n- Need to focus on viewing edge relationships in local areas\n- Highlight connections between specific nodes in complex networks\n\n## Basic Usage\n\nBelow is a simple example of initializing the EdgeFilterLens plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // Follow mouse movement\n      r: 60, // Set lens radius\n      nodeType: 'both', // Edge display condition\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                                                                                                                                                                                 | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                                                                                                                                                                                 | string                                                                                                                                                                  | `edge-filter-lens`                          | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                                                                                                                                                                                           | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the lens:<br/>- `pointermove`: The lens always follows the mouse movement <br/>- `click`: Move the lens to the click position when clicking on the canvas <br/>- `drag`: Move the lens by dragging                                                                                                                                                                           | `pointermove` \\| `click` \\| `drag`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the lens                                                                                                                                                                                                                                                                                                                                                                          | number                                                                                                                                                                  | 60                                          |          |\n| maxR           | Maximum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum radius of the lens                                                                                                                                                                                                                                                                                                                                                                  | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to scale the lens radius: `wheel`: Scale the lens radius by the wheel                                                                                                                                                                                                                                                                                                                | `wheel`                                                                                                                                                                 | -                                           |          |\n| nodeType       | Edge display condition:<br/> - `both`: The edge is displayed only when both the source and target nodes are in the lens <br/> - `source`: The edge is displayed only when the source node is in the lens<br/> - `target`: The edge is displayed only when the target node is in the lens <br/> - `either`: The edge is displayed as long as either the source or target node is in the lens | `both` \\| `source` \\| `target` \\| `either`                                                                                                                              | `both`                                      |          |\n| filter         | Filter out elements that are never displayed in the lens                                                                                                                                                                                                                                                                                                                                    | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                       | () => true                                  |          |\n| style          | Style of the lens, [configuration options](#style)                                                                                                                                                                                                                                                                                                                                          | object                                                                                                                                                                  |                                             |          |\n| nodeStyle      | Style of nodes in the lens                                                                                                                                                                                                                                                                                                                                                                  | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: false }`                          |          |\n| edgeStyle      | Style of edges in the lens                                                                                                                                                                                                                                                                                                                                                                  | [EdgeStyle](/en/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/en/manual/data#边数据edgedata)) => [EdgeStyle](/en/manual/element/edge/base-edge#style))   | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                                                                                                                                                                                           | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nStyle properties of the circular lens.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#fff`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | 1             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.8           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the lens:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // Upper evacuation area\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // Middle area\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // Lower area\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // Upper connections\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // Middle connections\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // Lower connections\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // Cross-region connections\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // Fill color of the lens area\n        fillOpacity: 0.6, // Opacity of the fill area\n        stroke: '#7e3feb', // Change lens border to purple\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n      },\n      nodeStyle: {\n        size: 24, // Enlarge nodes\n        fill: '#7e3feb', // Purple fill\n        stroke: '#5719c9', // Dark purple stroke\n        lineWidth: 1, // Thin border\n        label: true, // Show label\n        labelFill: '#ffffff', // White text\n        labelFontSize: 14, // Enlarge text\n        labelFontWeight: 'bold', // Bold text\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // Gray edge\n        lineWidth: 2, // Thicken edge line\n        label: true, // Show label\n        labelFill: '#5719c9', // Dark purple text\n        opacity: 0.8, // Appropriate opacity\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Edge Filter Lens](/en/examples/plugin/edge-filter-lens/#basic)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/EdgeFilterLens.zh.md) -->\n---\ntitle: 边过滤镜 EdgeFilterLens\norder: 5\n---\n\n## 概述\n\n边过滤镜插件可以将关注的边保留在过滤镜范围内，其他边将在该范围内不显示。这是一个重要的可视化探索工具，可以帮助用户聚焦于特定区域的边关系。\n\n## 使用场景\n\n- 需要聚焦查看局部区域的边关系\n- 在复杂网络中突出显示特定节点之间的连接\n\n## 基本用法\n\n以下是一个简单的 EdgeFilterLens 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      trigger: 'pointermove', // 跟随鼠标移动\n      r: 60, // 设置透镜半径\n      nodeType: 'both', // 边的显示条件\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/edge-filter-lens.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                                                                                       | 类型                                                                                                                                                           | 默认值               | 必选 |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                                                                                   | string                                                                                                                                                         | `edge-filter-lens`   | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                                                                                           | string                                                                                                                                                         | -                    |      |\n| trigger        | 移动透镜的方式：<br/>- `pointermove`：透镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动透镜到点击位置 <br/>- `drag`：通过拖拽方式移动透镜                                                                                                                | `pointermove` \\| `click` \\| `drag`                                                                                                                             | `pointermove`        |      |\n| r              | 透镜的半径                                                                                                                                                                                                                                                 | number                                                                                                                                                         | 60                   |      |\n| maxR           | 透镜的最大半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 画布宽高最小值的一半 |      |\n| minR           | 透镜的最小半径                                                                                                                                                                                                                                             | number                                                                                                                                                         | 0                    |      |\n| scaleRBy       | 缩放透镜半径的方式：`wheel`：通过滚轮缩放透镜的半径                                                                                                                                                                                                        | `wheel`                                                                                                                                                        | -                    |      |\n| nodeType       | 边显示的条件：<br/> - `both`：只有起始节点和目标节点都在透镜中时，边才会显示 <br/> - `source`：只有起始节点在透镜中时，边才会显示<br/> - `target`：只有目标节点在透镜中时，边才会显示 <br/> - `either`：只要起始节点或目标节点有一个在透镜中时，边就会显示 | `both` \\| `source` \\| `target` \\| `either`                                                                                                                     | `both`               |      |\n| filter         | 过滤出始终不在透镜中显示的元素                                                                                                                                                                                                                             | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                              | () => true           |      |\n| style          | 透镜的样式，[配置项](#style)                                                                                                                                                                                                                               | object                                                                                                                                                         |                      |      |\n| nodeStyle      | 在透镜中节点的样式                                                                                                                                                                                                                                         | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: false }`   |      |\n| edgeStyle      | 在透镜中边的样式                                                                                                                                                                                                                                           | [EdgeStyle](/manual/element/edge/base-edge#style) \\| ((datum: [EdgeData](/manual/data#边数据edgedata)) => [EdgeStyle](/manual/element/edge/base-edge#style))   | `{ label: true }`    |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                                                                                           | boolean                                                                                                                                                        | true                 |      |\n\n### style\n\n圆形透镜的样式属性。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#fff` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | 1      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.8    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['edge-filter-lens'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  plugins: ['edge-filter-lens'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义透镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      // 上部疏散区域\n      { id: 'node1', style: { x: 150, y: 60, label: 'Node 1' } },\n      { id: 'node2', style: { x: 100, y: 40, label: 'Node 2' } },\n      { id: 'node3', style: { x: 200, y: 35, label: 'Node 3' } },\n      { id: 'node4', style: { x: 150, y: 30, label: 'Node 4' } },\n\n      // 中部区域\n      { id: 'node5', style: { x: 220, y: 140, label: 'Node 5' } },\n      { id: 'node6', style: { x: 280, y: 160, label: 'Node 6' } },\n      { id: 'node7', style: { x: 220, y: 120, label: 'Node 7' } },\n      { id: 'node8', style: { x: 260, y: 100, label: 'Node 8' } },\n      { id: 'node9', style: { x: 240, y: 130, label: 'Node 9' } },\n      { id: 'node10', style: { x: 300, y: 110, label: 'Node 10' } },\n\n      // 下部区域\n      { id: 'node11', style: { x: 240, y: 200, label: 'Node 11' } },\n      { id: 'node12', style: { x: 280, y: 220, label: 'Node 12' } },\n      { id: 'node13', style: { x: 300, y: 190, label: 'Node 13' } },\n      { id: 'node14', style: { x: 320, y: 210, label: 'Node 14' } },\n    ],\n    edges: [\n      // 上部连接\n      { id: 'edge1', source: 'node1', target: 'node2' },\n      { id: 'edge2', source: 'node2', target: 'node3' },\n      { id: 'edge3', source: 'node3', target: 'node4' },\n\n      // 中部连接\n      { id: 'edge4', source: 'node5', target: 'node6' },\n      { id: 'edge5', source: 'node6', target: 'node7' },\n      { id: 'edge6', source: 'node7', target: 'node8' },\n      { id: 'edge7', source: 'node8', target: 'node9' },\n      { id: 'edge8', source: 'node9', target: 'node10' },\n\n      // 下部连接\n      { id: 'edge9', source: 'node11', target: 'node12' },\n      { id: 'edge10', source: 'node12', target: 'node13' },\n      { id: 'edge11', source: 'node13', target: 'node14' },\n\n      // 跨区域连接\n      { id: 'edge12', source: 'node4', target: 'node8' },\n      { id: 'edge13', source: 'node7', target: 'node11' },\n      { id: 'edge14', source: 'node10', target: 'node13' },\n    ],\n  },\n  node: {\n    style: {\n      size: 20,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'edge-filter-lens',\n      r: 80,\n      style: {\n        fill: '#f0f5ff', // 透镜区域的填充颜色\n        fillOpacity: 0.6, // 填充区域的透明度\n        stroke: '#7e3feb', // 透镜边框改为紫色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n      },\n      nodeStyle: {\n        size: 24, // 放大节点\n        fill: '#7e3feb', // 紫色填充\n        stroke: '#5719c9', // 深紫色描边\n        lineWidth: 1, // 细边框\n        label: true, // 显示标签\n        labelFill: '#ffffff', // 白色文字\n        labelFontSize: 14, // 放大文字\n        labelFontWeight: 'bold', // 文字加粗\n      },\n      edgeStyle: {\n        stroke: '#8b9baf', // 灰色边\n        lineWidth: 2, // 加粗边线\n        label: true, // 显示标签\n        labelFill: '#5719c9', // 深紫色文字\n        opacity: 0.8, // 适当的透明度\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [边过滤镜](/examples/plugin/edge-filter-lens/#basic)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Fisheye.en.md) -->\n---\ntitle: Fisheye\norder: 6\n---\n\n## Overview\n\nThe Fisheye plugin is designed for focus+context exploration scenarios. It can magnify the area of interest while ensuring that the context and the relationship between the context and the focus center are not lost. It is an important visualization exploration tool.\n\n## Use Cases\n\n- Highlight certain areas during presentations\n- Magnify details locally without losing the overall view\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fisheye plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // Move fisheye by dragging\n      d: 1.5, // Set distortion factor\n      r: 120, // Set fisheye radius\n      showDPercent: true, // Show distortion degree\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                                                                   | Type                                                                                                                                                                    | Default Value                               | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------- |\n| type           | Plugin type                                                                                                                                                                                                                   | string                                                                                                                                                                  | `fisheye`                                   | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                                                             | string                                                                                                                                                                  | -                                           |          |\n| trigger        | Method to move the fisheye:<br/>- `pointermove`: The fisheye always follows the mouse movement <br/>- `click`: Move the fisheye to the click position when clicking on the canvas <br/>- `drag`: Move the fisheye by dragging | `pointermove` \\| `drag` \\| `click`                                                                                                                                      | `pointermove`                               |          |\n| r              | Radius of the fisheye                                                                                                                                                                                                         | number                                                                                                                                                                  | 120                                         |          |\n| maxR           | Maximum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | Half of the smaller dimension of the canvas |          |\n| minR           | Minimum adjustable radius of the fisheye                                                                                                                                                                                      | number                                                                                                                                                                  | 0                                           |          |\n| d              | Distortion factor                                                                                                                                                                                                             | number                                                                                                                                                                  | 1.5                                         |          |\n| maxD           | Maximum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 5                                           |          |\n| minD           | Minimum adjustable distortion factor of the fisheye                                                                                                                                                                           | number                                                                                                                                                                  | 0                                           |          |\n| scaleRBy       | Method to adjust the fisheye radius:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                                     | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| scaleDBy       | Method to adjust the fisheye distortion factor:<br/>- `'wheel'`: Adjust by wheel <br/>- `'drag'`: Adjust by dragging                                                                                                          | `wheel` \\| `drag`                                                                                                                                                       | -                                           |          |\n| showDPercent   | Whether to show the distortion factor value in the fisheye                                                                                                                                                                    | boolean                                                                                                                                                                 | true                                        |          |\n| style          | Style of the fisheye, [configuration options](#style)                                                                                                                                                                         | object                                                                                                                                                                  | -                                           |          |\n| nodeStyle      | Style of nodes in the fisheye                                                                                                                                                                                                 | [NodeStyle](/en/manual/element/node/base-node#style) \\| ((datum: [NodeData](/en/manual/data#节点数据nodedata)) => [NodeStyle](/en/manual/element/node/base-node#style)) | `{ label: true }`                           |          |\n| preventDefault | Whether to prevent default events                                                                                                                                                                                             | boolean                                                                                                                                                                 | true                                        |          |\n\n### style\n\nCircular style properties for configuring the appearance of the fisheye.\n\n| Property      | Description        | Type                          | Default Value |\n| ------------- | ------------------ | ----------------------------- | ------------- |\n| fill          | Fill color         | string \\| Pattern \\| null     | `#ccc`        |\n| stroke        | Stroke color       | string \\| Pattern \\| null     | `#000`        |\n| opacity       | Overall opacity    | number \\| string              | -             |\n| fillOpacity   | Fill opacity       | number \\| string              | 0.1           |\n| strokeOpacity | Stroke opacity     | number \\| string              | -             |\n| lineWidth     | Line width         | number \\| string              | 2             |\n| lineCap       | Line cap style     | `butt` \\| `round` \\| `square` | -             |\n| lineJoin      | Line join style    | `miter` \\| `round` \\| `bevel` | -             |\n| shadowColor   | Shadow color       | string                        | -             |\n| shadowBlur    | Shadow blur degree | number                        | -             |\n| shadowOffsetX | Shadow X offset    | number                        | -             |\n| shadowOffsetY | Shadow Y offset    | number                        | -             |\n\nFor complete style properties, refer to [Element - Node - Built-in Node - General Style Properties - style](/en/manual/element/node/base-node#style)\n\n### Zoom Control\n\n`scaleRBy` and `scaleDBy` can be used to control the adjustment method of the fisheye's radius and distortion factor respectively:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // Adjust radius by wheel\n      scaleRBy: 'wheel',\n      // Adjust distortion factor by dragging\n      scaleDBy: 'drag',\n      // Set range for radius and distortion factor\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\nNote: When `trigger`, `scaleRBy`, and `scaleDBy` are all set to `'drag'`, the priority order is `trigger` > `scaleRBy` > `scaleDBy`, and only the highest priority configuration item will bind the drag event. Similarly, if `scaleRBy` and `scaleDBy` are both set to `'wheel'`, only `scaleRBy` will bind the wheel event.\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### Custom Styles\n\nYou can customize the appearance and behavior of the fisheye:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // Fill color of the fisheye area\n        fillOpacity: 0.2, // Opacity of the fill area\n        stroke: '#1d39c4', // Color of the fisheye border\n        strokeOpacity: 0.8, // Opacity of the border\n        lineWidth: 1.5, // Line width of the border\n        shadowColor: '#1d39c4', // Shadow color\n        shadowBlur: 10, // Shadow blur radius\n        shadowOffsetX: 0, // Horizontal shadow offset\n        shadowOffsetY: 0, // Vertical shadow offset\n        cursor: 'pointer', // Cursor style when hovering\n      },\n      nodeStyle: {\n        // Basic node style\n        size: 40, // Node size\n        fill: '#d6e4ff', // Node fill color\n        stroke: '#2f54eb', // Node border color\n        lineWidth: 2, // Node border width\n        shadowColor: '#2f54eb', // Node shadow color\n        shadowBlur: 5, // Node shadow blur radius\n        cursor: 'pointer', // Cursor style when hovering\n\n        // Label style\n        label: true, // Show label\n        labelFontSize: 14, // Label font size\n        labelFontWeight: 'bold', // Label font weight\n        labelFill: '#1d39c4', // Label text color\n        labelBackground: true, // Show label background\n        labelBackgroundFill: '#fff', // Label background fill color\n        labelBackgroundStroke: '#1d39c4', // Label background border color\n        labelBackgroundOpacity: 0.8, // Label background opacity\n        labelBackgroundPadding: [4, 8, 4, 8], // Label background padding [top, right, bottom, left]\n\n        // Icon style\n        icon: true, // Show icon\n        iconFontFamily: 'iconfont', // Icon font\n        iconText: '\\ue6f6', // Icon Unicode\n        iconFill: '#1d39c4', // Icon color\n        iconSize: 16, // Icon size\n        iconFontWeight: 'normal', // Icon font weight\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Fisheye.zh.md) -->\n---\ntitle: 鱼眼放大镜 Fisheye\norder: 6\n---\n\n## 概述\n\n鱼眼放大镜插件是为 focus+context 的探索场景设计的，它能够在放大关注区域的同时，保证上下文以及上下文与关注中心的关系不丢失，是一个重要的可视化探索工具。\n\n## 使用场景\n\n- 在演示过程中需要突出展示某些区域内容\n- 需要局部放大查看细节时，同时又不想失去整体视图\n\n## 基本用法\n\n以下是一个简单的 Fisheye 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      trigger: 'drag', // 通过拖拽移动鱼眼\n      d: 1.5, // 设置畸变因子\n      r: 120, // 设置鱼眼半径\n      showDPercent: true, // 显示畸变程度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/fisheye.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                                                                                          | 类型                                                                                                                                                           | 默认值                 | 必选 |\n| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---- |\n| type           | 插件类型                                                                                                                                                                                      | string                                                                                                                                                         | `fisheye`              | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                                                                                              | string                                                                                                                                                         | -                      |      |\n| trigger        | 用于控制鱼眼放大镜的移动方式，支持以下三种配置：<br/>- `pointermove`：鱼眼放大镜始终跟随鼠标移动 <br/>- `click`：点击画布时移动鱼眼放大镜到点击位置 <br/>- `drag`：通过拖拽方式移动鱼眼放大镜 | `pointermove` \\| `drag` \\| `click`                                                                                                                             | `pointermove`          |      |\n| r              | 鱼眼放大镜半径                                                                                                                                                                                | number                                                                                                                                                         | 120                    |      |\n| maxR           | 鱼眼放大镜可调整的最大半径                                                                                                                                                                    | number                                                                                                                                                         | 画布宽高的最小值的一半 |      |\n| minR           | 鱼眼放大镜可调整的最小半径                                                                                                                                                                    | number                                                                                                                                                         | 0                      |      |\n| d              | 畸变因子                                                                                                                                                                                      | number                                                                                                                                                         | 1.5                    |      |\n| maxD           | 鱼眼放大镜可调整的最大畸变因子                                                                                                                                                                | number                                                                                                                                                         | 5                      |      |\n| minD           | 鱼眼放大镜可调整的最小畸变因子                                                                                                                                                                | number                                                                                                                                                         | 0                      |      |\n| scaleRBy       | 调整鱼眼放大镜范围半径的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| scaleDBy       | 调整鱼眼放大镜畸变因子的方式：<br/>- `'wheel'`：滚轮调整 <br/>- `'drag'`：拖拽调整                                                                                                            | `wheel` \\| `drag`                                                                                                                                              | -                      |      |\n| showDPercent   | 是否在鱼眼放大镜中显示畸变因子数值                                                                                                                                                            | boolean                                                                                                                                                        | true                   |      |\n| style          | 鱼眼放大镜样式，[配置项](#style)                                                                                                                                                              | object                                                                                                                                                         | -                      |      |\n| nodeStyle      | 在鱼眼放大镜中的节点样式                                                                                                                                                                      | [NodeStyle](/manual/element/node/base-node#style) \\| ((datum: [NodeData](/manual/data#节点数据nodedata)) => [NodeStyle](/manual/element/node/base-node#style)) | `{ label: true }`      |      |\n| preventDefault | 是否阻止默认事件                                                                                                                                                                              | boolean                                                                                                                                                        | true                   |      |\n\n### style\n\n圆形样式属性，用于配置鱼眼放大镜的外观。\n\n| 属性          | 描述            | 类型                          | 默认值 |\n| ------------- | --------------- | ----------------------------- | ------ |\n| fill          | 填充颜色        | string \\| Pattern \\| null     | `#ccc` |\n| stroke        | 描边颜色        | string \\| Pattern \\| null     | `#000` |\n| opacity       | 整体透明度      | number \\| string              | -      |\n| fillOpacity   | 填充透明度      | number \\| string              | 0.1    |\n| strokeOpacity | 描边透明度      | number \\| string              | -      |\n| lineWidth     | 线宽度          | number \\| string              | 2      |\n| lineCap       | 线段端点样式    | `butt` \\| `round` \\| `square` | -      |\n| lineJoin      | 线段连接处样式  | `miter` \\| `round` \\| `bevel` | -      |\n| shadowColor   | 阴影颜色        | string                        | -      |\n| shadowBlur    | 阴影模糊程度    | number                        | -      |\n| shadowOffsetX | 阴影 X 方向偏移 | number                        | -      |\n| shadowOffsetY | 阴影 Y 方向偏移 | number                        | -      |\n\n完整样式属性参考 [元素 -节点 - 内置节点 - 通用样式属性 - style](/manual/element/node/base-node#style)\n\n### 缩放控制\n\n通过 `scaleRBy` 和 `scaleDBy` 可以分别控制鱼眼放大镜的半径和畸变因子的调整方式：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      // 通过滚轮调整半径\n      scaleRBy: 'wheel',\n      // 通过拖拽调整畸变因子\n      scaleDBy: 'drag',\n      // 设置半径和畸变因子的范围\n      minR: 50,\n      maxR: 200,\n      minD: 1,\n      maxD: 3,\n    },\n  ],\n});\n```\n\n注意：当 `trigger`、`scaleRBy` 和 `scaleDBy` 同时设置为 `'drag'` 时，优先级顺序为 `trigger` > `scaleRBy` > `scaleDBy`，只会为优先级最高的配置项绑定拖拽事件。同理，如果 `scaleRBy` 和 `scaleDBy` 同时设置为 `'wheel'`，只会为 `scaleRBy` 绑定滚轮事件。\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['fisheye'],\n});\n```\n\n### 自定义样式\n\n可以自定义鱼眼放大镜的外观和行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fisheye',\n      r: 150,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 300,\n  data: {\n    nodes: [\n      { id: 'node-1', style: { x: 150, y: 100 } },\n      { id: 'node-2', style: { x: 250, y: 100 } },\n      { id: 'node-3', style: { x: 200, y: 180 } },\n      { id: 'node-4', style: { x: 120, y: 180 } },\n      { id: 'node-5', style: { x: 280, y: 180 } },\n    ],\n    edges: [\n      { id: 'edge-1', source: 'node-1', target: 'node-2' },\n      { id: 'edge-2', source: 'node-1', target: 'node-3' },\n      { id: 'edge-3', source: 'node-2', target: 'node-3' },\n      { id: 'edge-4', source: 'node-3', target: 'node-4' },\n      { id: 'edge-5', source: 'node-3', target: 'node-5' },\n    ],\n  },\n  node: {\n    style: {\n      size: 30,\n      fill: '#e6f7ff',\n      stroke: '#1890ff',\n      lineWidth: 1,\n      label: false,\n      icon: false,\n    },\n  },\n  edge: {\n    style: {\n      stroke: '#91d5ff',\n      lineWidth: 1,\n    },\n  },\n  plugins: [\n    {\n      type: 'fisheye',\n      key: 'fisheye',\n      r: 100,\n      d: 2,\n      style: {\n        fill: '#2f54eb', // 鱼眼区域的填充颜色\n        fillOpacity: 0.2, // 填充区域的透明度\n        stroke: '#1d39c4', // 鱼眼边框的颜色\n        strokeOpacity: 0.8, // 边框的透明度\n        lineWidth: 1.5, // 边框的线宽\n        shadowColor: '#1d39c4', // 阴影颜色\n        shadowBlur: 10, // 阴影的模糊半径\n        shadowOffsetX: 0, // 阴影的水平偏移\n        shadowOffsetY: 0, // 阴影的垂直偏移\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n      },\n      nodeStyle: {\n        // 节点基础样式\n        size: 40, // 节点大小\n        fill: '#d6e4ff', // 节点填充颜色\n        stroke: '#2f54eb', // 节点边框颜色\n        lineWidth: 2, // 节点边框宽度\n        shadowColor: '#2f54eb', // 节点阴影颜色\n        shadowBlur: 5, // 节点阴影模糊半径\n        cursor: 'pointer', // 鼠标悬停时的指针样式\n\n        // 标签样式\n        label: true, // 是否显示标签\n        labelFontSize: 14, // 标签字体大小\n        labelFontWeight: 'bold', // 标签字体粗细\n        labelFill: '#1d39c4', // 标签文字颜色\n        labelBackground: true, // 是否显示标签背景\n        labelBackgroundFill: '#fff', // 标签背景填充颜色\n        labelBackgroundStroke: '#1d39c4', // 标签背景边框颜色\n        labelBackgroundOpacity: 0.8, // 标签背景透明度\n        labelBackgroundPadding: [4, 8, 4, 8], // 标签背景内边距 [上,右,下,左]\n\n        // 图标样式\n        icon: true, // 是否显示图标\n        iconFontFamily: 'iconfont', // 图标字体\n        iconText: '\\ue6f6', // 图标的 Unicode 编码\n        iconFill: '#1d39c4', // 图标颜色\n        iconSize: 16, // 图标大小\n        iconFontWeight: 'normal', // 图标字体粗细\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph, iconfont } from '@antv/g6';\n\nconst style = document.createElement('style');\nstyle.innerHTML = `@import url('${iconfont.css}');`;\ndocument.head.appendChild(style);\n\nfetch('https://assets.antv.antgroup.com/g6/relations.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const graph = new Graph({\n      container: 'container',\n      autoFit: 'view',\n      data,\n      node: {\n        style: {\n          size: (datum) => datum.id.length * 2 + 10,\n          label: false,\n          labelText: (datum) => datum.id,\n          labelBackground: true,\n          icon: false,\n          iconFontFamily: 'iconfont',\n          iconText: '\\ue6f6',\n          iconFill: '#fff',\n        },\n        palette: {\n          type: 'group',\n          field: (datum) => datum.id,\n          color: ['#1783FF', '#00C9C9', '#F08F56', '#D580FF'],\n        },\n      },\n      edge: {\n        style: {\n          stroke: '#e2e2e2',\n        },\n      },\n      plugins: [{ key: 'fisheye', type: 'fisheye', nodeStyle: { label: true, icon: true } }],\n    });\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Fullscreen.en.md) -->\n---\ntitle: Fullscreen\norder: 7\n---\n\n## Overview\n\nThe Fullscreen plugin allows users to expand the graph visualization content to the entire screen, providing a broader view and a better immersive experience.\n\n## Use Cases\n\nThe Fullscreen plugin is mainly suitable for the following scenarios:\n\n- Provide a broader view for viewing complex graph data\n- Enhance immersive experience, focusing on graph visualization content\n- Display graph data in presentations or reports\n\n## Basic Usage\n\nBelow is a simple example of initializing the Fullscreen plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n      onEnter: () => {\n        console.log('Entered fullscreen mode');\n      },\n      onExit: () => {\n        console.log('Exited fullscreen mode');\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property | Description                                                                                                      | Type                                 | Default Value | Required |\n| -------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ------------- | -------- |\n| type     | Plugin type                                                                                                      | string                               | `fullscreen`  | ✓        |\n| key      | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                | string                               | -             |          |\n| autoFit  | Whether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen | boolean                              | true          |          |\n| trigger  | Method to trigger fullscreen, [example](#trigger)                                                                | { request?: string; exit?: string; } | -             |          |\n| onEnter  | Callback after entering fullscreen                                                                               | () => void                           | -             |          |\n| onExit   | Callback after exiting fullscreen                                                                                | () => void                           | -             |          |\n\n### trigger\n\nThe trigger property is used to control the method of triggering fullscreen. It supports two configuration methods:\n\n#### Shortcut Key Configuration\n\nUse keyboard shortcuts to trigger fullscreen and exit fullscreen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // Use shortcut key F to enter fullscreen\n        exit: 'Esc', // Use shortcut key Esc to exit fullscreen\n      },\n    },\n  ],\n});\n```\n\n#### Custom Trigger\n\nControl fullscreen by calling the request and exit methods.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\nWhether to auto-fit the canvas size, the canvas size will automatically adapt to the screen size when fullscreen.\n\n- When set to true, the canvas will automatically resize to fit the entire screen.\n- When set to false, the canvas size remains unchanged.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\nThis method is used to enter fullscreen mode programmatically. It can be called on the plugin instance to expand the graph visualization to the entire screen.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Enter fullscreen\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\nThis method is used to exit fullscreen mode programmatically. It can be called on the plugin instance to revert the graph visualization back to its original size.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// Exit fullscreen\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## Practical Examples\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Fullscreen.zh.md) -->\n---\ntitle: 全屏展示 Fullscreen\norder: 7\n---\n\n## 概述\n\n全屏展示插件允许用户将图可视化内容扩展到整个屏幕，提供更广阔的视图和更好的沉浸式体验。\n\n## 使用场景\n\n全屏展示插件主要适用于以下场景：\n\n- 提供更广阔的视图，便于查看复杂图数据\n- 增强沉浸式体验，专注于图可视化内容\n- 在演示或报告中展示图数据\n\n## 基本用法\n\n以下是一个简单的 Fullscreen 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n      onEnter: () => {\n        console.log('进入全屏模式');\n      },\n      onExit: () => {\n        console.log('退出全屏模式');\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性    | 描述                                                 | 类型                                 | 默认值       | 必选 |\n| ------- | ---------------------------------------------------- | ------------------------------------ | ------------ | ---- |\n| type    | 插件类型                                             | string                               | `fullscreen` | ✓    |\n| key     | 插件的唯一标识，可用于获取插件实例或更新插件选项     | string                               | -            |      |\n| autoFit | 是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸 | boolean                              | true         |      |\n| trigger | 触发全屏的方式，[示例](#trigger)                     | { request?: string; exit?: string; } | -            |      |\n| onEnter | 进入全屏后的回调                                     | () => void                           | -            |      |\n| onExit  | 退出全屏后的回调                                     | () => void                           | -            |      |\n\n### trigger\n\ntrigger 属性用于控制触发全屏的方式。它支持两种配置方式：\n\n#### 快捷键配置\n\n使用键盘快捷键来触发全屏和退出全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      trigger: {\n        request: 'F', // 使用快捷键 F 进入全屏\n        exit: 'Esc', // 使用快捷键 Esc 退出全屏\n      },\n    },\n  ],\n});\n```\n\n#### 自定义触发\n\n通过调用 request 和 exit 方法来控制全屏。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n### autoFit\n\n是否自适应画布尺寸，全屏后画布尺寸会自动适应屏幕尺寸。\n\n- 设置为 true 时，画布会自动调整大小以适应整个屏幕。\n- 设置为 false 时，画布大小保持不变。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      autoFit: true,\n    },\n  ],\n});\n```\n\n## API\n\n### Fullscreen.request()\n\n这个方法可以让你通过代码进入全屏模式。调用插件实例上的这个方法，就能把图形内容扩展到整个屏幕。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 进入全屏\ngraph.getPluginInstance('my-fullscreen').request();\n```\n\n### Fullscreen.exit()\n\n这个方法可以让你通过代码退出全屏模式。调用插件实例上的这个方法，就能把图形内容恢复到原来的大小。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'my-fullscreen',\n    },\n  ],\n});\n\n// 退出全屏\ngraph.getPluginInstance('my-fullscreen').exit();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  autoFit: 'center',\n  background: '#fff',\n  plugins: [\n    {\n      type: 'fullscreen',\n      key: 'fullscreen',\n    },\n    function () {\n      const graph = this;\n      return {\n        type: 'toolbar',\n        key: 'toolbar',\n        position: 'top-left',\n        onClick: (item) => {\n          const fullscreenPlugin = graph.getPluginInstance('fullscreen');\n          if (item === 'request-fullscreen') {\n            fullscreenPlugin.request();\n          }\n          if (item === 'exit-fullscreen') {\n            fullscreenPlugin.exit();\n          }\n        },\n        getItems: () => {\n          return [\n            { id: 'request-fullscreen', value: 'request-fullscreen' },\n            { id: 'exit-fullscreen', value: 'exit-fullscreen' },\n          ];\n        },\n      };\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/GridLine.en.md) -->\n---\ntitle: GridLine\norder: 8\n---\n\n## Overview\n\nThe GridLine plugin provides visual auxiliary lines for the canvas, helping users precisely position and align graphic elements. It is an indispensable tool in graphic drawing.\n\n## Use Cases\n\nThe GridLine plugin is mainly suitable for the following scenarios:\n\n- Assisting users in precise drawing and element alignment\n- Providing visual references to enhance spatial awareness\n- Building a structured reference system when designing and editing graphics\n\n## Basic Usage\n\nBelow is a simple example of initializing the GridLine plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // Specify a unique identifier for dynamic updates\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## Configuration Options\n\n| Property        | Description                                                                                         | Type                                              | Default     | Required |\n| --------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------- | -------- |\n| type            | Plugin type                                                                                         | string                                            | `grid-line` | ✓        |\n| key             | Unique identifier for the plugin, used to get the plugin instance or update plugin options          | string                                            | -           |          |\n| border          | Whether to display the border                                                                       | boolean                                           | true        |          |\n| borderLineWidth | Border line width                                                                                   | number                                            | 1           |          |\n| borderStroke    | Border color, see [CSS border-color](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color) | string                                            | `#eee`      |          |\n| borderStyle     | Border style, see [CSS border-style](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style) | string                                            | `solid`     |          |\n| follow          | Whether to follow canvas movements                                                                  | boolean \\| {translate ?: boolean, zoom?: boolean} | false       |          |\n| lineWidth       | Grid line width                                                                                     | number \\| string                                  | 1           |          |\n| size            | Grid unit size in pixels                                                                            | number                                            | 20          |          |\n| stroke          | Grid line color                                                                                     | string                                            | `#eee`      |          |\n\n### follow\n\nThe `follow` property controls whether the grid lines follow the canvas transformations. It supports two configuration methods:\n\n1. **Boolean Configuration**: When set to `true`, the grid lines follow both canvas translation and zoom; when set to `false`, they remain static.\n\n```js\n// Enable both translation and zoom following\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **Object Configuration**: Allows more precise control over the grid line following behavior.\n\n```js\n// Follow translation only, not zoom\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // Follow translation\n        zoom: false, // Do not follow zoom\n      },\n    },\n  ],\n});\n\n// Follow zoom only, not translation\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // Do not follow translation\n        zoom: true, // Follow zoom\n      },\n    },\n  ],\n});\n```\n\nWhen grid lines follow zoom, they maintain a relative position to the canvas content, making alignment references more precise. Following translation allows the grid to move with the canvas content, enhancing the visual experience of spatial continuity.\n\n## Code Examples\n\n### Basic Grid Line\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid-line'],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### Custom Style\n\nYou can customize the grid line style as needed:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid unit\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // Blue semi-transparent grid line\n      lineWidth: 2,\n      size: 40, // Larger grid\n      borderStroke: '#1890ff', // Blue border\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Follow Movement\n\nEnabling the follow option allows the grid to move with the canvas, enhancing user experience:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n```\n\nTry dragging/zooming the canvas to observe the grid following effect:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // Grid follows canvas movement\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Dynamic Grid Update\n\nUse the key identifier to dynamically update grid properties at runtime:\n\n```js\n// Initial configuration\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// Subsequent dynamic updates\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // Update grid size\n  stroke: '#ff4d4f', // Update grid color\n});\n```\n\n## Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/GridLine.zh.md) -->\n---\ntitle: 网格线 GridLine\norder: 8\n---\n\n## 概述\n\n网格线插件为画布提供可视化辅助线，帮助用户精确定位和对齐图形元素，是图形绘制中不可或缺的辅助工具。\n\n## 使用场景\n\n网格线插件主要适用于以下场景：\n\n- 辅助用户精确绘图和元素对齐\n- 提供视觉参考，增强空间感知\n- 在设计和编辑图形时构建结构化的参考系统\n\n## 基本用法\n\n以下是一个简单的 GridLine 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid-line', // 指定唯一标识符，便于后续动态更新\n      size: 20,\n      stroke: '#0001',\n      follow: true,\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/grid-line.md\"></embed>\n\n## 配置项\n\n| 属性            | 描述                                                                                                     | 类型                                               | 默认值      | 必选 |\n| --------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------- | ---- |\n| type            | 插件类型                                                                                                 | string                                             | `grid-line` | ✓    |\n| key             | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                         | string                                             | -           |      |\n| border          | 是否显示边框                                                                                             | boolean                                            | true        |      |\n| borderLineWidth | 边框线宽                                                                                                 | number                                             | 1           |      |\n| borderStroke    | 边框颜色，详细属性参考 [CSS border-color](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-color) | string                                             | `#eee`      |      |\n| borderStyle     | 边框样式，详细属性参考 [CSS border-style](https://developer.mozilla.org/zh-CN/docs/Web/CSS/border-style) | string                                             | `solid`     |      |\n| follow          | 是否跟随画布移动                                                                                         | boolean \\｜ {translate ?: boolean, zoom?: boolean} | false       |      |\n| lineWidth       | 网格线宽度                                                                                               | number \\| string                                   | 1           |      |\n| size            | 网格单元大小，单位为像素                                                                                 | number                                             | 20          |      |\n| stroke          | 网格线颜色                                                                                               | string                                             | `#eee`      |      |\n\n### follow\n\n`follow` 属性用于控制网格线是否跟随画布的变换操作。它支持两种配置方式：\n\n1. **布尔值配置**：当设置为 `true` 时，网格线会同时跟随画布的平移和缩放；设置为 `false` 时则保持静态。\n\n```js\n// 同时启用跟随平移和缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true,\n    },\n  ],\n});\n```\n\n2. **对象配置**：可以更精细地控制网格线的跟随行为。\n\n```js\n// 仅跟随平移，不跟随缩放\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: true, // 跟随平移\n        zoom: false, // 不跟随缩放\n      },\n    },\n  ],\n});\n\n// 仅跟随缩放，不跟随平移\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: {\n        translate: false, // 不跟随平移\n        zoom: true, // 跟随缩放\n      },\n    },\n  ],\n});\n```\n\n当网格线跟随缩放时，它会保持与画布内容的相对位置关系，使得对齐参考更加精准。跟随平移则让网格随着画布内容一起移动，增强空间连续性的视觉体验。\n\n## 代码示例\n\n### 基础网格线\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid-line'],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: ['grid-line'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义网格线的样式：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格单元\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      stroke: '#1890ff33', // 蓝色半透明网格线\n      lineWidth: 2,\n      size: 40, // 更大的网格\n      borderStroke: '#1890ff', // 蓝色边框\n      borderLineWidth: 2,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 跟随移动\n\n启用 follow 选项可以让网格跟随画布移动，增强用户体验：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n```\n\n试着拖拽/缩放画布，观察网格的跟随效果：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  data: { nodes: [{ id: 'node-1', style: { x: 150, y: 75 } }] },\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n  plugins: [\n    {\n      type: 'grid-line',\n      follow: true, // 网格跟随画布移动\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 动态更新网格\n\n使用 key 标识符可以在运行时动态更新网格属性：\n\n```js\n// 初始化配置\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'grid-line',\n      key: 'my-grid',\n      size: 20,\n    },\n  ],\n});\n\n// 后续动态更新\ngraph.updatePlugin({\n  key: 'my-grid',\n  size: 40, // 更新网格大小\n  stroke: '#ff4d4f', // 更新网格颜色\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ key: 'grid-line', type: 'grid-line', follow: false }],\n});\n\ngraph.render();\n\nwindow.addPanel((gui) => {\n  gui\n    .add({ follow: false }, 'follow')\n    .name('Follow')\n    .onChange((value) => {\n      graph.updatePlugin({\n        key: 'grid-line',\n        follow: value,\n      });\n    });\n});\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/History.en.md) -->\n---\ntitle: History\norder: 9\n---\n\n## Overview\n\nThis plugin is used to implement the **Undo** and **Redo** functions in graph editing. By recording the historical state stack of user operations, it supports backtracking or restoring operations during graph interactions. The plugin provides users with comprehensive configuration options and APIs.\n\n## Usage Scenarios\n\nThe history plugin is suitable for all scenarios involving graph editing.\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## Basic Usage\n\nAdd this plugin in the graph configuration:\n\n**1. Quick Configuration (Static)**\n\nDeclare directly using a string. This method is simple but only supports default configurations and cannot be dynamically modified after configuration:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['history'],\n});\n```\n\n**2. Object Configuration (Recommended)**\n\nConfigure using an object form, supporting custom parameters, and allowing dynamic updates at runtime:\n\n```javascript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property         | Description                                                                                                                                                                                                   | Type                                                           | Default Value | Required |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | -------- |\n| afterAddCommand  | Called after a command is added to the `Undo/Redo` queue. `revert` is `true` for undo operations and `false` for redo operations                                                                              | (cmd: [Command](#command), revert: boolean) => void            | -             |          |\n| beforeAddCommand | Called before a command is added to the `Undo/Redo` queue. If this method returns `false`, the command will not be added to the queue. `revert` is `true` for undo operations and `false` for redo operations | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -             |          |\n| executeCommand   | Callback function when executing a command                                                                                                                                                                    | (cmd: [Command](#command)) => void                             | -             |          |\n| stackSize        | Maximum length of history records to be recorded                                                                                                                                                              | number                                                         | 0 (unlimited) |          |\n\n### Parameter Type Description\n\n#### `Command`\n\n```typescript\n// Single history command\ninterface Command {\n  current: CommandData; // Current data\n  original: CommandData; // Original data\n  animation: boolean; // Whether to enable animation\n}\n// Single history command data\ninterface CommandData {\n  add: GraphData; // Added data\n  update: GraphData; // Updated data\n  remove: GraphData; // Removed data\n}\n// Graph data\ninterface GraphData {\n  nodes?: NodeData[]; // Node data\n  edges?: EdgeData[]; // Edge data\n  combos?: ComboData[]; // Combo data\n}\n```\n\n## API\n\nThe history plugin provides the following APIs for users to use as needed. For how to call plugin methods, please refer to the [Plugin Overview Document](/en/manual/plugin/overview#calling-plugin-methods)\n\n### History.canRedo()\n\nDetermines whether a **redo** operation can be performed. If there are records in the redo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanRedo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('Redo operation can be performed');\n} else {\n  console.log('Redo stack is empty, cannot redo');\n}\n```\n\n### History.canUndo()\n\nDetermines whether an **undo** operation can be performed. If there are records in the undo stack, it returns `true`; otherwise, it returns `false`.\n\n```typescript\ncanUndo(): boolean;\n```\n\n**Example:**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('Undo operation can be performed');\n} else {\n  console.log('Undo stack is empty, cannot undo');\n}\n```\n\n### History.clear()\n\nClears the history records, including the undo and redo stacks.\n\n```typescript\nclear(): void;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('History records cleared');\n```\n\n### History.on()\n\nListens to history events, allowing users to execute custom logic when specific events occur.\n\n```typescript\non(event: Loosen<HistoryEvent>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\nParameter Type Description:\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // When a command is undone\n    REDO = 'redo', // When a command is redone\n    CANCEL = 'cancel', // When a command is canceled\n    ADD = 'add', // When a command is added to the queue\n    CLEAR = 'clear', // When the history queue is cleared\n    CHANGE = 'change', // When the history queue changes\n  }\n  ```\n\n- Command\n\n  Please refer to the previous [Command](#parameter-type-description) type description\n\nExample:\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('Undo operation executed');\n});\n```\n\n### History.redo()\n\nPerforms a **redo** operation and returns the plugin instance. If the redo stack is empty, no operation is performed.\n\n```typescript\nredo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('Redo operation executed');\n```\n\n### History.undo()\n\nPerforms an **undo** operation and returns the plugin instance. If the undo stack is empty, no operation is performed.\n\n```typescript\nundo(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('Undo operation executed');\n```\n\n### History.undoAndCancel()\n\nPerforms an undo operation without recording it in the history and returns the plugin instance. Note that this operation will clear the **redo** stack.\n\n```typescript\nundoAndCancel(): History;\n```\n\n**Example:**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('Undo and cancel operation executed');\n```\n\n## History Modes\n\nThis plugin supports two history modes:\n\n### Default Mode\n\nIn default mode, every time a **render** is triggered (for example, after updating element data, the user actively executes the `graph.draw()` method to trigger rendering), the plugin records the data **before** and **after** rendering and stacks it as an operation record.\n\n### Custom Mode\n\n#### Scenario Description\n\nIn actual needs, a user's graph editing operation may involve **multiple renders**. For example, in one editing operation, first display nodes A and B, then display the connection from A to B. This involves two renders (i.e., the user needs to perform `graph.draw()` twice). In this scenario, the default mode will stack two history records, which are:\n\n- Display nodes A and B\n- Display the connection from A to B\n\nObviously, in actual business, one operation should only require one undo.\n\nBut here, when undoing this operation, the user needs to call the `undo` method twice, which means two undos are required.\n\n#### Scenario Support\n\nTo support such scenarios, G6 provides a batch controller (`BatchController`, [refer to the source code](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)), which is provided in the graph instance context.\n\nThe history plugin implements custom operation records based on this batch controller. The code example is as follows:\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // Start batch operation\ngraph.addNodeData(...); // Display nodes A and B\ngraph.draw(); // First render trigger\ngraph.addEdgeData(...); // Display the connection from A to B\ngraph.draw(); // Second render trigger\ngraph.context.batch.endBatch(); // End batch operation\n```\n\nIn the example:\n\n- By calling the `startBatch` method of the batch controller instance, the history plugin is informed that batch operations are now being performed. Before the batch operation ends, no matter how many renders are triggered, no history records should be stacked (the history plugin will record the change data for each render trigger).\n- After completing the last data change, call the `endBatch()` method. The history plugin listens for the completion of the batch operation and stacks this batch operation as a history record.\n\nFinally, the user only needs to perform one `undo` to undo.\n\n## Code Examples\n\nBelow are some common cases with corresponding code references.\n\n### Undo and Redo Button States\n\nIn actual business scenarios, you may need to customize the toolbar of the canvas, which involves the enable and disable states of the undo and redo buttons.\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\nIn the example, by listening to the `HistoryEvent.CHANGE` event, which is triggered when the history queue changes, it is determined in real-time whether undo and redo operations can be performed.\n\n### Determine Whether a Command is Allowed to Enter the Queue\n\nHere is a simple scenario: only the operation of removing elements is allowed to enter the history queue.\n\n```typescript\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\nIn the example, the configuration option [beforeAddCommand](#beforeAddCommand) is used to determine whether there are elements removed in `cmd.current.remove`.\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/History.zh.md) -->\n---\ntitle: 历史记录 History\norder: 9\n---\n\n## 概述\n\n该插件用于实现图编辑的 **撤销（Undo）** 和 **重做（Redo）** 功能，通过记录用户操作的历史状态堆栈，支持在图交互过程中进行回溯或恢复操作。该插件为用户提供了完善的配置项和 API 。\n\n## 使用场景\n\n历史记录插件适用于所有涉及到图编辑的场景。\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/history.md\"></embed>\n\n## 基本用法\n\n在图配置中添加这一插件：\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['history'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history-1',\n      stackSize: 10,\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性             | 描述                                                                                                                                                                | 类型                                                           | 默认值      | 必选 |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------- | ---- |\n| afterAddCommand  | 当一个命令被添加到 `Undo/Redo` 队列后被调用。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作                                                           | (cmd: [Command](#command), revert: boolean) => void            | -           |      |\n| beforeAddCommand | 当一个命令被添加到 `Undo/Redo` 队列前被调用，如果该方法返回 `false`，那么这个命令将不会被添加到队列中。`revert` 为 `true` 时表示撤销操作，为 `false` 时表示重做操作 | (cmd: [Command](#command), revert: boolean) => boolean \\| void | -           |      |\n| executeCommand   | 执行命令时的回调函数                                                                                                                                                | (cmd: [Command](#command)) => void                             | -           |      |\n| stackSize        | 最多记录该数据长度的历史记录                                                                                                                                        | number                                                         | 0（不限制） |      |\n\n### 参数类型说明\n\n#### `Command`\n\n```typescript\n// 单条历史记录命令\ninterface Command {\n  current: CommandData; // 当前数据\n  original: CommandData; // 原始数据\n  animation: boolean; // 是否开启动画\n}\n// 单条历史记录命令数据\ninterface CommandData {\n  add: GraphData; // 新增的数据\n  update: GraphData; // 更新的数据\n  remove: GraphData; // 移除的数据\n}\n// 图数据\ninterface GraphData {\n  nodes?: NodeData[]; // 节点数据\n  edges?: EdgeData[]; // 边数据\n  combos?: ComboData[]; // Combo 数据\n}\n```\n\n## API\n\nhistory 插件提供了以下 API 供用户按需使用，调用插件方法的方式请参考 [插件总览文档](/manual/plugin/overview#调用插件方法)\n\n### History.canRedo()\n\n判断是否可以进行**重做**操作。如果重做堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanRedo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canRedo = historyInstance.canRedo();\nif (canRedo) {\n  console.log('可以进行重做操作');\n} else {\n  console.log('重做堆栈为空，无法重做');\n}\n```\n\n### History.canUndo()\n\n判断是否可以进行**撤销**操作。如果撤销堆栈中有记录，则返回 `true`，否则返回 `false`。\n\n```typescript\ncanUndo(): boolean;\n```\n\n**示例：**\n\n```typescript\nconst canUndo = historyInstance.canUndo();\nif (canUndo) {\n  console.log('可以进行撤销操作');\n} else {\n  console.log('撤销堆栈为空，无法撤销');\n}\n```\n\n### History.clear()\n\n清空历史记录，包括撤销和重做堆栈。\n\n```typescript\nclear(): void;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.clear();\nconsole.log('历史记录已清空');\n```\n\n### History.on()\n\n监听历史记录事件，允许用户在特定事件发生时执行自定义逻辑。\n\n```typescript\non(event: Loosen/<HistoryEvent/>, handler: (e: { cmd?: Command | null }) => void): void;\n```\n\n参数类型说明：\n\n- HistoryEvent\n\n  ```typescript\n  enum HistoryEvent {\n    UNDO = 'undo', // 当命令被撤销时\n    REDO = 'redo', // 当命令被重做时\n    CANCEL = 'cancel', // 当命令被取消时\n    ADD = 'add', // 当命令被添加到队列时\n    CLEAR = 'clear', // 当历史队列被清空时\n    CHANGE = 'change', // 当历史队列发生变化时\n  }\n  ```\n\n- Command\n\n  请参考前面的 [Command](#参数类型说明) 类型说明\n\n示例：\n\n```typescript\nhistoryInstance.on(HistoryEvent.UNDO, () => {\n  console.log('执行了撤销操作');\n});\n```\n\n### History.redo()\n\n执行**重做**操作，并返回插件实例。如果重做堆栈为空，则不执行任何操作。\n\n```typescript\nredo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.redo();\nconsole.log('执行了重做操作');\n```\n\n### History.undo()\n\n执行**撤销**操作，并返回插件实例。如果撤销堆栈为空，则不执行任何操作。\n\n```typescript\nundo(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undo();\nconsole.log('执行了撤销操作');\n```\n\n### History.undoAndCancel()\n\n执行撤销操作且不计入历史记录，并返回插件实例。注意，执行该操作会清空**重做**栈。\n\n```typescript\nundoAndCancel(): History;\n```\n\n**示例：**\n\n```typescript\nhistoryInstance.undoAndCancel();\nconsole.log('执行了撤销并取消操作');\n```\n\n## 历史记录模式\n\n该插件支持两种历史记录模式：\n\n### 默认模式\n\n默认模式下，每一次触发**渲染后**（比如更新元素数据后，用户主动执行 `graph.draw()` 方法触发渲染），插件会把**渲染前**和**渲染后**的数据记录下来并作为一次操作记录入栈。\n\n### 自定义模式\n\n#### 场景描述\n\n实际需求中，用户的一次图编辑操作可能涉及到**多次渲染**，比如，一次编辑操作中，首先把节点 A、B 展示出来，然后展示 A->B 的连线，这里就涉及到两次渲染（即用户需要进行两次 `graph.draw()` ），这种场景下，默认模式会入栈两次历史记录，分别是：\n\n- 展示节点 A 和 B\n- 展示 A->B 的连线\n\n显然，实际业务中，一次操作，也应该只需一次撤销。\n\n但这里在撤销本次操作时，用户需要调用两次 `undo` 方法，也就是需要进行两次撤销。\n\n#### 场景支持\n\n为了支持这样的场景，G6 提供了一个批量控制器（ `BatchController`，[可参考源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/batch.ts)），在图实例上下文中提供了这个批量控制器实例。\n\n历史记录插件则基于这个批量控制器，来实现自定义操作记录，代码示例如下：\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\n\ngraph.context.batch.startBatch(); // 开始批量操作\ngraph.addNodeData(...); // 把节点 A、B 展示出来\ngraph.draw(); // 第一次触发渲染\ngraph.addEdgeData(...); // 把 A->B 连线展示出来\ngraph.draw(); // 第二次触发渲染\ngraph.context.batch.endBatch(); // 结束批量操作\n```\n\n示例中：\n\n- 通过调用批量控制器实例的 `startBatch` 方法，告诉历史记录插件，现在开始进行批量操作，在批量操作没有结束前，不管触发多少次渲染，都不能进行历史记录入栈（历史记录插件会把每次触发渲染的变更数据记录下来）\n- 在完成最后一次数据变更后，调用 `endBatch()` 方法，历史记录插件监听到批量操作完成，则把本次批量操作作为一次历史记录入栈\n\n最终，用户只需要进行一次 `undo` 即可撤销。\n\n## 代码示例\n\n下面列举一些常见的案例，并给出相应的代码参考\n\n### 撤销、重做按钮状态\n\n实际业务场景中，可能需要自定义画布的工具栏，也就涉及到撤销和重做按钮的启禁用状态\n\n```typescript\nconst canUndo = false;\nconst canRedo = false;\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n  ],\n});\nconst historyInstance = graph.getPluginInstance('history');\n\nhistoryInstance.on(HistoryEvent.CHANGE, () => {\n  canUndo = historyInstance.canUndo();\n  canRedo = historyInstance.canRedo();\n});\n```\n\n示例中通过监听 `HistoryEvent.CHANGE` 事件，这个事件在历史队列发生变化时会触发，每次发生变化后，实时判断当前是否可以进行撤销和重做操作\n\n### 判断是否允许命令进入队列\n\n这里实现一个简单的场景：只有移除元素的操作才允许进入历史记录队列\n\n```typescript\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n      beforeAddCommand: (cmd) => {\n        return (\n          cmd.current.remove?.nodes?.length > 0 ||\n          cmd.current.remove?.combos?.length > 0 ||\n          cmd.current.remove?.edges?.length > 0\n        );\n      },\n    },\n  ],\n});\n```\n\n示例中通过配置项 [beforeAddCommand](#beforeAddCommand) 来实现，判断 `cmd.current.remove` 里面是否存在被移除的元素\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Hull.en.md) -->\n---\ntitle: Hull\norder: 10\n---\n\n## Overview\n\nHull is used to process and represent the convex or concave polygon bounding box of a set of points. It can wrap a set of nodes in a minimal geometric shape, helping users better understand and analyze datasets.\n\n- **Convex Hull**: This is a convex polygon that contains all the points and has no indentations.\n- **Concave Hull**: This is a concave polygon that also contains all the points but may have indentations. The degree of indentation is controlled by the concavity parameter.\n\n## Usage Scenarios\n\nThe hull plugin is mainly applicable to the following scenarios:\n\n- Wrapping node collections in data visualization\n- Providing visual references to enhance spatial awareness\n- Identifying the collection relationship of specific nodes in complex network graphs\n\n## Basic Usage\n\nBelow is a simple example of initializing the Hull plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // Specify a unique identifier for subsequent dynamic updates\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n      concavity: Infinity, // Default to convex hull\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## Configuration Options\n\n| Property         | Description                                                                                              | Type                                               | Default Value | Required |\n| ---------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type             | Plugin type                                                                                              | string                                             | `hull`        | ✓        |\n| key              | Unique identifier for the plugin, used for subsequent updates                                            | string                                             | -             |          |\n| members          | Elements within the Hull, including nodes and edges                                                      | string[]                                           | -             | ✓        |\n| concavity        | Concavity, the larger the value, the smaller the concavity; default is Infinity representing Convex Hull | number                                             | Infinity      |          |\n| corner           | Corner type, options are `rounded` \\| `smooth` \\| `sharp`                                                | string                                             | `rounded`     |          |\n| padding          | Padding                                                                                                  | number                                             | `10`          |          |\n| label            | Whether to display the label                                                                             | boolean                                            | true          |          |\n| labelPlacement   | Label position                                                                                           | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`      |          |\n| labelBackground  | Whether to display the background                                                                        | boolean                                            | false         |          |\n| labelPadding     | Label padding                                                                                            | number \\| number[]                                 | 0             |          |\n| labelCloseToPath | Whether the label is close to the hull                                                                   | boolean                                            | true          |          |\n| labelAutoRotate  | Whether the label rotates with the hull, effective only when closeToPath is true                         | boolean                                            | true          |          |\n| labelOffsetX     | X-axis offset                                                                                            | number                                             | 0             |          |\n| labelOffsetY     | Y-axis offset                                                                                            | number                                             | 0             |          |\n| labelMaxWidth    | Maximum width of the text, exceeding will automatically ellipsis                                         | number                                             | 0             |          |\n\nFor complete label styles, see [this link](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nThe concavity attribute is used to control the concavity of the Hull. When set to Infinity, a convex hull is generated; otherwise, a concave hull is generated.\n\n```js\n// Convex hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // Convex hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// Concave hull example\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // Concave hull\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## Code Examples\n\n### Basic Hull\n\nThe simplest way is to use the preset configuration directly:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // List of node IDs to be wrapped\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style of the Hull as needed, such as adjusting color, transparency, and other properties.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // Red semi-transparent border\n      fill: '#7e3feb', // Light purple fill\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // Larger padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### Label Configuration\n\nYou can configure the position, background, offset, and other properties of the label to enhance the visual effect.\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // Display label\n      labelText: 'hull-a',\n      labelPlacement: 'top', // Label position\n      labelBackground: true, // Display label background\n      labelPadding: 5, // Label padding\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Hull.zh.md) -->\n---\ntitle: 轮廓包围 Hull\norder: 10\n---\n\n## 概述\n\n轮廓包围（Hull）用于处理和表示一组点的凸多边形或凹多边形包围盒。它可以将一组节点包裹在一个最小的几何形状中，帮助用户更好地理解和分析数据集。\n\n- **凸包（Convex Hull）**：这是一个凸多边形，它包含所有的点，并且没有任何凹陷。\n- **凹包（Concave Hull）**：这是一个凹多边形，它同样包含所有的点，但是可能会有凹陷。凹包的凹陷程度由 concavity 参数控制。\n\n## 使用场景\n\n轮廓包围插件主要适用于以下场景：\n\n- 数据可视化中的节点集合包裹\n- 提供视觉参考，增强空间感知\n- 在复杂网络图中标识特定节点的集合关系\n\n## 基本用法\n\n以下是一个简单的 Hull 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      key: 'my-hull', // 指定唯一标识符，便于后续动态更新\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n      concavity: Infinity, // 默认为凸包\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/hull.md\"></embed>\n\n## 配置项\n\n| 属性             | 描述                                                       | 类型                                               | 默认值    | 必选 |\n| ---------------- | ---------------------------------------------------------- | -------------------------------------------------- | --------- | ---- |\n| type             | 插件类型                                                   | string                                             | `hull`    | ✓    |\n| key              | 插件唯一标识符，用于后续更新                               | string                                             | -         |      |\n| members          | Hull 内的元素，包括节点和边                                | string[]                                           | -         | ✓    |\n| concavity        | 凹度，数值越大凹度越小；默认为 Infinity 代表为 Convex Hull | number                                             | Infinity  |      |\n| corner           | 拐角类型，可选值为 `rounded` \\| `smooth` \\| `sharp`        | string                                             | `rounded` |      |\n| padding          | 内边距                                                     | number                                             | `10`      |      |\n| label            | 是否显示标签                                               | boolean                                            | true      |      |\n| labelPlacement   | 标签位置                                                   | `left` \\| `right` \\| `top` \\| `bottom` \\| `center` | `bottom`  |      |\n| labelBackground  | 是否显示背景                                               | boolean                                            | false     |      |\n| labelPadding     | 标签内边距                                                 | number \\| number[]                                 | 0         |      |\n| labelCloseToPath | 标签是否贴合轮廓                                           | boolean                                            | true      |      |\n| labelAutoRotate  | 标签是否跟随轮廓旋转，仅在 closeToPath 为 true 时生效      | boolean                                            | true      |      |\n| labelOffsetX     | x 轴偏移量                                                 | number                                             | 0         |      |\n| labelOffsetY     | y 轴偏移量                                                 | number                                             | 0         |      |\n| labelMaxWidth    | 文本的最大宽度，超出会自动省略                             | number                                             | 0         |      |\n\n完整的标签样式见[此链接](https://g6.antv.antgroup.com/manual/element/node/base-node#%E6%A0%87%E7%AD%BE%E6%A0%B7%E5%BC%8F)\n\n### concavity\n\nconcavity 属性用于控制 Hull 的凹度。当设置为 Infinity 时，生成的是凸包；否则会生成凹包。\n\n```js\n// 凸包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: Infinity, // 凸包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n\n// 凹包示例\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      concavity: 50, // 凹包\n      members: ['node-1', 'node-2'],\n    },\n  ],\n});\n```\n\n## 代码示例\n\n### 基础 Hull\n\n最简单的方式是直接使用预设配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'], // 需要包裹的节点 ID 列表\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n您可以根据需要自定义 Hull 的样式，例如调整颜色、透明度等属性。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'view',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2', 'node-3'],\n      stroke: '#ff000033', // 红色半透明边框\n      fill: '#7e3feb', // 浅紫色填充\n      fillOpacity: 0.2,\n      lineWidth: 2,\n      padding: 15, // 更大的内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n### 标签配置\n\n您可以配置标签的位置、背景、偏移量等属性，以增强可视化效果。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 300,\n  height: 150,\n  autoFit: 'center',\n  data: {\n    nodes: [\n      {\n        id: 'node-0',\n        data: { cluster: 'a' },\n        style: { x: 555, y: 151 },\n      },\n      {\n        id: 'node-1',\n        data: { cluster: 'a' },\n        style: { x: 532, y: 323 },\n      },\n      {\n        id: 'node-2',\n        data: { cluster: 'a' },\n        style: { x: 473, y: 227 },\n      },\n      {\n        id: 'node-3',\n        data: { cluster: 'a' },\n        style: { x: 349, y: 212 },\n      },\n      {\n        id: 'node-4',\n        data: { cluster: 'b' },\n        style: { x: 234, y: 201 },\n      },\n      {\n        id: 'node-5',\n        data: { cluster: 'b' },\n        style: { x: 338, y: 333 },\n      },\n      {\n        id: 'node-6',\n        data: { cluster: 'b' },\n        style: { x: 365, y: 91 },\n      },\n    ],\n    edges: [\n      {\n        source: 'node-0',\n        target: 'node-2',\n      },\n      {\n        source: 'node-1',\n        target: 'node-2',\n      },\n      {\n        source: 'node-2',\n        target: 'node-3',\n      },\n      {\n        source: 'node-3',\n        target: 'node-4',\n      },\n      {\n        source: 'node-3',\n        target: 'node-5',\n      },\n      {\n        source: 'node-3',\n        target: 'node-6',\n      },\n    ],\n  },\n  plugins: [\n    {\n      type: 'hull',\n      members: ['node-1', 'node-2'],\n      label: true, // 显示标签\n      labelText: 'hull-a',\n      labelPlacement: 'top', // 标签位置\n      labelBackground: true, // 显示标签背景\n      labelPadding: 5, // 标签内边距\n    },\n  ],\n  behaviors: ['zoom-canvas', 'drag-canvas'],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nfetch('https://assets.antv.antgroup.com/g6/collection.json')\n  .then((res) => res.json())\n  .then((data) => {\n    const groupedNodesByCluster = data.nodes.reduce((acc, node) => {\n      const cluster = node.data.cluster;\n      acc[cluster] ||= [];\n      acc[cluster].push(node.id);\n      return acc;\n    }, {});\n\n    const createStyle = (baseColor) => ({\n      fill: baseColor,\n      stroke: baseColor,\n      labelFill: '#fff',\n      labelPadding: 2,\n      labelBackgroundFill: baseColor,\n      labelBackgroundRadius: 5,\n    });\n\n    const graph = new Graph({\n      container: 'container',\n      data,\n      behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n      node: {\n        palette: { field: 'cluster' },\n      },\n      layout: {\n        type: 'force',\n        preventOverlap: true,\n        linkDistance: (d) => {\n          if (d.source === 'node0' || d.target === 'node0') {\n            return 200;\n          }\n          return 80;\n        },\n      },\n      plugins: [\n        {\n          key: 'hull-a',\n          type: 'hull',\n          members: groupedNodesByCluster['a'],\n          labelText: 'cluster-a',\n          ...createStyle('#1783FF'),\n        },\n        {\n          key: 'hull-b',\n          type: 'hull',\n          members: groupedNodesByCluster['b'],\n          labelText: 'cluster-b',\n          ...createStyle('#00C9C9'),\n        },\n        {\n          key: 'hull-c',\n          type: 'hull',\n          members: groupedNodesByCluster['c'],\n          labelText: 'cluster-c',\n          ...createStyle('#F08F56'),\n        },\n        {\n          key: 'hull-d',\n          type: 'hull',\n          members: groupedNodesByCluster['d'],\n          labelText: 'cluster-d',\n          ...createStyle('#D580FF'),\n        },\n      ],\n      autoFit: 'center',\n    });\n\n    graph.render();\n  });\n```\n\n```\n\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Legend.en.md) -->\n---\ntitle: Legend\norder: 11\n---\n\n## Overview\n\nThe Legend plugin is used to display classification information of elements in the graph, supporting the display of classification information for nodes, edges, and combos. Through the legend, users can quickly perceive the classification information of related elements in the graph and quickly locate elements by clicking on the corresponding legend items, improving user browsing efficiency.\n\n## Usage Scenarios\n\nThis plugin is mainly used for:\n\n- Quickly classifying elements through the legend\n- Quickly highlighting and locating corresponding elements through the legend\n\n## Basic Usage\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property          | Description                                                                                                                                                                                    | Type                                                                                        | Default Value | Required |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type              | Plugin type                                                                                                                                                                                    | string                                                                                      | `legend`      | ✓        |\n| key               | Unique identifier for the plugin, used for subsequent updates                                                                                                                                  | string                                                                                      | -             |          |\n| trigger           | How the legend item triggers the corresponding item highlight: <br/>- `hover`: Triggered when the mouse enters the legend item <br/>- `click`: Triggered when the mouse clicks the legend item | `hover` \\| `click`                                                                          | `hover`       |          |\n| position          | Relative position of the legend on the canvas, [optional values](#cardinalplacement)                                                                                                           | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`      |          |\n| container         | Container to which the legend is mounted, if not provided, it is mounted to the container where the Graph is located                                                                           | HTMLElement \\| string                                                                       | -             |          |\n| className         | Legend canvas class name, not effective when an external container is passed                                                                                                                   | string                                                                                      | -             |          |\n| containerStyle    | Style of the legend container, not effective when an external container is passed                                                                                                              | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| nodeField         | Node classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| edgeField         | Edge classification identifier                                                                                                                                                                 | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| comboField        | Combo classification identifier                                                                                                                                                                | string \\| (item: ElementDatum) => string                                                    | -             |          |\n| orientation       | Layout direction of legend items: <br/>- `horizontal`: Horizontal direction <br/>- `vertical`: Vertical direction                                                                              | `horizontal` \\| `vertical`                                                                  | 'horizontal'  |          |\n| layout            | Layout method: <br/>- `flex`: Flexible layout <br/>- `grid`: Grid layout                                                                                                                       | `flex` \\| `grid`                                                                            | `flex`        |          |\n| showTitle         | Whether to display the title                                                                                                                                                                   | boolean                                                                                     | false         |\n| titleText         | Title content                                                                                                                                                                                  | string                                                                                      | \"\"            |\n| x                 | Relative horizontal position of the legend on the canvas, higher priority than position                                                                                                        | number                                                                                      | -             |          |\n| y                 | Relative vertical position of the legend on the canvas, higher priority than position                                                                                                          | number                                                                                      | -             |          |\n| width             | Width of the legend                                                                                                                                                                            | number                                                                                      | 240           |          |\n| height            | Height of the legend                                                                                                                                                                           | number                                                                                      | 160           |          |\n| itemSpacing       | Spacing between the text of the legend item and the corresponding marker                                                                                                                       | number                                                                                      | 4             |          |\n| rowPadding        | Spacing between each row in the legend                                                                                                                                                         | number                                                                                      | 10            |          |\n| colPadding        | Spacing between each column in the legend                                                                                                                                                      | number                                                                                      | 10            |          |\n| itemMarkerSize    | Size of the legend item marker                                                                                                                                                                 | number                                                                                      | 16            |          |\n| itemLabelFontSize | Font size of the legend item text                                                                                                                                                              | number                                                                                      | 16            |          |\n| gridCol           | Maximum number of columns allowed for legend items when width permits                                                                                                                          | number                                                                                      | -             |          |\n| gridRow           | Maximum number of rows allowed for legend items when height permits                                                                                                                            | number                                                                                      | -             |          |\n\n### CardinalPlacement\n\nThe `position` property supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side near the top\n- `'left-bottom'`: Left side near the bottom\n- `'right-top'`: Right side near the top\n- `'right-bottom'`: Right side near the bottom\n\n## Code Examples\n\n### Basic Legend\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend', // Plugin type is legend\n      nodeField: 'cluster', // Array field name for node grouping\n      edgeField: 'cluster', // Array field name for edge grouping\n    },\n  ],\n});\n```\n\n### Custom Legend Position\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // You can quickly specify the position through position\n      // position: \"top-left\",\n      // Or you can more flexibly control the position of the legend through x, y\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### Custom Legend Item Layout\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // Control to display only one row\n      gridRow: 1,\n      // Control to display 10 columns in one row, a page button will be displayed when the column width is insufficient\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Setting orientation is ineffective?\n\n`orientation` mainly controls the direction of the layout, and the specific display of **multiple columns in one row** or **multiple rows in one column** is mainly controlled by `gridRow` and `gridCol`. For example, if you want it to look like a vertical legend item, you can configure it like this:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // Control to display 1 column in one row\n      gridCol:1,\n      // Control to display up to 20 rows\n      gridRow: 20,\n    },\n  ],\n```\n\nThis way, it becomes a legend with only one column, conforming to the visual vertical arrangement.\n\n### 2. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  data,\n  // Other configurations...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// Update legend position\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Legend.zh.md) -->\n---\ntitle: 图例 Legend\norder: 11\n---\n\n## 概述\n\n图例（Legend）插件用于展示图中元素的分类信息，支持节点、边、组合的分类信息展示。通过图例，用户可以快速感知到图中相关元素的分类信息，也可以通过点击对应图例项来快速定位到元素，提高用户的浏览效率。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 通过图例快速对元素进行分类\n- 通过图例快速高亮定位到对应元素\n\n## 基本用法\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性              | 描述                                                                                                  | 类型                                                                                        | 默认值       | 必选 |\n| ----------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type              | 插件类型                                                                                              | string                                                                                      | `legend`     | ✓    |\n| key               | 插件唯一标识符，用于后续更新                                                                          | string                                                                                      | -            |      |\n| trigger           | 图例项触发对应项高亮的方式：<br/>- `hover`：鼠标移入图例项时触发 <br/>- `click`：鼠标点击图例项时触发 | `hover` \\| `click`                                                                          | `hover`      |      |\n| position          | 图例在画布中的相对位置，[可选值](#cardinalplacement)                                                  | [CardinalPlacement](#cardinalplacement)                                                     | `bottom`     |      |\n| container         | 图例挂载的容器，无则挂载到 Graph 所在容器                                                             | HTMLElement \\| string                                                                       | -            |      |\n| className         | 图例画布类名，传入外置容器时不生效                                                                    | string                                                                                      | -            |      |\n| containerStyle    | 图例的容器样式，传入外置容器时不生效                                                                  | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| nodeField         | 节点分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| edgeField         | 边分类标识                                                                                            | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| comboField        | 组合分类标识                                                                                          | string \\| (item: ElementDatum) => string                                                    | -            |      |\n| orientation       | 图例项的布局方向：<br/>- `horizontal`：水平方向 <br/>- `vertical`：垂直方向                           | `horizontal` \\| `vertical`                                                                  | 'horizontal' |      |\n| layout            | 布局方式：<br/>- `flex`：弹性布局 <br/>- `grid`：网格布局                                             | `flex` \\| `grid`                                                                            | `flex`       |      |\n| showTitle         | 是否显示标题                                                                                          | boolean                                                                                     | false        |\n| titleText         | 标题内容                                                                                              | string                                                                                      | \"\"           |\n| x                 | 图例在画布中的相对的横向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| y                 | 图例在画布中的相对的纵向位置，优先级高于position                                                      | number                                                                                      | -            |      |\n| width             | 图例的宽度                                                                                            | number                                                                                      | 240          |      |\n| height            | 图例的高度                                                                                            | number                                                                                      | 160          |      |\n| itemSpacing       | 图例项的文本和对应标记之间的间距                                                                      | number                                                                                      | 4            |      |\n| rowPadding        | 图例中每行之间的间距                                                                                  | number                                                                                      | 10           |      |\n| colPadding        | 图例中每列之间的间距                                                                                  | number                                                                                      | 10           |      |\n| itemMarkerSize    | 图例项标记的大小                                                                                      | number                                                                                      | 16           |      |\n| itemLabelFontSize | 图例项文本的字体大小                                                                                  | number                                                                                      | 16           |      |\n| gridCol           | 图例项在宽度允许情况下的最大列数                                                                      | number                                                                                      | -            |      |\n| gridRow           | 图例项在高度允许情况下的最大行数                                                                      | number                                                                                      | -            |      |\n\n### CardinalPlacement\n\n`position` 属性支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n## 代码示例\n\n### 基础图例\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend', // 插件类型为 legend\n      nodeField: 'cluster', // 用于节点分组的数组字段名称\n      edgeField: 'cluster', // 用于边分组的数组字段名称\n    },\n  ],\n});\n```\n\n### 自定义图例位置\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      // 可以通过 position 快捷的来指定位置\n      // position: \"top-left\",\n      // 也可以通过x,y来更加灵活的控制图例的位置\n      x: 20,\n      y: 20,\n    },\n  ],\n});\n```\n\n### 自定义图例项布局\n\n```js\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n  ],\n  edges: [{ source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } }],\n};\n\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: 'flex',\n      // 控制只显示一行\n      gridRow: 1,\n      // 控制一行显示10列，当列宽不足时会显示翻页按钮\n      gridCol: 10,\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 设置了 orientation 无效？\n\n`orientation`主要控制布局的方向，具体展示**一行多列**还是**一列多行**，主要通过 `gridRow` 以及`gridCol`来控制，例如想要看起来像是竖向的图例项，则可以通过这样配置:\n\n```js\n   plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n      layout: \"flex\",\n      // 控制一行显示1列\n      gridCol:1,\n      // 控制显示最多20行\n      gridRow: 20,\n    },\n  ],\n```\n\n这样就变成了只有一列的图例，符合视觉上的竖向排列。\n\n### 2. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  data,\n  // 其他配置...\n  plugins: [\n    {\n      type: 'legend',\n      key: 'my-legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\n// 更新图例位置\ngraph.updatePlugin({\n  key: 'my-legend',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node-1', type: 'circle', data: { cluster: 'node-type1' } },\n    { id: 'node-2', type: 'rect', data: { cluster: 'node-type2' } },\n    { id: 'node-3', type: 'triangle', data: { cluster: 'node-type3' } },\n    { id: 'node-4', type: 'diamond', data: { cluster: 'node-type4' } },\n  ],\n  edges: [\n    { source: 'node-1', target: 'node-2', data: { cluster: 'edge-type1' } },\n    { source: 'node-1', target: 'node-4', data: { cluster: 'edge-type2' } },\n    { source: 'node-3', target: 'node-4' },\n    { source: 'node-2', target: 'node-4', data: { cluster: 'edge-type3' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  node: {\n    style: { size: 32 },\n    palette: {\n      field: 'cluster',\n    },\n  },\n  layout: {\n    type: 'force',\n  },\n  plugins: [\n    {\n      type: 'legend',\n      nodeField: 'cluster',\n      edgeField: 'cluster',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Minimap.en.md) -->\n---\ntitle: Minimap\norder: 12\n---\n\n## Overview\n\nThe main function of the Minimap is to provide users with an overall layout of the current graph content in the form of a thumbnail, allowing quick positioning of graph operation locations.\n\n**⚠️ Note**, The Minimap plugin is currently incompatible with React Node rendering mechanism. When using Minimap functionality, it is recommended to implement node rendering through [built-in nodes](/en/manual/element/node/overview) or [custom nodes](/en/manual/element/node/custom-node).\n\n## Usage Scenarios\n\nThe Minimap plugin is mainly applicable to the following scenarios:\n\n- Providing a global view for quick area positioning\n- Navigation and interaction assistance, allowing quick positioning to the target location through the minimap\n\n## Basic Usage\n\nBelow is a simple example of initializing the Minimap plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                             | Type                                                                                                                                                                                                   | Default Value  | Required |\n| -------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | -------- |\n| type           | Plugin type                                                                                                             | string                                                                                                                                                                                                 | `minimap`      | ✓        |\n| key            | Unique identifier for the plugin, used for subsequent updates                                                           | string                                                                                                                                                                                                 | -              |          |\n| className      | Class name of the thumbnail canvas, not effective when an external container is passed                                  | string                                                                                                                                                                                                 |                |          |\n| container      | Container to which the thumbnail is mounted, if not provided, it is mounted to the container where the Graph is located | HTMLElement \\| string                                                                                                                                                                                  |                |          |\n| containerStyle | Style of the thumbnail container, not effective when an external container is passed                                    | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| delay          | Delay update time (milliseconds) for performance optimization                                                           | number                                                                                                                                                                                                 | 128            |          |\n| filter         | Filter for filtering out elements that do not need to be displayed                                                      | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |          |\n| maskStyle      | Style of the mask                                                                                                       | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |          |\n| padding        | Padding                                                                                                                 | number \\| number[]                                                                                                                                                                                     | 10             |          |\n| position       | Position of the thumbnail relative to the canvas                                                                        | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |          |\n| renderer       | Renderer, default is Canvas renderer                                                                                    | IRenderer                                                                                                                                                                                              |                |          |\n| shape          | Method for generating element thumbnails                                                                                | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |          |\n| size           | Width and height                                                                                                        | [number, number]                                                                                                                                                                                       | [240, 160]     |          |\n\n### containerStyle\n\nSet the style of the thumbnail container, not effective when an external container is passed. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value    | Required |\n| ------------ | -------------------------- | ------ | ---------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd` | ✓        |\n| background   | Container background color | string | `#fff`           | ✓        |\n| borderRadius | Container border radius    | string | -                |          |\n| boxShadow    | Container shadow effect    | string | -                |          |\n| padding      | Container padding          | string | -                |          |\n| margin       | Container margin           | string | -                |          |\n| opacity      | Opacity                    | string | -                |          |\n\n### maskStyle\n\nSpecify the style of the mask. Inherits all CSS style properties (CSSStyleDeclaration), and you can use any valid CSS property to configure the style of the thumbnail container.\n\nBelow are some common configurations:\n\n| Property     | Description                | Type   | Default Value        | Required |\n| ------------ | -------------------------- | ------ | -------------------- | -------- |\n| border       | Container border style     | string | `1px solid #ddd`     | ✓        |\n| background   | Container background color | string | `rgba(0, 0, 0, 0.1)` | ✓        |\n| borderRadius | Container border radius    | string | -                    | -        |\n| boxShadow    | Container shadow effect    | string | -                    | -        |\n| padding      | Container padding          | string | -                    | -        |\n| margin       | Container margin           | string | -                    | -        |\n| opacity      | Opacity                    | string | -                    | -        |\n\n### position\n\nPosition of the thumbnail relative to the canvas, the thumbnail position configuration supports array form and preset value form.\n\n- Array form [number, number] represents relative position, with a value range of 0~1. For example: [0, 0] represents the top left corner of the canvas, [1, 1] represents the bottom right corner of the canvas.\n- Preset value form is used to set the fixed position of the thumbnail on the canvas, optional values are: `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // Modify the position of the minimap here\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\nSet the width and height of the minimap, default value is [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // Other configurations\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // Set the width and height of the minimap\n    }\n  ]\n})\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## Practical Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Minimap.zh.md) -->\n---\ntitle: 小地图 Minimap\norder: 12\n---\n\n## 概述\n\nMinimap（小地图）的主要作用是为用户提供以缩略图形式展示当前图内容的整体布局，可以快速定位图操作位置。\n\n**⚠️ 需要注意**，Minimap 插件当前不兼容 React Node 渲染机制，在需要使用 Minimap 功能的场景中，建议通过 [内置节点](/manual/element/node/overview) 或者[自定义节点](/manual/element/node/custom-node) 实现节点渲染。\n\n## 使用场景\n\nMinimap（小地图）插件主要适用于以下场景：\n\n- 提供全局视野，快速定位区域\n- 导航与交互辅助，通过操作小地图可以快速定位到目标位置\n\n## 基本用法\n\n以下是一个简单的 Minimap 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'minimap',\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/minimap.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                        | 类型                                                                                                                                                                                                   | 默认值         | 必选 |\n| -------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ---- |\n| type           | 插件类型                                    | string                                                                                                                                                                                                 | `minimap`      | ✓    |\n| key            | 插件唯一标识符，用于后续更新                | string                                                                                                                                                                                                 | -              |      |\n| className      | 缩略图画布类名，传入外置容器时不生效        | string                                                                                                                                                                                                 |                |      |\n| container      | 缩略图挂载的容器，无则挂载到 Graph 所在容器 | HTMLElement \\| string                                                                                                                                                                                  |                |      |\n| containerStyle | 缩略图的容器样式，传入外置容器时不生效      | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| delay          | 延迟更新时间(毫秒)，用于性能优化            | number                                                                                                                                                                                                 | 128            |      |\n| filter         | 过滤器，用于过滤不必显示的元素              | (id: string, elementType: `node` \\| `edge` \\| `combo`) => boolean                                                                                                                                      |                |      |\n| maskStyle      | 遮罩的样式                                  | Partial\\<CSSStyleDeclaration\\>                                                                                                                                                                         |                |      |\n| padding        | 内边距                                      | number \\| number[]                                                                                                                                                                                     | 10             |      |\n| position       | 缩略图相对于画布的位置                      | [number, number] \\| `left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center` | `right-bottom` |      |\n| renderer       | 渲染器，默认使用 Canvas 渲染器              | IRenderer                                                                                                                                                                                              |                |      |\n| shape          | 元素缩略图形的生成方法                      | `key` \\| ((id: string, elementType: `node` \\| `edge` \\| `combo`, element: DisplayObject) => DisplayObject)                                                                                             | `key`          |      |\n| size           | 宽度和高度                                  | [number, number]                                                                                                                                                                                       | [240, 160]     |      |\n\n### containerStyle\n\n设置缩略图的容器样式，传入外置容器时不生效。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值           | 必选 |\n| ------------ | ------------ | ------ | ---------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd` | ✓    |\n| background   | 容器背景颜色 | string | `#fff`           | ✓    |\n| borderRadius | 容器圆角大小 | string | -                |      |\n| boxShadow    | 容器阴影效果 | string | -                |      |\n| padding      | 容器内边距   | string | -                |      |\n| margin       | 容器外边距   | string | -                |      |\n| opacity      | 透明度       | string | -                |      |\n\n### maskStyle\n\n指定遮罩的样式。继承了所有 CSS 样式属性（CSSStyleDeclaration），你可以使用任何合法的 CSS 属性来配置缩略图容器的样式。\n\n以下是一些常用配置：\n\n| 属性         | 描述         | 类型   | 默认值               | 必选 |\n| ------------ | ------------ | ------ | -------------------- | ---- |\n| border       | 容器边框样式 | string | `1px solid #ddd`     | ✓    |\n| background   | 容器背景颜色 | string | `rgba(0, 0, 0, 0.1)` | ✓    |\n| borderRadius | 容器圆角大小 | string | -                    | -    |\n| boxShadow    | 容器阴影效果 | string | -                    | -    |\n| padding      | 容器内边距   | string | -                    | -    |\n| margin       | 容器外边距   | string | -                    | -    |\n| opacity      | 透明度       | string | -                    | -    |\n\n### position\n\n缩略图相对于画布的位置，缩略图位置配置支持数组形式和预设值形式。\n\n- 数组形式 [number, number] 表示相对位置，取值范围为 0~1。举例：[0, 0] 代表画布左上角，[1, 1] 代表画布右下角。\n- 预设值形式用于设定缩略图所在画布固定方位，可选值有：`left` \\| `right` \\| `top` \\| `bottom` \\| `left-top` \\| `left-bottom` \\| `right-top` \\| `right-bottom` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right` \\| `center`\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      position: 'right-bottom'  // 这里进行修改minimap所在位置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [240, 160], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n### size\n\n设置小地图的宽度和高度，默认值为 [240, 160]\n\n```js\nconst graph = new Graph({\n  plugins:[\n    {\n      ... // 其他配置\n      key: 'minimap',\n      type: 'minimap',\n      size: [200, 120]  // minimap的宽度和高度的设置\n    }\n  ]\n})\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 300,\n  data: {\n    nodes: Array.from({ length: 50 }).map((_, i) => ({\n      id: `node-${i}`,\n      x: Math.random() * 500,\n      y: Math.random() * 300,\n    })),\n    edges: Array.from({ length: 100 }).map((_, i) => ({\n      id: `edge-${i}`,\n      source: `node-${Math.floor(Math.random() * 50)}`,\n      target: `node-${Math.floor(Math.random() * 50)}`,\n    })),\n  },\n  node: { style: { fill: '#7e3feb' } },\n  edge: { style: { stroke: '#8b9baf' } },\n  layout: { type: 'force' },\n  behaviors: ['drag-canvas'],\n  plugins: [{ type: 'minimap', key: 'minimap', size: [200, 120], position: 'right-bottom' }],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 20 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'minimap',\n      size: [240, 160],\n    },\n  ],\n  node: {\n    palette: 'spectral',\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/overview.en.md) -->\n---\ntitle: Plugin Overview\norder: 0\n---\n\n## What is a Plugin\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\nA Plugin is the most flexible extension mechanism in G6, allowing users to extend G6's functionality, such as adding graphical components to the canvas or implementing undo/redo features.\n\nMost customization needs can be achieved through plugins. G6 comes with some built-in plugins, such as: [Tooltip](/en/manual/plugin/tooltip), [Grid](/en/manual/plugin/grid-line), [History](/en/manual/plugin/history).\n\n## Built-in Plugins\n\nG6 provides a rich set of built-in plugins covering various common functional scenarios:\n\n| Category                     | Plugin Name                                                                                         | Registration Type  | Description                                                            |\n| ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------- |\n| **Visual Style Enhancement** |                                                                                                     |                    |                                                                        |\n|                              | [Grid Line](/en/manual/plugin/grid-line)                                                            | `grid-line`        | Displays grid reference lines on the canvas                            |\n|                              | [Background](/en/manual/plugin/background)                                                          | `background`       | Adds background images or colors to the canvas                         |\n|                              | [Watermark](/en/manual/plugin/watermark)                                                            | `watermark`        | Adds a watermark to the canvas to protect copyright                    |\n|                              | [Hull](/en/manual/plugin/hull)                                                                      | `hull`             | Creates an outline for a specified set of nodes                        |\n|                              | [Bubble Sets](/en/manual/plugin/bubble-sets)                                                        | `bubble-sets`      | Creates smooth bubble-like element outlines                            |\n|                              | [Snapline](/en/manual/plugin/snapline)                                                              | `snapline`         | Displays alignment reference lines when dragging elements              |\n| **Navigation and Overview**  |                                                                                                     |                    |                                                                        |\n|                              | [Minimap](/en/manual/plugin/minimap)                                                                | `minimap`          | Displays a thumbnail preview of the graph, supporting navigation       |\n|                              | [Fullscreen](/en/manual/plugin/fullscreen)                                                          | `fullscreen`       | Supports full-screen display and exit for charts                       |\n|                              | [Timebar](/en/manual/plugin/timebar)                                                                | `timebar`          | Provides filtering and playback control for temporal data              |\n| **Interactive Controls**     |                                                                                                     |                    |                                                                        |\n|                              | [Toolbar](/en/manual/plugin/toolbar)                                                                | `toolbar`          | Provides a collection of common operation buttons                      |\n|                              | [Context Menu](/en/manual/plugin/contextmenu)                                                       | `contextmenu`      | Displays a menu of selectable operations on right-click                |\n|                              | [Tooltip](/en/manual/plugin/tooltip)                                                                | `tooltip`          | Displays detailed information about elements on hover                  |\n|                              | [Legend](/en/manual/plugin/legend)                                                                  | `legend`           | Displays categories and corresponding style descriptions of chart data |\n| **Data Exploration**         |                                                                                                     |                    |                                                                        |\n|                              | [Fisheye](/en/manual/plugin/fisheye)                                                                | `fisheye`          | Provides a focus + context exploration experience                      |\n|                              | [Edge Filter Lens](/en/manual/plugin/edge-filter-lens)                                              | `edge-filter-lens` | Filters and displays edges within a specified area                     |\n|                              | [Edge Bundling](/en/manual/plugin/edge-bundling)                                                    | `edge-bundling`    | Bundles edges with similar paths together to reduce visual clutter     |\n| **Advanced Features**        |                                                                                                     |                    |                                                                        |\n|                              | [History](/en/manual/plugin/history)                                                                | `history`          | Supports undo/redo operations                                          |\n|                              | [Camera Setting](/enhttps://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | Configures camera parameters in a 3D scene                             |\n\nFor detailed configuration of each plugin, refer to the [Built-in Plugin Documentation](/en/manual/plugin/grid-line).\n\n## Configuration Methods\n\n### Basic Configuration\n\nSpecify the required plugins through the `plugins` array when initializing the graph instance:\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // Other configurations...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### Configuring Plugin Parameters\n\nFor plugins that require custom parameters, you can configure properties using the `object` form:\n\n```javascript {5-9}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // Specify a key for the plugin for future updates\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### Dynamically Updating Plugins\n\nG6 supports dynamic management of plugins during the runtime of the graph instance to meet complex interaction needs:\n\nUse the [getPlugins](/en/api/plugin#graphgetplugins) method to get the current list of plugins:\n\n```javascript\n// Get the list of plugins\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\nYou can adjust plugins using the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method:\n\n```javascript\n// Add a new plugin\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// Remove a plugin\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\nYou can update the configuration of a plugin using the [updatePlugin](/en/api/plugin#graphupdatepluginplugin) method:\n\n```javascript {6,14}\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>Node: ${e.target.id}</div>`,\n    },\n  ],\n});\n\n// Update a single plugin\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>Updated content: ${e.target.id}</div>`,\n});\n```\n\n:::warning{title=Note}\nWhen using the `updatePlugin` method, you need to specify a unique `key` for the plugin during initialization.\n:::\n\n### Uninstalling Plugins\n\nUse the [setPlugins](/en/api/plugin#graphsetpluginsplugins) method to uninstall plugins by setting the plugin configuration list to empty:\n\n```javascript\n// Uninstall all plugins\ngraph.setPlugins([]);\n```\n\n### Calling Plugin Methods\n\nSome plugins provide API methods for users to call, such as the `history` plugin providing `undo` and `redo` methods, allowing users to implement undo and redo operations by calling these methods.\n\nTo call these methods, you need to first get the plugin instance, which can be obtained through the [getPluginInstance](/en/api/plugin#graphgetplugininstancekey) method:\n\n```javascript\n// Configure the plugin\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// Get the plugin instance\nconst history = graph.getPluginInstance('my-history');\n\n// Call plugin methods\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=Note}\nThe `graph.getPluginInstance` method takes the plugin key value as a parameter, so if you need to get the plugin instance, you need to configure the corresponding plugin in the form of an `object` and pass in the `key` value.\n:::\n\nFor more plugin-related APIs, please refer to the [Plugin API Documentation](/en/api/plugin).\n\n## Custom Plugins\n\nWhen built-in plugins cannot meet your needs, you can:\n\n- Inherit and extend existing plugins\n- Create brand new custom plugins\n\nCustom plugins need to be registered before use. For detailed tutorials, please refer to the [Custom Plugin](/en/manual/plugin/custom-plugin) documentation.\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// Register custom plugin\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// Use custom plugin\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\nBy reasonably combining and configuring plugins, you can build graph visualization applications with rich features and excellent interactive experiences.\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/overview.zh.md) -->\n---\ntitle: 插件总览\norder: 0\n---\n\n## 什么是插件\n\n<image width=\"200px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sa3jRqp83K4AAAAAAAAAAAAADmJ7AQ/original\" />\n\n插件(Plugin)是 G6 中最灵活的扩展机制，用户可以通过插件来扩展 G6 的功能，例如在画布中额外挂载图形组件、实现撤销重做等功能。\n\n绝大多数的定制需求都可以通过插件来实现，G6 内置了一些常用的插件，例如：[Tooltip](/manual/plugin/tooltip)、[Grid](/manual/plugin/grid-line)、[History](/manual/plugin/history)。\n\n## 内置插件\n\nG6 提供了丰富的内置插件，涵盖多种常见功能场景：\n\n| 分类             | 插件名称                                                                                   | 注册类型           | 功能描述                               |\n| ---------------- | ------------------------------------------------------------------------------------------ | ------------------ | -------------------------------------- |\n| **视觉样式增强** |                                                                                            |                    |                                        |\n|                  | [网格线](/manual/plugin/grid-line)                                                         | `grid-line`        | 在画布上显示网格参考线                 |\n|                  | [背景](/manual/plugin/background)                                                          | `background`       | 为画布添加背景图片或颜色               |\n|                  | [水印](/manual/plugin/watermark)                                                           | `watermark`        | 为画布添加水印，保护版权               |\n|                  | [轮廓包围](/manual/plugin/hull)                                                            | `hull`             | 为指定节点集合创建轮廓                 |\n|                  | [气泡集](/manual/plugin/bubble-sets)                                                       | `bubble-sets`      | 创建平滑气泡状的元素集合轮廓           |\n|                  | [对齐线](/manual/plugin/snapline)                                                          | `snapline`         | 拖动元素时显示对齐参考线               |\n| **导航与概览**   |                                                                                            |                    |                                        |\n|                  | [缩略图](/manual/plugin/minimap)                                                           | `minimap`          | 显示图的缩略预览，支持导航             |\n|                  | [全屏](/manual/plugin/fullscreen)                                                          | `fullscreen`       | 支持图表全屏显示和退出                 |\n|                  | [时间轴](/manual/plugin/timebar)                                                           | `timebar`          | 提供时序数据的筛选和播放控制           |\n| **交互控件**     |                                                                                            |                    |                                        |\n|                  | [工具栏](/manual/plugin/toolbar)                                                           | `toolbar`          | 提供常用操作按钮集合                   |\n|                  | [上下文菜单](/manual/plugin/contextmenu)                                                   | `contextmenu`      | 右键点击时显示可选操作菜单             |\n|                  | [提示框](/manual/plugin/tooltip)                                                           | `tooltip`          | 悬停时显示元素详细信息                 |\n|                  | [图例](/manual/plugin/legend)                                                              | `legend`           | 显示图表数据的类别和对应样式说明       |\n| **数据探索**     |                                                                                            |                    |                                        |\n|                  | [鱼眼放大镜](/manual/plugin/fisheye)                                                       | `fisheye`          | 提供焦点+上下文的探索体验              |\n|                  | [边过滤镜](/manual/plugin/edge-filter-lens)                                                | `edge-filter-lens` | 在指定区域内筛选显示边                 |\n|                  | [边绑定](/manual/plugin/edge-bundling)                                                     | `edge-bundling`    | 将相似路径的边捆绑在一起，减少视觉混乱 |\n| **高级功能**     |                                                                                            |                    |                                        |\n|                  | [历史记录](/manual/plugin/history)                                                         | `history`          | 支持撤销/重做操作                      |\n|                  | [相机设置](https://github.com/antvis/G6/blob/v5/packages/g6/src/plugins/camera-setting.ts) | `camera-setting`   | 配置3D场景下的相机参数                 |\n\n各插件的详细配置可参考 [内置插件文档](/manual/plugin/grid-line)。\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `plugins` 数组指定需要的插件：\n\n```javascript {}5\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  plugins: ['grid', 'minimap', 'tooltip'],\n});\n```\n\n### 配置插件参数\n\n对于需要自定义参数的插件，可以使用 `object` 形式配置属性：\n\n```javascript {5-9}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    'grid',\n    {\n      type: 'tooltip',\n      key: 'my-tooltip', // 为插件指定key，便于后续更新\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n```\n\n### 动态更新插件\n\nG6 支持在图实例运行期间动态管理插件，满足复杂交互需求：\n\n通过 [getPlugins](/api/plugin#graphgetplugins) 方法获取当前插件列表：\n\n```javascript\n// 获取插件列表\nconst plugins = graph.getPlugins();\n// console.log(plugins) 👉 ['minimap', 'grid']\n```\n\n可以通过 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法调整插件：\n\n```javascript\n// 添加新插件\ngraph.setPlugins((plugins) => [...plugins, 'minimap']);\n\n// 移除插件\ngraph.setPlugins((plugins) => plugins.filter((p) => p !== 'grid'));\n```\n\n可以通过 [updatePlugin](/api/plugin#graphupdatepluginplugin) 方法更新插件的配置：\n\n```javascript {6,14}\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n      key: 'my-tooltip',\n      getContent: (e) => `<div>节点：${e.target.id}</div>`,\n    },\n  ],\n});\n\n// 更新单个插件\ngraph.updatePlugin({\n  key: 'my-tooltip',\n  getContent: (e) => `<div>更新的内容：${e.target.id}</div>`,\n});\n```\n\n:::warning{title=注意}\n使用 `updatePlugin` 方法时，需要在初始化时为插件指定唯一的 `key`。\n:::\n\n### 卸载插件\n\n使用 [setPlugins](/api/plugin#graphsetpluginsplugins) 方法同样可以卸载插件，将插件配置列表置为空即可：\n\n```javascript\n// 卸载所有插件\ngraph.setPlugins([]);\n```\n\n### 调用插件方法\n\n一些插件提供了可供用户调用的 API 方法，例如 `history` 插件提供了 `undo` 和 `redo` 方法，用户可以通过调用这些方法来实现撤销和重做操作。\n\n要调用这些方法，需要先获取到插件实例，可通过 [getPluginInstance](/api/plugin#graphgetplugininstancekey) 方法获取：\n\n```javascript\n// 配置插件\nconst graph = new Graph({\n  plugins: [{ type: 'history', key: 'my-history' }],\n});\n\n// 获取插件实例\nconst history = graph.getPluginInstance('my-history');\n\n// 调用插件方法\nhistory.undo();\nhistory.redo();\n```\n\n:::warning{title=注意}\n`graph.getPluginInstance` 方法接收插件 key 值作为参数，因此如果需要获取插件实例，需要将对应插件配置为 `object` 的形式，并传入 `key` 值。\n:::\n\n更多与插件相关的 API 请参考 [插件 API 文档](/api/plugin)。\n\n## 自定义插件\n\n当内置插件无法满足需求时，你可以：\n\n- 继承和扩展现有插件\n- 创建全新的自定义插件\n\n自定义插件需要先注册后使用。详细教程请参考 [自定义插件](/manual/plugin/custom-plugin) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomPlugin } from './my-custom-plugin';\n\n// 注册自定义插件\nregister(ExtensionCategory.PLUGIN, 'my-custom-plugin', MyCustomPlugin);\n\n// 使用自定义插件\nconst graph = new Graph({\n  plugins: ['my-custom-plugin'],\n});\n```\n\n通过合理组合和配置插件，你可以构建出功能丰富、交互体验出色的图可视化应用。\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Snapline.en.md) -->\n---\ntitle: Snapline\norder: 13\n---\n\n## Overview\n\nThe Snapline plugin provides intelligent alignment guidelines for the canvas, automatically displaying guide lines when moving nodes and supporting automatic snapping. It helps users achieve precise alignment and is an important tool for improving efficiency and accuracy in graphic editing.\n\n## Use Cases\n\nThe Snapline plugin is mainly suitable for the following scenarios:\n\n- When manually adjusting node positions and precise alignment with other nodes is needed\n- When dragging multiple nodes while maintaining their alignment relationships\n- When creating standardized graphic layouts to ensure consistency in node spacing and positioning\n- When improving node layout efficiency through automatic snapping functionality\n\n## Basic Usage\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // Specify unique identifier\n      tolerance: 5, // Alignment snap threshold\n      offset: 20, // Guide line extension distance\n      autoSnap: true, // Enable automatic snapping\n    },\n  ],\n});\n```\n\n## Live Demo\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## Options\n\n| Property            | Description                                                                                                                                                                                            | Type                                      | Default                 | Required |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | ----------------------- | -------- |\n| type                | Plugin type                                                                                                                                                                                            | string                                    | `'snapline'`            | ✓        |\n| key                 | Plugin unique identifier                                                                                                                                                                               | string                                    | -                       |          |\n| tolerance           | The alignment accuracy, that is, when the distance between the moved node and the target position is less than tolerance, the alignment line is displayed                                              | number                                    | 5                       |          |\n| offset              | The extension distance of the snapline                                                                                                                                                                 | number                                    | 20                      |          |\n| autoSnap            | Whether to enable automatic snapping                                                                                                                                                                   | boolean                                   | true                    |          |\n| shape               | Specifies which shape on the element to use as the reference shape:<br/>- `'key'`: uses the key shape of the element as the reference shape<br/>- `Function`: receives the element and returns a shape | string \\| ((node: Node) => DisplayObject) | `'key'`                 |          |\n| verticalLineStyle   | Vertical snapline style                                                                                                                                                                                | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| horizontalLineStyle | Horizontal snapline style                                                                                                                                                                              | BaseStyleProps                            | `{ stroke: '#1783FF' }` |          |\n| filter              | Filter nodes that do not need to participate in alignment                                                                                                                                              | (node: Node) => boolean                   | `() => true`            |          |\n\n### shape\n\nThe `shape` property specifies the reference shape for elements and supports the following configurations:\n\n```js\n// Use the key shape as reference\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// Use custom function to return reference shape\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### Snapline Style Configuration\n\n| Property       | Description             | Type                                     | Default     |\n| -------------- | ----------------------- | ---------------------------------------- | ----------- |\n| stroke         | Line color              | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | Overall opacity         | number \\| string                         | 1           |\n| strokeOpacity  | Stroke opacity          | number \\| string                         | 1           |\n| lineWidth      | Line width              | number \\| string                         | 1           |\n| lineCap        | Line end style          | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | Line join style         | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | Dash line configuration | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | Dash line offset        | number                                   | 0           |\n| shadowBlur     | Shadow blur             | number                                   | 0           |\n| shadowColor    | Shadow color            | string                                   | -           |\n| shadowOffsetX  | Shadow X offset         | number                                   | 0           |\n| shadowOffsetY  | Shadow Y offset         | number                                   | 0           |\n| cursor         | Mouse cursor style      | string                                   | `'default'` |\n| zIndex         | Rendering level         | number                                   | 0           |\n\nExample configuration:\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## Code Examples\n\n### Basic Snapline\n\nThe simplest usage:\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### Custom Configuration\n\nYou can customize the snapline behavior according to your needs:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // Larger snap range\n      offset: 30, // Longer extension lines\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // Filter nodes by id, exclude from alignment\n    },\n  ],\n});\n```\n\n## Live Example\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Snapline.zh.md) -->\n---\ntitle: 对齐线 Snapline\norder: 13\n---\n\n## 概述\n\n对齐线插件为画布提供智能对齐参考线，在移动节点时自动显示辅助线并支持自动吸附，帮助用户实现精确对齐，是图形编辑中提升效率和精确度的重要工具。\n\n## 使用场景\n\n对齐线插件主要适用于以下场景：\n\n- 手动调整节点位置时,需要与其他节点精确对齐\n- 拖拽移动多个节点时,保持它们之间的对齐关系\n- 制作规范的图形布局时,确保节点间距和位置的一致性\n- 通过自动吸附功能提高节点排版效率\n\n## 基本用法\n\n以下是一个简单的 Snapline 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'my-snapline', // 指定唯一标识符\n      tolerance: 5, // 对齐吸附阈值\n      offset: 20, // 对齐线延伸距离\n      autoSnap: true, // 启用自动吸附\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/snapline.md\"></embed>\n\n## 配置项\n\n| 属性                | 描述                                                                                                                    | 类型                                                                                                                            | 默认值                  | 必选 |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type                | 插件类型                                                                                                                | string                                                                                                                          | `'snapline'`            | ✓    |\n| key                 | 插件唯一标识符                                                                                                          | string                                                                                                                          | -                       |      |\n| tolerance           | 对齐精度，即触发对齐的距离阈值                                                                                          | number                                                                                                                          | 5                       |      |\n| offset              | 对齐线头尾的延伸距离                                                                                                    | number                                                                                                                          | 20                      |      |\n| autoSnap            | 是否启用自动吸附                                                                                                        | boolean                                                                                                                         | true                    |      |\n| shape               | 指定元素的参照图形：<br/>- `'key'`: 使用元素的主图形作为参照图形<br/>- `Function`: 传入函数时接收元素对象，返回一个图形 | string \\| ((node: Node) => DisplayObject)                                                                                       | `'key'`                 |      |\n| verticalLineStyle   | 垂直对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| horizontalLineStyle | 水平对齐线样式                                                                                                          | 支持[BaseStyleProps](/manual/element/shape/properties#baseshapestyle) 下的部分配置，详见[「对齐线样式配置项」](#对齐线样式配置) | `{ stroke: '#1783FF' }` |      |\n| filter              | 过滤不需要参与对齐的节点                                                                                                | (node: Node) => boolean                                                                                                         | `() => true`            |      |\n\n### shape\n\n`shape` 属性用于指定元素的参照图形，支持以下配置方式：\n\n```js\n// 使用主图形作为参照\n{\n  type: 'snapline',\n  shape: 'key'\n}\n\n// 使用自定义函数返回参照图形\n{\n  type: 'snapline',\n  shape: (node) => {\n    return node.getShape('custom-shape');\n  }\n}\n```\n\n### 对齐线样式配置\n\n| 配置项         | 说明            | 类型                                     | 默认值      |\n| -------------- | --------------- | ---------------------------------------- | ----------- |\n| stroke         | 线条颜色        | string \\| Pattern \\| null                | `'#1783FF'` |\n| opacity        | 整体透明度      | number \\| string                         | 1           |\n| strokeOpacity  | 描边透明度      | number \\| string                         | 1           |\n| lineWidth      | 线宽度          | number \\| string                         | 1           |\n| lineCap        | 线段端点样式    | `'butt'` \\| `'round'` \\| `'square'`      | `'butt'`    |\n| lineJoin       | 线段连接处样式  | `'miter'` \\| `'round'` \\| `'bevel'`      | `'miter'`   |\n| lineDash       | 虚线配置        | number \\| string \\| (string \\| number)[] | -           |\n| lineDashOffset | 虚线偏移量      | number                                   | 0           |\n| shadowBlur     | 阴影模糊程度    | number                                   | 0           |\n| shadowColor    | 阴影颜色        | string                                   | -           |\n| shadowOffsetX  | 阴影 X 方向偏移 | number                                   | 0           |\n| shadowOffsetY  | 阴影 Y 方向偏移 | number                                   | 0           |\n| cursor         | 鼠标样式        | string                                   | `'default'` |\n| zIndex         | 渲染层级        | number                                   | 0           |\n\n示例配置\n\n```js\n{\n  type: 'snapline',\n  horizontalLineStyle: {\n    stroke: '#F08F56',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n  verticalLineStyle: {\n    stroke: '#17C76F',\n    strokeOpacity: 0.8,\n    lineWidth: 2,\n    lineDash: [4, 4],\n    lineDashOffset: 0,\n    opacity: 1,\n    cursor: 'move',\n  },\n}\n```\n\n## 代码示例\n\n### 基础对齐线\n\n最简单的使用方式：\n\n```js\nconst graph = new Graph({\n  plugins: ['snapline'],\n});\n```\n\n### 自定义配置\n\n可以根据需要自定义对齐线的行为：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'snapline',\n      tolerance: 8, // 更大的吸附范围\n      offset: 30, // 更长的延伸线\n      horizontalLineStyle: {\n        stroke: '#1890ff',\n        lineWidth: 2,\n      },\n      filter: (node) => node.id !== 'node-0', // 根据id过滤节点，不参与对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'snapline',\n      key: 'snapline',\n      verticalLineStyle: { stroke: '#F08F56', lineWidth: 2 },\n      horizontalLineStyle: { stroke: '#17C76F', lineWidth: 2 },\n      autoSnap: false,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Timebar.en.md) -->\n---\ntitle: Timebar\norder: 14\n---\n\n## Overview\n\nThe Timebar plugin is an important tool for exploring time-series data. It can display the time distribution of data in the form of a timeline or trend chart, and supports interactions such as time interval filtering and dynamic playback, helping users better understand the changes in data over time.\n\n## Use Cases\n\n- Need to display and analyze the time distribution of time-series data\n- Need to filter and explore graph data through the time dimension\n- Need to dynamically display the process of data changing over time\n\n## Basic Usage\n\nBelow is a simple example of initializing the Timebar plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // Time data\n      width: 450, // Timebar width\n      height: 60, // Timebar height\n      position: 'bottom', // Position\n      loop: false, // Whether to loop playback\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## Configuration Options\n\n| Property       | Description                                                                                                                                                                              | Type                                               | Default Value | Required |\n| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------- | -------- |\n| type           | Plugin type                                                                                                                                                                              | string                                             | `timebar`     | ✓        |\n| key            | Unique identifier for the plugin, can be used to get the plugin instance or update plugin options                                                                                        | string                                             | -             |          |\n| className      | Additional class name for the toolbar DOM                                                                                                                                                | string                                             | `g6-timebar`  |          |\n| x              | X position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| y              | Y position (position will be invalid if set)                                                                                                                                             | number                                             | -             |          |\n| width          | Timebar width                                                                                                                                                                            | number                                             | 450           |          |\n| height         | Timebar height                                                                                                                                                                           | number                                             | 60            |          |\n| position       | Timebar position                                                                                                                                                                         | `bottom` \\| `top`                                  | `bottom`      |          |\n| padding        | Padding                                                                                                                                                                                  | number \\| number[]                                 | 10            |          |\n| data           | Time data                                                                                                                                                                                | number[] \\| { time: number; value: number }[]      | -             | ✓        |\n| timebarType    | Timebar display type                                                                                                                                                                     | `time` \\| `chart`                                  | `time`        |          |\n| elementTypes   | Filter element types                                                                                                                                                                     | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]      |          |\n| mode           | Control element filtering method, supports the following two configurations: <br/>- `modify`: filter by modifying graph data <br/>- `visibility`: filter by modifying element visibility | `modify` \\| `visibility`                           | `modify`      |          |\n| values         | Current time value                                                                                                                                                                       | number \\| [number, number] \\| Date \\| [Date, Date] | -             |          |\n| loop           | Whether to loop playback                                                                                                                                                                 | boolean                                            | false         |          |\n| getTime        | Method to get element time                                                                                                                                                               | (datum: ElementDatum) => number                    | -             |          |\n| labelFormatter | Custom time formatting in chart mode                                                                                                                                                     | (time: number \\| Date) => string                   | -             |          |\n| onChange       | Callback when the time interval changes                                                                                                                                                  | (values: number \\| [number, number]) => void       | -             |          |\n| onReset        | Callback when reset                                                                                                                                                                      | () => void                                         | -             |          |\n| onSpeedChange  | Callback when playback speed changes                                                                                                                                                     | (speed: number) => void                            | -             |          |\n| onPlay         | Callback when playback starts                                                                                                                                                            | () => void                                         | -             |          |\n| onPause        | Callback when paused                                                                                                                                                                     | () => void                                         | -             |          |\n| onBackward     | Callback when moving backward                                                                                                                                                            | () => void                                         | -             |          |\n| onForward      | Callback when moving forward                                                                                                                                                             | () => void                                         | -             |          |\n\n### timebarType\n\nThe `timebarType` property is used to control the display type of the timebar, supporting the following two configurations:\n\n- `time`: Displayed as a timeline, refer to [Time Mode Example](/examples/plugin/timebar/#timer)\n- `chart`: Displayed as a trend chart, at this time the `data` configuration item under `timebar` needs to pass an additional `value` field as chart data, refer to [Chart Mode Example](/examples/plugin/timebar/#chart)\n\n## Code Examples\n\n### Basic Usage\n\nThe simplest configuration method:\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        // By default, elementTypes=['node'], so nodes need to set data.timestamp to display sequentially according to the timeline\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // Scenario 1: By default, elementTypes = ['node']\n        // - Edges do not need to set data.timestamp, the display/hide of edges depends entirely on whether the two connected nodes are visible\n\n        // Scenario 2: If elementTypes includes 'edge', for example, elementTypes = ['node', 'edge']\n        // - At this time, edges must set data.timestamp, and the display of edges is controlled by it\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: 'Node 1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: 'Node 2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: 'Node 3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\n`width`, `height`, `padding`, `className` can customize the display effect of the timebar, but note that `className` only acts on the outer DOM container and cannot affect the internal Canvas rendering content of the timebar (timeline, chart, play button, etc.).\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // Note: Since the content is Canvas rendered, CSS styles cannot affect the internal content of the timebar\n      width: 400, // Set timebar width\n      height: 80, // Set timebar height\n      padding: [20, 20, 10, 20], // Set padding [top, right, bottom, left]\n      position: 'bottom', // Keep position at the bottom\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\nCSS can only set the style of the timebar container:\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\nThe effect is as follows:\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## Real Cases\n\n- [Time Mode](/examples/plugin/timebar/#timer)\n- [Chart Mode](/examples/plugin/timebar/#chart)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Timebar.zh.md) -->\n---\ntitle: 时间条 Timebar\norder: 14\n---\n\n## 概述\n\n时间条插件是一个用于时序数据探索的重要工具，它能够通过时间轴或趋势图的形式展示数据的时间分布，并支持时间区间筛选、动态播放等交互方式，帮助用户更好地理解数据随时间的变化。\n\n## 使用场景\n\n- 需要展示和分析时序数据的时间分布\n- 需要通过时间维度筛选和探索图数据\n- 需要动态展示数据随时间变化的过程\n\n## 基本用法\n\n以下是一个简单的 Timebar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      data: timeData, // 时间数据\n      width: 450, // 时间条宽度\n      height: 60, // 时间条高度\n      position: 'bottom', // 位置\n      loop: false, // 是否循环播放\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/timebar.md\"></embed>\n\n## 配置项\n\n| 属性           | 描述                                                                                                                           | 类型                                               | 默认值       | 必选 |\n| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------------ | ---- |\n| type           | 插件类型                                                                                                                       | string                                             | `timebar`    | ✓    |\n| key            | 插件的唯一标识，可用于获取插件实例或更新插件选项                                                                               | string                                             | -            |      |\n| className      | 给工具栏的 DOM 追加的类名                                                                                                      | string                                             | `g6-timebar` |      |\n| x              | X 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| y              | Y 位置（设置后 position 会失效）                                                                                               | number                                             | -            |      |\n| width          | 时间条宽度                                                                                                                     | number                                             | 450          |      |\n| height         | 时间条高度                                                                                                                     | number                                             | 60           |      |\n| position       | 时间条位置                                                                                                                     | `bottom` \\| `top`                                  | `bottom`     |      |\n| padding        | 边距                                                                                                                           | number \\| number[]                                 | 10           |      |\n| data           | 时间数据                                                                                                                       | number[] \\| { time: number; value: number }[]      | -            | ✓    |\n| timebarType    | 时间条展示类型                                                                                                                 | `time` \\| `chart`                                  | `time`       |      |\n| elementTypes   | 筛选元素类型                                                                                                                   | (`node` \\| `edge` \\| `combo`)[]                    | [`node`]     |      |\n| mode           | 控制元素的筛选方式，支持以下两种配置： <br/>- `modify`：通过修改图数据进行筛选 <br/>- `visibility`：通过修改元素可见性进行筛选 | `modify` \\| `visibility`                           | `modify`     |      |\n| values         | 当前时间值                                                                                                                     | number \\| [number, number] \\| Date \\| [Date, Date] | -            |      |\n| loop           | 是否循环播放                                                                                                                   | boolean                                            | false        |      |\n| getTime        | 获取元素时间的方法                                                                                                             | (datum: ElementDatum) => number                    | -            |      |\n| labelFormatter | 图表模式下自定义时间格式化                                                                                                     | (time: number \\| Date) => string                   | -            |      |\n| onChange       | 时间区间变化时的回调                                                                                                           | (values: number \\| [number, number]) => void       | -            |      |\n| onReset        | 重置时的回调                                                                                                                   | () => void                                         | -            |      |\n| onSpeedChange  | 播放速度变化时的回调                                                                                                           | (speed: number) => void                            | -            |      |\n| onPlay         | 开始播放时的回调                                                                                                               | () => void                                         | -            |      |\n| onPause        | 暂停时的回调                                                                                                                   | () => void                                         | -            |      |\n| onBackward     | 后退时的回调                                                                                                                   | () => void                                         | -            |      |\n| onForward      | 前进时的回调                                                                                                                   | () => void                                         | -            |      |\n\n### timebarType\n\n`timebarType` 属性用于控制时间条的展示类型，支持以下两种配置：\n\n- `time`：显示为时间轴形式，参考 [时间模式示例](/examples/plugin/timebar/#timer)\n- `chart`：显示为趋势图形式，此时`timebar`下的`data`配置项，每个数组项需要额外传入 `value` 字段作为图表数据，参考 [图表模式示例](/examples/plugin/timebar/#chart)\n\n## 代码示例\n\n### 基础用法\n\n最简单的配置方式：\n\n```js\nconst graph = new Graph({\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        // 默认情况下 elementTypes=['node']，所以节点需要设置 data.timestamp，才能按照时间轴内的时间依次展示\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n        // 场景一：默认情况 elementTypes = ['node']\n        // - 边不需要设置 data.timestamp，边的显示/隐藏完全取决于其连接的两个节点是否可见\n\n        // 场景二：如果elementTypes包含了'edge'，比如 elementTypes = ['node', 'edge']\n        // - 此时必须为边设置 data.timestamp，边的显示受其控制\n        // data: {\n        //   timestamp: new Date('2023-08-01').getTime()\n        // }\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n```\n\n效果如下：\n\n```js | ob { pin: false, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  width: 600,\n  height: 400,\n  width: 600,\n  height: 400,\n  layout: { type: 'grid', cols: 5 },\n  plugins: [\n    {\n      type: 'timebar',\n      data: [\n        {\n          time: new Date('2023-08-01').getTime(),\n          value: 5,\n        },\n        {\n          time: new Date('2023-08-02').getTime(),\n          value: 10,\n        },\n        {\n          time: new Date('2023-08-03').getTime(),\n          value: 15,\n        },\n      ],\n    },\n  ],\n  data: {\n    nodes: [\n      {\n        id: 'node1',\n        label: '节点1',\n        data: {\n          timestamp: new Date('2023-08-01').getTime(),\n        },\n      },\n      {\n        id: 'node2',\n        label: '节点2',\n        data: {\n          timestamp: new Date('2023-08-02').getTime(),\n        },\n      },\n      {\n        id: 'node3',\n        label: '节点3',\n        data: {\n          timestamp: new Date('2023-08-03').getTime(),\n        },\n      },\n    ],\n    edges: [\n      {\n        id: 'edge1',\n        source: 'node1',\n        target: 'node2',\n      },\n      {\n        id: 'edge2',\n        source: 'node2',\n        target: 'node3',\n      },\n      {\n        id: 'edge3',\n        source: 'node3',\n        target: 'node1',\n      },\n    ],\n  },\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n`width`、`height`、`padding`、`className` 可自定义时间条的展示效果，但需要注意 `className` 仅作用于外层 DOM 容器，无法影响时间条内部的 Canvas 渲染内容（时间轴、图表、播放按钮等）。\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'timebar',\n      className: 'custom-timebar', // 注意：由于内容是 Canvas 渲染，CSS 样式无法影响到时间条的内部内容\n      width: 400, // 设置时间条宽度\n      height: 80, // 设置时间条高度\n      padding: [20, 20, 10, 20], // 设置内边距 [上, 右, 下, 左]\n      position: 'bottom', // 位置保持在底部\n      data: timeData,\n      // labelFormatter: (time) => {\n      //   return new Date(time).toLocaleDateString();\n      // }\n    },\n  ],\n});\n```\n\n通过 CSS 只能设置时间条容器的样式：\n\n```css\n.custom-timebar {\n  background-color: #f0f0f0;\n  border: 1px solid #ccc;\n  border-radius: 5px;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n```\n\n效果如下：\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: () => {\n      return {\n        nodes: [\n          {\n            id: 'node1',\n            style: { x: 100, y: 100, label: 'Node 1' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime(),\n            },\n          },\n          {\n            id: 'node2',\n            style: { x: 200, y: 100, label: 'Node 2' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            },\n          },\n          {\n            id: 'node3',\n            style: { x: 150, y: 200, label: 'Node 3' },\n            data: {\n              timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            },\n          },\n        ],\n        edges: [\n          { id: 'edge1', source: 'node1', target: 'node2' },\n          { id: 'edge2', source: 'node2', target: 'node3' },\n          { id: 'edge3', source: 'node3', target: 'node1' },\n        ],\n      };\n    },\n    node: {\n      style: {\n        size: 20,\n        label: true,\n      },\n    },\n    edge: {\n      style: {\n        stroke: '#91d5ff',\n        lineWidth: 1,\n      },\n    },\n    plugins: [\n      {\n        type: 'timebar',\n        className: 'custom-timebar',\n        width: 400,\n        height: 80,\n        padding: [20, 20, 10, 20],\n        position: 'bottom',\n        data: [\n          {\n            time: new Date('2023-08-01').getTime(),\n            value: 5,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,\n            value: 10,\n          },\n          {\n            time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,\n            value: 15,\n          },\n        ],\n        labelFormatter: (time) => {\n          return new Date(time).toLocaleDateString();\n        },\n      },\n    ],\n  },\n  { width: 600, height: 400 },\n  (gui, graph) => {\n    gui?.hide();\n    const style = document.createElement('style');\n    style.innerHTML = `\n      .custom-timebar {\n        background-color: #f0f0f0;\n        border: 1px solid #ccc;\n        border-radius: 5px;\n        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n      }\n    `;\n    document.head.appendChild(style);\n  },\n);\n```\n\n## 实际案例\n\n- [时间模式](/examples/plugin/timebar/#timer)\n- [图表模式](/examples/plugin/timebar/#chart)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Title.en.md) -->\n---\ntitle: Title\norder: 15\n---\n\n## Overview\n\nTitle indicates the name of the image and conveys the brief content of the image.\n\n## Basic Usage\n\nThe following is a simple example of initializing the Title plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: 'This is a title',\n      subTitle: 'This is a subtitle',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Option    | Description                                                   | Type                          | Default      | Required |\n| --------- | ------------------------------------------------------------- | ----------------------------- | ------------ | -------- |\n| type      | Plugin type                                                   | string                        | `title`      | ✓        |\n| key       | Unique identifier for the plugin, used for subsequent updates | string                        | -            |          |\n| title     | title content [style config](#title)                          | `TitleStyle`                  | -            | ✓        |\n| subtitle  | subtitle content [style config](#subtitle)                    | `SubTitleStyle`               | -            |          |\n| spacing   | Vertical spacing between main title and subtitle              | number                        | 8            |          |\n| className | Class name of the title canvas                                | string                        | -            |          |\n| align     | Graph title alignment                                         | `left` \\| `center` \\| `right` | `left`       |          |\n| size      | Height of the title plugin                                    | number                        | 44           |          |\n| padding   | Padding                                                       | number \\| number[]            | [16,24,0,24] |          |\n\n### size\n\n<description> _number_ **optional** </description>\n\nUsed to configure the space height of the title plugin. Default is `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\nUsed to configure the horizontal alignment of the title plugin. Default is `left`. You can choose `left`, `center`, or `right`, representing left-aligned, center-aligned, and right-aligned respectively.\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: 'Ciallo' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: 'This is a title This is a title',\n        subtitle: 'This is a sub-',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\nUsed to configure the spacing between the chart main title and subtitle. Default is `8`. Appropriate spacing can make the chart look more harmonious overall.\n\n### title\n\nThe title, specifically the main title, can be customized with the following configurations for various title styles.\n\n| Attr               | Desc                                               | Type       | Default               |\n| ------------------ | -------------------------------------------------- | ---------- | --------------------- |\n| title              | Title text content                                 | `string`   | -                     |\n| titleFontSize      | Title text size                                    | `number`   | 16                    |\n| titleFontFamily    | Title text font                                    | `string`   | system-ui, sans-serif |\n| titleFontWeight    | Title font weight                                  | `number`   | bold                  |\n| titleLineHeight    | Title text line height                             | `number`   | 16                    |\n| titleTextAlign     | Horizontal alignment of content in title text line | `string`   | left                  |\n| titleTextBaseline  | Vertical baseline of title text                    | `string`   | top                   |\n| titleFill          | Fill color of title text                           | `string`   | #1D2129               |\n| titleFillOpacity   | Fill transparency of title text                    | `number`   | 0.9                   |\n| titleStroke        | Stroke color of title text                         | `string`   | transparent           |\n| titleStrokeOpacity | Stroke transparency of title text                  | `number`   | 1                     |\n| titleLineWidth     | Stroke width of title text                         | `number`   | 0                     |\n| titleLineDash      | Dash style of title text                           | `number[]` | []                    |\n| titleOpacity       | Overall transparency of title text                 | `number`   | 1                     |\n| titleShadowColor   | Shadow color of title text                         | `string`   | transparent           |\n| titleShadowBlur    | Gaussian blur coefficient of title text shadow     | `number`   | 0                     |\n| titleShadowOffsetX | Horizontal offset of title text shadow             | `number`   | 0                     |\n| titleShadowOffsetY | Vertical offset of title text shadow               | `number`   | 0                     |\n| titleCursor        | Mouse style of title text                          | `string`   | default               |\n| titleDx            | Horizontal offset of title text                    | `number`   | 0                     |\n| titleDy            | Vertical offset of title text                      | `number`   | 0                     |\n\n### subtitle\n\nThe subtitle, which can be customized with the following configurations for various subtitle styles.\n\n| Attr                  | Desc                                            | Type       | Default               |\n| --------------------- | ----------------------------------------------- | ---------- | --------------------- |\n| subtitle              | Subtitle text content                           | `string`   | -                     |\n| subtitleFontSize      | Subtitle text size                              | `number`   | 12                    |\n| subtitleFontFamily    | Subtitle text font                              | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | Subtitle font weight                            | `number`   | normal                |\n| subtitleLineHeight    | Subtitle text line height                       | `number`   | 12                    |\n| subtitleTextAlign     | Subtitle text line content horizontal alignment | `string`   | left                  |\n| subtitleTextBaseline  | Subtitle text vertical baseline                 | `string`   | top                   |\n| subtitleFill          | Subtitle text fill color                        | `string`   | #1D2129               |\n| subtitleFillOpacity   | Subtitle text fill transparency                 | `number`   | 0.65                  |\n| subtitleStroke        | Subtitle text stroke color                      | `string`   | transparent           |\n| subtitleStrokeOpacity | Subtitle text stroke transparency               | `number`   | 1                     |\n| subtitleLineWidth     | Subtitle text stroke width                      | `number`   | 0                     |\n| subtitleLineDash      | Subtitle text dashed line style                 | `number[]` | []                    |\n| subtitleOpacity       | Subtitle text overall transparency              | `number`   | 1                     |\n| subtitleShadowColor   | Subtitle text shadow color                      | `string`   | transparent           |\n| subtitleShadowBlur    | Subtitle text shadow Gaussian blur coefficient  | `number`   | 0                     |\n| subtitleShadowOffsetX | Subtitle text shadow horizontal offset          | `number`   | 0                     |\n| subtitleShadowOffsetY | Subtitle text shadow vertical offset            | `number`   | 0                     |\n| subtitleCursor        | Subtitle text mouse style                       | `string`   | default               |\n| subtitleDx            | Subtitle text horizontal offset                 | `number`   | 0                     |\n| subtitleDy            | Subtitle text vertical offset                   | `number`   | 0                     |\n\n## Try it\n\nFeel free to modify this example and try different configurations\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // Alignment of title\n      spacing: 4, // Spacing between main title and subtitle\n      size: 60, // Height of title, default is 44\n\n      // title\n      title: 'This is a title This is a title', // Title text\n      titleFontSize: 28, // Main title font size\n      titleFontFamily: 'sans-serif', // Main title font\n      titleFontWeight: 600, // Main title font weight\n      titleFill: '#fff', // Main title text color\n      titleFillOpacity: 1, // Main title text transparency\n      titleStroke: '#000', // Main title text stroke color\n      titleLineWidth: 2, // Main title text stroke line width\n      titleStrokeOpacity: 1, // Main title text stroke transparency\n\n      // subtitle\n      subtitle: 'This is a sub-', // Subtitle text\n      subtitleFontSize: 16, // Subtitle font size\n      subtitleFontFamily: 'Arial', // Subtitle font\n      subtitleFontWeight: 300, // Subtitle font weight\n      subtitleFill: '#2989FF', // Subtitle text color\n      subtitleFillOpacity: 1, // Subtitle text transparency\n      subtitleStroke: '#000', // Subtitle text stroke color\n      subtitleLineWidth: 1, // Subtitle text stroke line width\n      subtitleStrokeOpacity: 0.5, // Subtitle text stroke transparency\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: 'Ciallo' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Title.zh.md) -->\n---\ntitle: 标题 Title\norder: 15\n---\n\n## 概述\n\nTitle（标题）表明了这张图的名称，传达图的简略内容\n\n## 基本用法\n\n以下是一个简单的 Title 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n      title: '这是一个标题',\n      subTitle: '这是一个副标题',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                             | 类型                          | 默认值       | 必选 |\n| --------- | -------------------------------- | ----------------------------- | ------------ | ---- |\n| type      | 插件类型                         | string                        | `title`      | ✓    |\n| key       | 插件唯一标识符，用于后续更新     | string                        | -            |      |\n| title     | 标题内容 [样式配置](#title)      | `TitleStyle`                  | -            | ✓    |\n| subtitle  | 副标题内容 [样式配置](#subtitle) | `SubTitleStyle`               | -            |      |\n| spacing   | 主标题、副标题之间的上下间距     | number                        | 8            |      |\n| className | 标题画布类名                     | string                        | -            |      |\n| align     | 标题相对于画布的位置             | `left` \\| `center` \\| `right` | `left`       |      |\n| size      | 整个标题插件的高度               | number                        | 44           |      |\n| padding   | 内边距                           | number \\| number[]            | [16,24,0,24] |      |\n\n### size\n\n<description> _number_ **optional** </description>\n\n用于配置标题的空间高度大小，默认为 `44`。\n\n### align\n\n<description> _string_ **optional** </description>\n\n用于配置标题的的左右对齐方式，默认为 `left`，可以选择使用 `left`，`center`，`right`，分别代表着居左对齐、居中对齐、居右对齐。\n\n```js | ob { pin: false }\ncreateGraph(\n  {\n    data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n    node: {\n      palette: 'spectral',\n      style: { labelText: '你好' },\n    },\n    behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n    plugins: [\n      {\n        key: 'title',\n        type: 'title',\n        title: '这是一个标题这是一个标题',\n        subtitle: '这是一个副标',\n      },\n    ],\n    layout: { type: 'circular' },\n    autoFit: 'view',\n  },\n  { width: 600, height: 300 },\n  (gui, graph) => {\n    const options = { align: 'left' };\n    const optionFolder = gui.addFolder('Align Options');\n    optionFolder.add(options, 'align', ['left', 'center', 'right']);\n    optionFolder.onChange(({ property, value }) => {\n      graph.updatePlugin({\n        key: 'title',\n        [property]: value,\n      });\n      graph.render();\n    });\n  },\n);\n```\n\n### spacing\n\n<description> _number_ **optional** </description>\n\n用于配置主标题和副标题之间的间距，默认为 `8`，合适的间距，可以让看起来整体更协调。\n\n### title\n\n的标题，具体来说是主标题，可以用以下的配置来定制标题的各种样式。\n\n| 属性               | 描述                           | 类型       | 默认值                |\n| ------------------ | ------------------------------ | ---------- | --------------------- |\n| title              | 标题文字内容                   | `string`   | -                     |\n| titleFontSize      | 标题文字大小                   | `number`   | 16                    |\n| titleFontFamily    | 标题文字字体                   | `string`   | system-ui, sans-serif |\n| titleFontWeight    | 标题字体粗细                   | `number`   | bold                  |\n| titleLineHeight    | 标题文字的行高                 | `number`   | 16                    |\n| titleTextAlign     | 标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| titleTextBaseline  | 标题文字垂直方向的基线         | `string`   | top                   |\n| titleFill          | 标题文字的填充色               | `string`   | #1D2129               |\n| titleFillOpacity   | 标题文字的填充透明度           | `number`   | 0.9                   |\n| titleStroke        | 标题文字的描边颜色             | `string`   | transparent           |\n| titleStrokeOpacity | 标题文字的描边透明度           | `number`   | 1                     |\n| titleLineWidth     | 标题文字描边宽度               | `number`   | 0                     |\n| titleLineDash      | 标题文字虚线样式               | `number[]` | []                    |\n| titleOpacity       | 标题文字整体透明度             | `number`   | 1                     |\n| titleShadowColor   | 标题文字阴影颜色               | `string`   | transparent           |\n| titleShadowBlur    | 标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| titleShadowOffsetX | 标题文字阴影水平偏移量         | `number`   | 0                     |\n| titleShadowOffsetY | 标题文字阴影垂直偏移量         | `number`   | 0                     |\n| titleCursor        | 标题文字鼠标样式               | `string`   | default               |\n| titleDx            | 标题文字在水平方向的偏移量     | `number`   | 0                     |\n| titleDy            | 标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n### subtitle\n\n的副标题，可以用以下的配置来定制副标题的各种样式。\n\n| 属性                  | 描述                             | 类型       | 默认值                |\n| --------------------- | -------------------------------- | ---------- | --------------------- |\n| subtitle              | 副标题文字内容                   | `string`   | -                     |\n| subtitleFontSize      | 副标题文字大小                   | `number`   | 12                    |\n| subtitleFontFamily    | 副标题文字字体                   | `string`   | system-ui, sans-serif |\n| subtitleFontWeight    | 副标题字体粗细                   | `number`   | normal                |\n| subtitleLineHeight    | 副标题文字的行高                 | `number`   | 12                    |\n| subtitleTextAlign     | 副标题文字行内内容的水平对齐方式 | `string`   | left                  |\n| subtitleTextBaseline  | 副标题文字垂直方向的基线         | `string`   | top                   |\n| subtitleFill          | 副标题文字的填充色               | `string`   | #1D2129               |\n| subtitleFillOpacity   | 副标题文字的填充透明度           | `number`   | 0.65                  |\n| subtitleStroke        | 副标题文字的描边颜色             | `string`   | transparent           |\n| subtitleStrokeOpacity | 副标题文字的描边透明度           | `number`   | 1                     |\n| subtitleLineWidth     | 副标题文字描边宽度               | `number`   | 0                     |\n| subtitleLineDash      | 副标题文字虚线样式               | `number[]` | []                    |\n| subtitleOpacity       | 副标题文字整体透明度             | `number`   | 1                     |\n| subtitleShadowColor   | 副标题文字阴影颜色               | `string`   | transparent           |\n| subtitleShadowBlur    | 副标题文字阴影的高斯模糊系数     | `number`   | 0                     |\n| subtitleShadowOffsetX | 副标题文字阴影水平偏移量         | `number`   | 0                     |\n| subtitleShadowOffsetY | 副标题文字阴影垂直偏移量         | `number`   | 0                     |\n| subtitleCursor        | 副标题文字鼠标样式               | `string`   | default               |\n| subtitleDx            | 副标题文字在水平方向的偏移量     | `number`   | 0                     |\n| subtitleDy            | 副标题文字在垂直方向的偏移量     | `number`   | 0                     |\n\n## 尝试一下\n\n你可以在这个例子里随意修改并尝试不同的配置\n\n```js | ob { pin: true, inject: true }\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  data: { nodes: Array.from({ length: 12 }).map((_, i) => ({ id: `node${i}` })) },\n  behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],\n  plugins: [\n    {\n      key: 'title',\n      type: 'title',\n\n      align: 'center', // 标题的对齐方式\n      spacing: 4, // 主标题和副标题之间的间距\n      size: 60, // 标题的高度，默认为 44\n\n      // 标题\n      title: '这是一个标题这是一个标题', // 标题的文本\n      titleFontSize: 28, // 主标题的字体大小\n      titleFontFamily: 'sans-serif', // 主标题的字体\n      titleFontWeight: 600, // 主标题的字体粗细\n      titleFill: '#fff', // 主标题的文字颜色\n      titleFillOpacity: 1, // 主标题的文字透明度\n      titleStroke: '#000', // 主标题的文字描边颜色\n      titleLineWidth: 2, // 主标题的文字描边线宽\n      titleStrokeOpacity: 1, // 主标题的文字描边透明度\n\n      // 副标题\n      subtitle: '这是一个副标', // 副标题的文本\n      subtitleFontSize: 16, // 副标题的字体大小\n      subtitleFontFamily: 'Arial', // 副标题的字体\n      subtitleFontWeight: 300, // 副标题的字体粗细\n      subtitleFill: '#2989FF', // 副标题的文字颜色\n      subtitleFillOpacity: 1, // 副标题的文字透明度\n      subtitleStroke: '#000', // 副标题的文字描边颜色\n      subtitleLineWidth: 1, // 副标题的文字描边线宽\n      subtitleStrokeOpacity: 0.5, // 副标题的文字描边透明度\n    },\n  ],\n  node: {\n    palette: 'spectral',\n    style: { labelText: '你好' },\n  },\n  layout: {\n    type: 'circular',\n  },\n  autoFit: 'view',\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Toolbar.en.md) -->\n---\ntitle: Toolbar\norder: 15\n---\n\n## Overview\n\nThe Toolbar is a plugin in G6 used to provide a collection of operation buttons, supporting common chart operations such as zoom in, zoom out, auto-fit, and reset. Through the toolbar, users can quickly access common functions of the chart, improving operational efficiency and user experience.\n\n## Use Cases\n\nThis plugin is mainly used for:\n\n- Quickly accessing common functions of the chart\n\n## Basic Usage\n\nBelow is a simple example of initializing the Toolbar plugin:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // Handle button click events\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property  | Description                                                                  | Type                                                                                        | Default Value | Required |\n| --------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | -------- |\n| type      | Plugin type                                                                  | string                                                                                      | `toolbar`     | ✓        |\n| key       | Unique identifier for the plugin, used for updates                           | string                                                                                      | -             |          |\n| className | Additional CSS class name for the toolbar DOM element                        | string                                                                                      | -             |          |\n| position  | Toolbar position relative to the canvas, [optional values](#position)        | string                                                                                      | `'top-left'`  |          |\n| style     | Custom style for the toolbar DOM element, [common values](#style-attributes) | [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) | -             |          |\n| getItems  | Returns the list of toolbar items                                            | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -             | ✓        |\n| onClick   | Callback function after a toolbar item is clicked                            | (value: string, target: Element) => void                                                    | -             |          |\n\n### position\n\nThe `position` parameter supports the following values:\n\n- `'top-left'`: Top left corner\n- `'top-right'`: Top right corner\n- `'bottom-left'`: Bottom left corner\n- `'bottom-right'`: Bottom right corner\n- `'left-top'`: Left side, top\n- `'left-bottom'`: Left side, bottom\n- `'right-top'`: Right side, top\n- `'right-bottom'`: Right side, bottom\n\n### style Attributes\n\n| Attribute       | Description      | Type   | Default Value       |\n| --------------- | ---------------- | ------ | ------------------- |\n| backgroundColor | Background color | string | `#fff`              |\n| border          | Border           | string | `1px solid #e8e8e8` |\n| borderRadius    | Border radius    | string | `4px`               |\n| height          | Height           | string | `auto`              |\n| margin          | Margin           | string | `12px`              |\n| opacity         | Opacity          | number | 0.9                 |\n| padding         | Padding          | string | `8px`               |\n| width           | Width            | string | `auto`              |\n\n### ToolbarItem\n\nEach toolbar item (ToolbarItem) includes the following attributes:\n\n| Attribute | Description                                                | Type     | Required |\n| --------- | ---------------------------------------------------------- | -------- | -------- |\n| id        | Icon ID of the item, see [Built-in Icons](#built-in-icons) | `string` | ✓        |\n| value     | Value returned when the item is clicked                    | `string` | ✓        |\n\n### Built-in Icons\n\nThe Toolbar provides the following built-in icon IDs:\n\n- `'zoom-in'`: Zoom in\n- `'zoom-out'`: Zoom out\n- `'redo'`: Redo\n- `'undo'`: Undo\n- `'edit'`: Edit\n- `'delete'`: Delete\n- `'auto-fit'`: Auto-fit view\n- `'export'`: Export chart\n- `'reset'`: Reset view\n- `'request-fullscreen'`: Request fullscreen\n- `'exit-fullscreen'`: Exit fullscreen\n\n### Custom Icons\n\nIn addition to using built-in icons, you can also use custom icons by introducing third-party icon libraries (such as Alibaba iconfont):\n\n```js\n// Introduce iconfont script\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // Replace with your iconfont script URL\ndocument.head.appendChild(iconFont);\n\n// Use custom icons in the toolbar\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // Use icons from iconfont\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Note: Custom icon IDs usually start with `icon-` and need to correspond to the icon names in the introduced iconfont.\n\n## Code Examples\n\n### Basic Toolbar\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo, undo need to be used with the history plugin\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### Custom Styles\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n> Common style attributes include:\n>\n> - `backgroundColor`: Background color\n> - `padding`: Padding\n> - `margin`/`marginTop`/`marginLeft`, etc.: Margin\n> - `border`: Border\n> - `borderRadius`: Border radius\n> - `boxShadow`: Shadow effect\n> - `opacity`: Opacity\n> - `width`/`height`: Width and height (default is content adaptive)\n> - `zIndex`: Layer (default is 100)\n> - `display`: Display mode (default is flex)\n\nThe toolbar container is set to `display: flex` by default, and child items use row layout by default (or change according to the direction configured by position). You can customize its appearance and position through `style`.\n\n### Asynchronous Loading of Toolbar Items\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // Toolbar configuration can be obtained from the server or other asynchronous sources\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // Handle click events\n      },\n    },\n  ],\n});\n```\n\n## Common Issues\n\n### 1. Toolbar icons not displaying?\n\n- Check if the correct built-in icon ID is used\n- Ensure CSS styles are not overridden or conflicting\n\n### 2. How to use with other plugins?\n\nThe toolbar is often used in conjunction with other plugins (such as history):\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. How to dynamically update the toolbar?\n\nYou can use the `updatePlugin` method to dynamically update the toolbar:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// Update toolbar position\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## Real Cases\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Toolbar.zh.md) -->\n---\ntitle: 工具栏 Toolbar\norder: 15\n---\n\n## 概述\n\nToolbar 是 G6 中用于提供操作按钮集合的插件，支持放大、缩小、自适应、重置等常用图表操作。通过工具栏，用户可以快速访问图表的常用功能，提高操作效率和用户体验。\n\n## 使用场景\n\n这一插件主要用于：\n\n- 快速访问图表的常用功能\n\n## 基本用法\n\n以下是一个简单的 Toolbar 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'auto-fit', value: 'auto-fit' },\n      ],\n      onClick: (value) => {\n        // 处理按钮点击事件\n        if (value === 'zoom-in') {\n          graph.zoomTo(1.1);\n        } else if (value === 'zoom-out') {\n          graph.zoomTo(0.9);\n        } else if (value === 'auto-fit') {\n          graph.fitView();\n        }\n      },\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性      | 描述                                             | 类型                                                                                        | 默认值       | 必选 |\n| --------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------ | ---- |\n| type      | 插件类型                                         | string                                                                                      | `toolbar`    | ✓    |\n| key       | 插件唯一标识符，用于后续更新                     | string                                                                                      | -            |      |\n| className | 工具栏DOM元素的额外CSS类名                       | string                                                                                      | -            |      |\n| position  | 工具栏位置，相对于画布，[可选值](#position)      | string                                                                                      | `'top-left'` |      |\n| style     | 工具栏DOM元素的自定义样式，[常用值](#style-属性) | [CSSStyleDeclaration](https://developer.mozilla.org/zh-CN/docs/Web/API/CSSStyleDeclaration) | -            |      |\n| getItems  | 返回工具栏项目列表                               | () => [ToolbarItem](#toolbaritem)[] \\| Promise<[ToolbarItem](#toolbaritem)[]>               | -            | ✓    |\n| onClick   | 工具栏项目点击后的回调函数                       | (value: string, target: Element) => void                                                    | -            |      |\n\n### position\n\n`position` 参数支持以下值：\n\n- `'top-left'`：左上角\n- `'top-right'`：右上角\n- `'bottom-left'`：左下角\n- `'bottom-right'`：右下角\n- `'left-top'`：左侧靠上\n- `'left-bottom'`：左侧靠下\n- `'right-top'`：右侧靠上\n- `'right-bottom'`：右侧靠下\n\n### style 属性\n\n| 属性            | 描述     | 类型   | 默认值              |\n| --------------- | -------- | ------ | ------------------- |\n| backgroundColor | 背景颜色 | string | `#fff`              |\n| border          | 边框     | string | `1px solid #e8e8e8` |\n| borderRadius    | 圆角     | string | `4px`               |\n| height          | 高度     | string | `auto`              |\n| margin          | 外边距   | string | `12px`              |\n| opacity         | 透明度   | number | 0.9                 |\n| padding         | 内边距   | string | `8px`               |\n| width           | 宽度     | string | `auto`              |\n\n### ToolbarItem\n\n每个工具栏项目 (ToolbarItem) 包含以下属性：\n\n| 属性  | 描述                                            | 类型     | 必选 |\n| ----- | ----------------------------------------------- | -------- | ---- |\n| id    | 项目的图标ID，内置图标ID见[内置图标](#内置图标) | `string` | ✓    |\n| value | 点击项目时返回的值                              | `string` | ✓    |\n\n### 内置图标\n\nToolbar 提供以下内置图标 ID：\n\n- `'zoom-in'`：放大\n- `'zoom-out'`：缩小\n- `'redo'`：重做\n- `'undo'`：撤销\n- `'edit'`：编辑\n- `'delete'`：删除\n- `'auto-fit'`：自适应视图\n- `'export'`：导出图表\n- `'reset'`：重置视图\n- `'request-fullscreen'`：请求全屏\n- `'exit-fullscreen'`：退出全屏\n\n### 自定义图标\n\n除了使用内置图标外，还可以通过引入第三方图标库（如阿里巴巴 iconfont）来使用自定义图标：\n\n```js\n// 引入 iconfont 脚本\nconst iconFont = document.createElement('script');\niconFont.src = '//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js'; // 替换为你的 iconfont 脚本地址\ndocument.head.appendChild(iconFont);\n\n// 在工具栏中使用自定义图标\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'icon-xinjian', value: 'new' }, // 使用 iconfont 中的图标\n        { id: 'icon-fenxiang', value: 'share' },\n        { id: 'icon-chexiao', value: 'undo' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 注意：自定义图标的 ID 通常以 `icon-` 开头，需要与引入的 iconfont 中的图标名称对应。\n\n## 代码示例\n\n### 基础工具栏\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-right',\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n        { id: 'auto-fit', value: 'fit' },\n      ],\n      onClick: (value) => {\n        // redo、undo 需要配合 history 插件使用\n        const history = graph.getPluginInstance('history');\n        switch (value) {\n          case 'zoom-in':\n            graph.zoomTo(1.1);\n            break;\n          case 'zoom-out':\n            graph.zoomTo(0.9);\n            break;\n          case 'undo':\n            history?.undo();\n            break;\n          case 'redo':\n            history?.redo();\n            break;\n          case 'fit':\n            graph.fitView();\n            break;\n          default:\n            break;\n        }\n      },\n    },\n  ],\n});\n```\n\n### 自定义样式\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      className: 'my-custom-toolbar',\n      style: {\n        backgroundColor: '#f5f5f5',\n        padding: '8px',\n        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',\n        borderRadius: '8px',\n        border: '1px solid #e8e8e8',\n        opacity: '0.9',\n        marginTop: '12px',\n        marginLeft: '12px',\n      },\n      getItems: () => [\n        { id: 'zoom-in', value: 'zoom-in' },\n        { id: 'zoom-out', value: 'zoom-out' },\n      ],\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n> 常用的样式属性包括：\n>\n> - `backgroundColor`：背景颜色\n> - `padding`：内边距\n> - `margin`/`marginTop`/`marginLeft` 等：外边距\n> - `border`：边框\n> - `borderRadius`：圆角\n> - `boxShadow`：阴影效果\n> - `opacity`：透明度\n> - `width`/`height`：宽高（默认自适应内容）\n> - `zIndex`：层级（默认为 100）\n> - `display`：显示方式（默认为 flex）\n\n工具栏容器默认设置 `display: flex`，子项目默认使用行布局（或根据 position 配置的方向改变）。你可以通过 `style` 自定义其外观和位置。\n\n### 异步加载工具栏项\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      getItems: async () => {\n        // 可以从服务器或其他异步源获取工具栏配置\n        const response = await fetch('/api/toolbar-config');\n        const items = await response.json();\n        return items;\n      },\n      onClick: (value) => {\n        // 处理点击事件\n      },\n    },\n  ],\n});\n```\n\n## 常见问题\n\n### 1. 工具栏图标不显示？\n\n- 检查是否使用了正确的内置图标 ID\n- 确保 CSS 样式未被覆盖或冲突\n\n### 2. 如何结合其他插件使用？\n\n工具栏常常与其他插件（如历史记录）配合使用：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'history',\n      key: 'history',\n    },\n    {\n      type: 'toolbar',\n      getItems: () => [\n        { id: 'undo', value: 'undo' },\n        { id: 'redo', value: 'redo' },\n      ],\n      onClick: (value) => {\n        const history = graph.getPluginInstance('history');\n        if (value === 'undo') {\n          history.undo();\n        } else if (value === 'redo') {\n          history.redo();\n        }\n      },\n    },\n  ],\n});\n```\n\n### 3. 如何动态更新工具栏？\n\n可以使用 `updatePlugin` 方法动态更新工具栏：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'toolbar',\n      key: 'my-toolbar',\n    },\n  ],\n});\n\n// 更新工具栏位置\ngraph.updatePlugin({\n  key: 'my-toolbar',\n  position: 'bottom-right',\n});\n```\n\n## 实际案例\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'toolbar',\n      position: 'top-left',\n      onClick: (item) => {\n        alert('item clicked:' + item);\n      },\n      getItems: () => {\n        // G6 内置了 9 个 icon，分别是 zoom-in、zoom-out、redo、undo、edit、delete、auto-fit、export、reset\n        return [\n          { id: 'zoom-in', value: 'zoom-in' },\n          { id: 'zoom-out', value: 'zoom-out' },\n          { id: 'redo', value: 'redo' },\n          { id: 'undo', value: 'undo' },\n          { id: 'edit', value: 'edit' },\n          { id: 'delete', value: 'delete' },\n          { id: 'auto-fit', value: 'auto-fit' },\n          { id: 'export', value: 'export' },\n          { id: 'reset', value: 'reset' },\n        ];\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Tooltip.en.md) -->\n---\ntitle: Tooltip\norder: 16\n---\n\n## Overview\n\nThe Tooltip plugin is used to display additional information when users hover over or click on elements in the graph. It helps users better understand the data in the graph and improves the interactive experience.\n\n## Use Cases\n\n- **Detailed Information Display**: When users need to understand detailed information about elements, use Tooltip to display this information\n- **Data Visualization Assistance**: In data visualization, Tooltip can display detailed information about data points in charts, helping users better understand the data\n- **Interactive Feedback**: Provide immediate visual feedback for user mouse operations\n\n## Basic Usage\n\nThe simplest Tooltip plugin configuration:\n\n```js\nconst graph = new Graph({\n  // Other configurations...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## Configuration Options\n\n| Property     | Description               | Type                                                                                                                                          | Default Value                         | Required |\n| ------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------- |\n| type         | Plugin type               | string                                                                                                                                        | `tooltip`                             | ✓        |\n| key          | Identifier                | string                                                                                                                                        | -                                     |          |\n| position     | Tooltip position          | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                                        | `top-right`                           |          |\n| enable       | Whether plugin is enabled | boolean \\| ((event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |          |\n| getContent   | Custom content            | (event: [IElementEvent](/en/api/event#event-object-properties), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |          |\n| onOpenChange | Show/hide callback        | (open: boolean) => void                                                                                                                       | -                                     |          |\n| trigger      | Trigger behavior          | `hover` \\| `click`                                                                                                                            | `hover`                               |\n| container    | Custom render container   | string \\| HTMLElement                                                                                                                         | -                                     |          |\n| offset       | Offset distance           | [number,number]                                                                                                                               | [10,10]                               |          |\n| enterable    | Whether pointer can enter | boolean                                                                                                                                       | false                                 |          |\n| title        | Title                     | string                                                                                                                                        | -                                     |\n| style        | Style object              | Record<string,any>                                                                                                                            | {'.tooltip': { visibility: 'hidden'}} |          |\n\n## Detailed Configuration\n\n### enable - Conditional Enable\n\nControls whether the plugin is enabled, supports passing functions to dynamically adjust enable logic.\n\n**Example: Enable Tooltip only for nodes**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Server Node' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Database Node' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: 'Connection' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // Enable only for nodes, not for edges\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>Node: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - Custom Content\n\nCustomize Tooltip content rendering, supports returning HTMLElement or string.\n\n**Example: Dynamically render custom HTML content**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: 'Server A', type: 'Application Server', status: 'Running', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: 'Database B', type: 'MySQL Database', status: 'Normal', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Type:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>Status:</strong>\n                <span style=\"color: ${item.data.status === 'Running' || item.data.status === 'Normal' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Memory:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Connections:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>Size:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">Connection Info</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Bandwidth:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>Latency:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return 'No information available';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - Trigger Mode\n\nControls the trigger behavior of Tooltip.\n\n**Available values:**\n\n- `hover`: Trigger when mouse enters element (default)\n- `click`: Trigger when mouse clicks element\n\n**Example: Click-triggered Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'Click me' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: 'Click me too' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              Click Triggered 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              Element ID: ${items[0].id}<br/>\n              Name: ${items[0].data?.name || 'Unnamed'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - Display Position\n\nControls the display position of Tooltip relative to mouse position.\n\n**Available values:**\n\n- `top`: Top\n- `bottom`: Bottom\n- `left`: Left\n- `right`: Right\n- `top-left`: Top left\n- `top-right`: Top right (default)\n- `bottom-left`: Bottom left\n- `bottom-right`: Bottom right\n\n**Example: Tooltips at different positions**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Display at top ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Display at bottom ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `Display at left ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `Display at right ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - Offset\n\nSet the offset for Tooltip display position, with mouse position as the base point.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'Default offset' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'Custom offset' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `Default offset [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // Offset 30px to the right, 10px up\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `Custom offset [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - Mouse Enterable\n\nControls whether the mouse pointer can enter the tooltip box, commonly used for scenarios requiring interaction within the Tooltip.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: 'User A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: 'User B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">User Actions</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>Name:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>Email:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('Send message to ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Message\n              </button>\n              <button onclick=\"alert('View ${item.data.name} details')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                Details\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - Style Customization\n\nCustomize Tooltip styles.\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: 'Dark Theme' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: 'Light Theme' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## Practical Examples\n\n- [Basic Tooltip](/en/examples/plugin/tooltip/#basic)\n- [Click-triggered Tooltip](/en/examples/plugin/tooltip/#click)\n- [Different tooltips for hover and click on the same element](/en/examples/plugin/tooltip/#dual)\n- [Custom styled Tooltip](/en/examples/plugin/tooltip/#custom-style)\n- [Asynchronous content loading Tooltip](/en/examples/plugin/tooltip/#async)\n\n## API\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Tooltip.zh.md) -->\n---\ntitle: 提示框 Tooltip\norder: 16\n---\n\n## 概述\n\nTooltip 插件用于在用户将鼠标悬停或点击图中的元素时，显示额外的信息。它可以帮助用户更好地理解图中的数据，提高交互体验。\n\n## 使用场景\n\n- **详细信息展示**：当用户需要了解元素的详细信息时，使用 Tooltip 提示框来展示这些信息\n- **数据可视化辅助**：在数据可视化中，Tooltip 可以显示图表中数据点的详细信息，帮助用户更好地理解数据\n- **交互反馈**：为用户的鼠标操作提供即时的视觉反馈\n\n## 基本使用\n\n最简单的 Tooltip 插件配置：\n\n```js\nconst graph = new Graph({\n  // 其他配置...\n  plugins: [\n    {\n      type: 'tooltip',\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性         | 描述                    | 类型                                                                                                                            | 默认值                                | 必选 |\n| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | ---- |\n| type         | 插件类型                | string                                                                                                                          | `tooltip`                             | ✓    |\n| key          | 标识符                  | string                                                                                                                          | -                                     |      |\n| position     | 气泡框位置              | `top` \\| `bottom` \\| `left` \\| `right` \\| `top-left` \\| `top-right` \\| `bottom-left` \\| `bottom-right`                          | `top-right`                           |      |\n| enable       | 插件是否启用            | boolean \\| ((event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => boolean)           | true                                  |      |\n| getContent   | 自定义内容              | (event: [IElementEvent](/api/event#事件对象属性), items: NodeData \\| EdgeData \\| ComboData[]) => Promise<HTMLElement \\| string> | -                                     |      |\n| onOpenChange | 显示隐藏的回调          | (open: boolean) => void                                                                                                         | -                                     |      |\n| trigger      | 触发行为                | `hover` \\| `click`                                                                                                              | `hover`                               |\n| container    | tooltip自定义渲染的容器 | string \\| HTMLElement                                                                                                           | -                                     |      |\n| offset       | 偏移距离                | [number,number]                                                                                                                 | [10,10]                               |      |\n| enterable    | 指针是否可以进入        | boolean                                                                                                                         | false                                 |      |\n| title        | 标题                    | string                                                                                                                          | -                                     |\n| style        | 样式对象                | Record<string,any>                                                                                                              | {'.tooltip': { visibility: 'hidden'}} |      |\n\n## 详细配置说明\n\n### enable - 条件启用\n\n控制插件是否启用，支持传入函数动态调整启用逻辑。\n\n**示例：只对节点启用 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '服务器节点' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '数据库节点' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { type: '连接线' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      // 只对节点启用，边不显示tooltip\n      enable: (e) => e.targetType === 'node',\n      getContent: (e, items) => {\n        return `<div>节点: ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### getContent - 自定义内容\n\n自定义渲染 Tooltip 内容，支持返回 HTMLElement 或 string。\n\n**示例：动态渲染自定义 HTML 内容**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    {\n      id: 'node1',\n      style: { x: 100, y: 100 },\n      data: { name: '服务器A', type: '应用服务器', status: '运行中', cpu: '45%', memory: '2.1GB' },\n    },\n    {\n      id: 'node2',\n      style: { x: 250, y: 100 },\n      data: { name: '数据库B', type: 'MySQL数据库', status: '正常', connections: 23, size: '500MB' },\n    },\n  ],\n  edges: [{ source: 'node1', target: 'node2', data: { bandwidth: '1Gbps', latency: '5ms' } }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      getContent: (e, items) => {\n        const item = items[0];\n\n        if (e.targetType === 'node') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333; border-bottom: 1px solid #eee; padding-bottom: 4px;\">\n                ${item.data.name}\n              </h4>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>类型:</strong> ${item.data.type}\n              </div>\n              <div style=\"margin: 4px 0; color: #666;\">\n                <strong>状态:</strong>\n                <span style=\"color: ${item.data.status === '运行中' || item.data.status === '正常' ? '#52c41a' : '#ff4d4f'}\">\n                  ${item.data.status}\n                </span>\n              </div>\n              ${item.data.cpu ? `<div style=\"margin: 4px 0; color: #666;\"><strong>CPU:</strong> ${item.data.cpu}</div>` : ''}\n              ${item.data.memory ? `<div style=\"margin: 4px 0; color: #666;\"><strong>内存:</strong> ${item.data.memory}</div>` : ''}\n              ${item.data.connections ? `<div style=\"margin: 4px 0; color: #666;\"><strong>连接数:</strong> ${item.data.connections}</div>` : ''}\n              ${item.data.size ? `<div style=\"margin: 4px 0; color: #666;\"><strong>大小:</strong> ${item.data.size}</div>` : ''}\n            </div>\n          `;\n        } else if (e.targetType === 'edge') {\n          return `\n            <div>\n              <h4 style=\"margin: 0 0 8px 0; color: #333;\">连接信息</h4>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>带宽:</strong> ${item.data.bandwidth}</div>\n              <div style=\"margin: 4px 0; color: #666;\"><strong>延迟:</strong> ${item.data.latency}</div>\n            </div>\n          `;\n        }\n\n        return '暂无信息';\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### trigger - 触发方式\n\n控制 Tooltip 的触发行为。\n\n**可选值：**\n\n- `hover`：鼠标移入元素时触发（默认）\n- `click`：鼠标点击元素时触发\n\n**示例：点击触发 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '点击我' } },\n    { id: 'node2', style: { x: 200, y: 100 }, data: { name: '也点击我' } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 350,\n  height: 200,\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.data.name,\n    },\n  },\n  plugins: [\n    {\n      type: 'tooltip',\n      trigger: 'click',\n      getContent: (e, items) => {\n        return `\n          <div>\n            <div style=\"color: #0369a1; font-weight: bold; margin-bottom: 4px;\">\n              点击触发 🖱️\n            </div>\n            <div style=\"color: #0c4a6e;\">\n              元素ID: ${items[0].id}<br/>\n              名称: ${items[0].data?.name || '未命名'}\n            </div>\n          </div>\n        `;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### position - 显示位置\n\n控制 Tooltip 相对于鼠标位置的显示位置。\n\n**可选值：**\n\n- `top`: 顶部\n- `bottom`: 底部\n- `left`: 左侧\n- `right`: 右侧\n- `top-left`: 顶部靠左\n- `top-right`: 顶部靠右（默认）\n- `bottom-left`: 底部靠左\n- `bottom-right`: 底部靠右\n\n**示例：不同位置的 Tooltip**\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: 'TOP' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: 'BOTTOM' } },\n    { id: 'node3', style: { x: 100, y: 250 }, data: { label: 'LEFT' } },\n    { id: 'node4', style: { x: 250, y: 250 }, data: { label: 'RIGHT' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 400,\n  data,\n  node: { style: { labelText: (d) => d.data.label } },\n  plugins: [\n    {\n      key: 'tooltip-top',\n      type: 'tooltip',\n      position: 'top',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `顶部显示 ⬆️`,\n      style: {\n        '.tooltip': {\n          background: ' #fff2e8',\n          border: '1px solid #ffa940',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-bottom',\n      type: 'tooltip',\n      position: 'bottom',\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `底部显示 ⬇️`,\n      style: {\n        '.tooltip': {\n          background: '#f6ffed',\n          border: '1px solid #73d13d',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-left',\n      type: 'tooltip',\n      position: 'left',\n      enable: (e, items) => items[0].id === 'node3',\n      getContent: () => `左侧显示 ⬅️`,\n      style: {\n        '.tooltip': {\n          background: '#fff1f0',\n          border: '1px solid #ff7875',\n          borderRadius: 4,\n        },\n      },\n    },\n    {\n      key: 'tooltip-right',\n      type: 'tooltip',\n      position: 'right',\n      enable: (e, items) => items[0].id === 'node4',\n      getContent: () => `右侧显示 ➡️`,\n      style: {\n        '.tooltip': {\n          background: '#f0f5ff',\n          border: '1px solid #597ef7',\n          borderRadius: 4,\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### offset - 偏移量\n\n设置 Tooltip 显示位置的偏移量，以鼠标位置为基点。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { label: '默认偏移' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { label: '自定义偏移' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 800,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-default',\n      type: 'tooltip',\n      enable: (e, items) => items[0].id === 'node1',\n      getContent: () => `默认偏移 [10,10]`,\n    },\n    {\n      key: 'tooltip-custom',\n      type: 'tooltip',\n      offset: [30, -10], // 向右偏移30px，向上偏移10px\n      enable: (e, items) => items[0].id === 'node2',\n      getContent: () => `自定义偏移 [30,-10]`,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### enterable - 鼠标可进入\n\n控制鼠标指针是否可以进入气泡框，常用于需要在 Tooltip 内进行交互的场景。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { name: '用户A', email: 'usera@example.com' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { name: '用户B', email: 'userb@example.com' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      type: 'tooltip',\n      enterable: true,\n      position: 'right',\n      getContent: (e, items) => {\n        const item = items[0];\n        return `\n          <div>\n            <h4 style=\"margin: 0 0 12px 0; color: #333;\">用户操作</h4>\n            <div style=\"margin-bottom: 8px; color: #666;\">\n              <strong>姓名:</strong> ${item.data.name}\n            </div>\n            <div style=\"margin-bottom: 12px; color: #666;\">\n              <strong>邮箱:</strong> ${item.data.email}\n            </div>\n            <div style=\"display: flex; gap: 8px;\">\n              <button onclick=\"alert('发送消息给 ${item.data.name}')\"\n                      style=\"padding: 4px 12px; background: #1890ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                发消息\n              </button>\n              <button onclick=\"alert('查看 ${item.data.name} 的详情')\"\n                      style=\"padding: 4px 12px; background: #52c41a; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;\">\n                详情\n              </button>\n            </div>\n          </div>\n        `;\n      },\n      style: {\n        '.tooltip': {\n          background: '#fff',\n          borderRadius: '8px',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.15)',\n          minWidth: '200px',\n        },\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### style - 样式自定义\n\n自定义 Tooltip 的样式。\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'node1', style: { x: 100, y: 100 }, data: { theme: 'dark', name: '深色主题' } },\n    { id: 'node2', style: { x: 250, y: 100 }, data: { theme: 'light', name: '浅色主题' } },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  width: 400,\n  height: 200,\n  data,\n  plugins: [\n    {\n      key: 'tooltip-dark',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'dark',\n      style: {\n        '.tooltip': {\n          background: '#1f1f1f',\n          color: '#fff',\n          border: '1px solid #333',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 4px 20px rgba(0,0,0,0.3)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>🌙 ${items[0].data.name}</div>`;\n      },\n    },\n    {\n      key: 'tooltip-light',\n      type: 'tooltip',\n      enable: (e, items) => items[0].data.theme === 'light',\n      style: {\n        '.tooltip': {\n          background: '#ffffff',\n          color: '#333',\n          border: '1px solid #d9d9d9',\n          borderRadius: '8px',\n          fontSize: '14px',\n          fontFamily: 'Arial, sans-serif',\n          boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n        },\n      },\n      getContent: (e, items) => {\n        return `<div>☀️ ${items[0].data.name}</div>`;\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n## 实际案例\n\n- [基础提示框](/examples/plugin/tooltip/#basic)\n- [点击触发 Tooltip](/examples/plugin/tooltip/#click)\n- [鼠标移入和点击同一元素时显示不同的提示框](/examples/plugin/tooltip/#dual)\n- [自定义样式的 Tooltip](/examples/plugin/tooltip/#custom-style)\n- [异步加载内容的 Tooltip](/examples/plugin/tooltip/#async)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Watermark.en.md) -->\n---\ntitle: Watermark\norder: 17\n---\n\n## Overview\n\nThe watermark plugin supports using text and images as watermarks. The principle is to add a `background-image` attribute to the div of the Graph container, and then control the position and style of the watermark through CSS. For text watermarks, a hidden canvas is used to convert the text into an image.\n\n## Use Cases\n\n- Add copyright or ownership marks to charts\n- Mark the status of charts during presentations or previews\n- Add anti-leakage marks to sensitive data\n\n## Basic Usage\n\nBelow is a simple example of initializing the Watermark plugin:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // Watermark text\n      opacity: 0.2, // Opacity\n      rotate: Math.PI / 12, // Rotation angle\n    },\n  ],\n});\n```\n\n## Online Experience\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## Configuration Options\n\n| Property             | Description                                              | Type                                                                        | Default Value | Required |\n| -------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | -------- |\n| type                 | Plugin type                                              | string                                                                      | `watermark`   | ✓        |\n| width                | Width of a single watermark                              | number                                                                      | 200           |          |\n| height               | Height of a single watermark                             | number                                                                      | 100           |          |\n| opacity              | Opacity of the watermark                                 | number                                                                      | 0.2           |          |\n| rotate               | Rotation angle of the watermark                          | number                                                                      | Math.PI / 12  |          |\n| imageURL             | Image watermark URL, higher priority than text watermark | string                                                                      | -             |          |\n| text                 | Watermark text content                                   | string                                                                      | -             |          |\n| textFill             | Color of the text watermark                              | string                                                                      | `#000`        |          |\n| textFontSize         | Font size of the text watermark                          | number                                                                      | 16            |          |\n| textFontFamily       | Font of the text watermark                               | string                                                                      | -             |          |\n| textFontWeight       | Font weight of the text watermark                        | string                                                                      | -             |          |\n| textFontVariant      | Font variant of the text watermark                       | string                                                                      | -             |          |\n| textAlign            | Text alignment of the watermark                          | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`      |          |\n| textBaseline         | Baseline alignment of the text watermark                 | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`      |          |\n| backgroundRepeat     | Repeat mode of the watermark                             | string                                                                      | `repeat`      |          |\n| backgroundAttachment | Background attachment behavior of the watermark          | string                                                                      | -             |          |\n| backgroundBlendMode  | Background blend mode of the watermark                   | string                                                                      | -             |          |\n| backgroundClip       | Background clip of the watermark                         | string                                                                      | -             |          |\n| backgroundColor      | Background color of the watermark                        | string                                                                      | -             |          |\n| backgroundImage      | Background image of the watermark                        | string                                                                      | -             |          |\n| backgroundOrigin     | Background origin of the watermark                       | string                                                                      | -             |          |\n| backgroundPosition   | Background position of the watermark                     | string                                                                      | -             |          |\n| backgroundPositionX  | Horizontal position of the watermark background          | string                                                                      | -             |          |\n| backgroundPositionY  | Vertical position of the watermark background            | string                                                                      | -             |          |\n| backgroundSize       | Background size of the watermark                         | string                                                                      | -             |          |\n\n## Code Examples\n\n### Text Watermark\n\nThe simplest text watermark configuration:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Image Watermark\n\nUse an image as a watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### Custom Styles\n\nYou can customize the style and position of the watermark:\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // Set font size\n      textFontFamily: 'Arial', // Set font\n      textFontWeight: 'bold', // Set font weight\n      textFill: '#1890ff', // Set text color\n      rotate: Math.PI / 6, // Set rotation angle\n      opacity: 0.15, // Set opacity\n      width: 180, // Set watermark width\n      height: 100, // Set watermark height\n      backgroundRepeat: 'space', // Set repeat mode\n      backgroundPosition: 'center', // Set position\n      textAlign: 'center', // Set text alignment\n      textBaseline: 'middle', // Set baseline alignment\n    },\n  ],\n});\n```\n\n## Real Cases\n\n- [Text Watermark](/examples/plugin/watermark/#text)\n- [Image Watermark](/examples/plugin/watermark/#repeat)\n\n\n<!-- Skill/Rule: Plugin Skill (packages/site/docs/manual/plugin/Watermark.zh.md) -->\n---\ntitle: 水印 Watermark\norder: 17\n---\n\n## 概述\n\n水印插件支持使用文本和图片作为水印，实现原理是在 Graph 容器的 div 上加上 `background-image` 属性，然后通过 CSS 来控制水印的位置和样式。对于文本水印，会使用隐藏 canvas 将文本转换为图片的方式来实现。\n\n## 使用场景\n\n- 为图表添加版权或所有权标识\n- 在演示或预览时标记图表的状态\n- 为敏感数据添加防泄露标记\n\n## 基本用法\n\n以下是一个简单的 Watermark 插件初始化示例：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph', // 水印文本\n      opacity: 0.2, // 透明度\n      rotate: Math.PI / 12, // 旋转角度\n    },\n  ],\n});\n```\n\n## 在线体验\n\n<embed src=\"@/common/api/plugins/watermark.md\"></embed>\n\n## 配置项\n\n| 属性                 | 描述                               | 类型                                                                        | 默认值       | 必选 |\n| -------------------- | ---------------------------------- | --------------------------------------------------------------------------- | ------------ | ---- |\n| type                 | 插件类型                           | string                                                                      | `watermark`  | ✓    |\n| width                | 单个水印的宽度                     | number                                                                      | 200          |      |\n| height               | 单个水印的高度                     | number                                                                      | 100          |      |\n| opacity              | 水印的透明度                       | number                                                                      | 0.2          |      |\n| rotate               | 水印的旋转角度                     | number                                                                      | Math.PI / 12 |      |\n| imageURL             | 图片水印的地址，优先级高于文本水印 | string                                                                      | -            |      |\n| text                 | 水印文本内容                       | string                                                                      | -            |      |\n| textFill             | 文本水印的颜色                     | string                                                                      | `#000`       |      |\n| textFontSize         | 文本水印的字体大小                 | number                                                                      | 16           |      |\n| textFontFamily       | 文本水印的字体                     | string                                                                      | -            |      |\n| textFontWeight       | 文本水印的字体粗细                 | string                                                                      | -            |      |\n| textFontVariant      | 文本水印的字体变体                 | string                                                                      | -            |      |\n| textAlign            | 文本水印的对齐方式                 | `center` \\| `end` \\| `left` \\| `right` \\| `start`                           | `center`     |      |\n| textBaseline         | 文本水印的基线对齐方式             | `alphabetic` \\| `bottom` \\| `hanging` \\| `ideographic` \\| `middle` \\| `top` | `middle`     |      |\n| backgroundRepeat     | 水印的重复方式                     | string                                                                      | `repeat`     |      |\n| backgroundAttachment | 水印的背景定位行为                 | string                                                                      | -            |      |\n| backgroundBlendMode  | 水印的背景混合模式                 | string                                                                      | -            |      |\n| backgroundClip       | 水印的背景裁剪                     | string                                                                      | -            |      |\n| backgroundColor      | 水印的背景颜色                     | string                                                                      | -            |      |\n| backgroundImage      | 水印的背景图片                     | string                                                                      | -            |      |\n| backgroundOrigin     | 水印的背景原点                     | string                                                                      | -            |      |\n| backgroundPosition   | 水印的背景位置                     | string                                                                      | -            |      |\n| backgroundPositionX  | 水印的背景水平位置                 | string                                                                      | -            |      |\n| backgroundPositionY  | 水印的背景垂直位置                 | string                                                                      | -            |      |\n| backgroundSize       | 水印的背景大小                     | string                                                                      | -            |      |\n\n## 代码示例\n\n### 文本水印\n\n最简单的文本水印配置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: { type: 'grid' },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6: Graph Visualization',\n      textFontSize: 14,\n      textFontFamily: 'Microsoft YaHei',\n      fill: 'rgba(0, 0, 0, 0.1)',\n      rotate: Math.PI / 12,\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 图片水印\n\n使用图片作为水印：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      imageURL: 'https://example.com/logo.png',\n      width: 100,\n      height: 50,\n      opacity: 0.1,\n    },\n  ],\n});\n```\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [{ id: 'node-0' }, { id: 'node-1' }, { id: 'node-2' }, { id: 'node-3' }, { id: 'node-4' }, { id: 'node-5' }],\n  edges: [\n    { source: 'node-0', target: 'node-1' },\n    { source: 'node-0', target: 'node-2' },\n    { source: 'node-0', target: 'node-3' },\n    { source: 'node-0', target: 'node-4' },\n    { source: 'node-1', target: 'node-0' },\n    { source: 'node-2', target: 'node-0' },\n    { source: 'node-3', target: 'node-0' },\n    { source: 'node-4', target: 'node-0' },\n    { source: 'node-5', target: 'node-0' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  data,\n  layout: {\n    type: 'grid',\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n  plugins: [\n    {\n      type: 'watermark',\n      width: 200,\n      height: 100,\n      rotate: Math.PI / 12,\n      imageURL: 'https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg',\n    },\n  ],\n});\n\ngraph.render();\n```\n\n### 自定义样式\n\n可以自定义水印的样式和位置：\n\n```js\nconst graph = new Graph({\n  plugins: [\n    {\n      type: 'watermark',\n      text: 'G6 Graph',\n      textFontSize: 20, // 设置字体大小\n      textFontFamily: 'Arial', // 设置字体\n      textFontWeight: 'bold', // 设置字体粗细\n      textFill: '#1890ff', // 设置文字颜色\n      rotate: Math.PI / 6, // 设置旋转角度\n      opacity: 0.15, // 设置透明度\n      width: 180, // 设置水印宽度\n      height: 100, // 设置水印高度\n      backgroundRepeat: 'space', // 设置重复方式\n      backgroundPosition: 'center', // 设置位置\n      textAlign: 'center', // 设置文本对齐\n      textBaseline: 'middle', // 设置基线对齐\n    },\n  ],\n});\n```\n\n## 实际案例\n\n- [文本水印](/examples/plugin/watermark/#text)\n- [图片水印](/examples/plugin/watermark/#repeat)\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/custom-palette.en.md) -->\n---\ntitle: Custom Palette\norder: 4\n---\n\n## Overview\n\n[Core Concepts - Palette](/en/manual/core-concept/palette) mentions that G6 supports discrete palettes and continuous palettes. A discrete palette is essentially an array of colors, while a continuous palette is a color interpolator.\n\nTherefore, customizing a palette also adopts these two methods, and the following sections will introduce how to customize discrete and continuous palettes, respectively.\n\n## Implement Palette\n\n### Discrete Palette\n\nYou can simply define a string array that contains color values. Supported color values include: RGB color values, hexadecimal color values, and color names. Below is an example of a discrete palette:\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### Continuous Palette\n\nA continuous palette requires the definition of a color interpolator. The interpolator is a function that accepts a numerical value as a parameter and returns a color value. Below is an example of a continuous palette:\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can register a palette using the `register` method provided by G6. For more details, please refer to [Register Palette](/en/manual/core-concept/palette#register-palette)\n\n## Use Without Registration\n\nIn addition to registration, you can also bypass the registration mechanism and directly pass the palette value at the location where the palette is needed, for example:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // Pass in a color array.\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Pass in an interpolator\n    }\n  }\n}\n```\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/custom-palette.zh.md) -->\n---\ntitle: 自定义色板\norder: 4\n---\n\n## 概述\n\n[色板](/manual/theme/palette) 中提到，G6 支持离散色板和连续色板，其中离散色板本质上是一个颜色数组，而连续色板是一个颜色插值器。\n\n因此自定义色板也采用这两种方式，下面分别介绍如何自定义离散色板和连续色板。\n\n## 实现色板\n\n### 离散色板\n\n直接定义一个包含颜色值的字符串数组即可，颜值值支持：RGB 色值、16 进制、颜色名，下面是一组离散色板示例：\n\n```typescript\nconst hex = ['#FF0000', '#00FF00', '#0000FF'];\n\nconst color = ['red', 'green', 'blue'];\n\nconst rgb = ['rgb(255, 0, 0)', 'rgb(0, 255, 0)', 'rgb(0, 0, 255)'];\n```\n\n### 连续色板\n\n连续色板需要定义一个颜色插值器，插值器是一个函数，接受一个数值参数，返回一个颜色值，下面是一个连续色板示例：\n\n```typescript\nconst color = (value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n通过 G6 提供的 register 方法注册即可，详见[注册色板](/manual/theme/palette#注册色板)\n\n## 非注册方式使用\n\n除此之外，你也可以在需要使用色板的位置跳过注册机制直接传入色板值，例如：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group',\n      field: 'category',\n      color: ['#5B8FF9', '#61DDAA', '#F6BD16'], // 传入颜色数组\n    }\n  },\n  edge: {\n    palette: {\n      type: 'value',\n      field: 'value',\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 传入插值器\n    }\n  }\n}\n```\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/custom-theme.en.md) -->\n---\ntitle: Custom Theme\norder: 2\n---\n\n## Overview\n\nIn G6, the theme is a subset of Graph Options and includes configurations related to the canvas and element styles. A theme can help you quickly switch between different graph styles.\n\n## Custom Theme\n\nFor element styles, the configurations within a theme are static and do not support the use of callback functions to dynamically calculate styles. Additionally, `type` is also not supported for configuration within a theme. A theme includes the following configurations:\n\n- `background`: Canvas background color\n- `node`: Node style\n- `edge`: Edge style\n- `combo`: Combo style\n\nBelow is a simple example of a theme configuration:\n\n```typescript\nconst theme = {\n  background: '#fff',\n  node: {\n    style: {\n      fill: '#e1f3fe',\n      lineWidth: 0,\n    },\n    selected: {\n      style: {\n        fill: '#3b71d6',\n        lineWidth: 1,\n      },\n    },\n  },\n  edge: {\n    // ...\n  },\n  combo: {\n    // ...\n  },\n};\n```\n\n❌ Incorrect Example\n\n```typescript\nconst theme = {\n  node: {\n    // ❌ The theme does not support configuring element types\n    type: 'rect',\n    style: {\n      // ❌ The theme does not support callback functions\n      fill: (d) => d.style.color,\n    },\n  },\n};\n```\n\n:::warning{title=Note}\nFor element state styles, please ensure that every property in the state style has a corresponding default style in the default style, otherwise it may result in the inability to clear the state style.\n:::\n\n## Register Theme\n\nYou can register a theme using the `register` method provided by G6. Here is an example:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.THEME, 'custom-theme', theme);\n```\n\n## Configure Theme\n\nTo enable and configure a theme, you need to pass the `theme` option when instantiating the `Graph`:\n\n```typescript\n{\n  theme: 'custom-theme',\n}\n```\n\n### Switch Theme\n\nAfter the `Graph` instance is created, you can switch themes by using the [setTheme](/en/api/theme#graphsetthemetheme) method:\n\n```typescript\ngraph.setTheme('dark');\n```\n\nAdditionally, you can also obtain the current theme by using the `getTheme` method:\n\n```typescript\ngraph.getTheme();\n// => 'dark'\n```\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/custom-theme.zh.md) -->\n---\ntitle: 自定义主题\norder: 2\n---\n\n除了使用内置主题外，G6 还支持创建自定义主题来满足特定的视觉需求。本文将介绍如何创建和使用自定义主题。\n\n## 创建自定义主题\n\n一个自定义主题需要遵循主题的基本结构，包含画布背景色和元素样式配置：\n\n```javascript\nconst customTheme = {\n  // 1. 画布背景色\n  background: '#f0f0f0',\n\n  // 2. 节点配置\n  node: {\n    // 调色板配置\n    palette: {\n      type: 'group',\n      color: ['#1783FF', '#00C9C9' /* 自定义颜色... */],\n    },\n    // 基础样式\n    style: {\n      fill: '#fff',\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他节点样式\n    },\n    // 状态样式\n    state: {\n      selected: {\n        fill: '#e8f3ff',\n        stroke: '#1783FF',\n      },\n      // ... 其他状态样式\n    },\n  },\n\n  // 3. 边配置\n  edge: {\n    style: {\n      stroke: '#d9d9d9',\n      lineWidth: 1,\n      // ... 其他边样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n\n  // 4. Combo 配置\n  combo: {\n    style: {\n      fill: '#f7f7f7',\n      stroke: '#d9d9d9',\n      // ... 其他 Combo 样式\n    },\n    state: {\n      // ... 状态样式\n    },\n  },\n};\n```\n\n## 使用限制\n\n在创建自定义主题时，需要注意以下限制：\n\n1. **仅支持静态值**\n\n   ```javascript\n   // ❌ 错误示例：不支持回调函数\n   const theme = {\n     node: {\n       style: {\n         fill: (d) => d.style.color,\n       },\n     },\n   };\n   ```\n\n2. **不支持配置元素类型**\n\n   ```javascript\n   // ❌ 错误示例：不支持在主题中配置元素类型\n   const theme = {\n     node: {\n       type: 'rect',\n       style: {\n         fill: '#fff',\n       },\n     },\n   };\n   ```\n\n3. **状态样式需要对应默认样式**\n   ```javascript\n   // ✅ 正确示例：状态样式的属性在默认样式中都有定义\n   const theme = {\n     node: {\n       style: {\n         fill: '#fff',\n         stroke: '#000',\n       },\n       state: {\n         selected: {\n           fill: '#e8f3ff',\n           stroke: '#1783FF',\n         },\n       },\n     },\n   };\n   ```\n\n## 应用自定义主题\n\n先注册主题，然后通过名称引用：\n\n```javascript\n// 1. 注册主题\nimport { register, ExtensionCategory } from '@antv/g6';\nregister(ExtensionCategory.THEME, 'custom-theme', customTheme);\n\n// 2. 使用主题\nconst graph = new Graph({\n  theme: 'custom-theme',\n  // ... 其他配置\n});\n```\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/overview.en.md) -->\n---\ntitle: Theme Overview\norder: 1\n---\n\n## Overview\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/overview.zh.md) -->\n---\ntitle: 主题总览\norder: 1\n---\n\n## 概述\n\nG6 中的主题是 Graph Options 的子集，它包含了关于画布和元素样式的配置。多主题可以帮助你快速地切换不同的图样式。\n\n<image width=\"350\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 主题结构\n\n一个主题由以下四个部分组成：\n\n1. **画布背景色 (background)**\n\n   - 控制整个画布的背景颜色\n\n2. **节点配置 (node)**\n\n   - 基础样式：填充色、描边、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于节点分组的颜色配置\n   - 状态样式：不同状态下的样式配置（选中、激活、禁用等）\n   - 动画配置：节点的动画效果配置\n\n3. **边配置 (edge)**\n\n   - 基础样式：线条样式、箭头、标签等静态视觉属性\n   - [调色板](/manual/theme/palette)：用于边分组的颜色配置\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：边的动画效果配置\n\n4. **Combo 配置 (combo)**\n   - 基础样式：填充、描边、折叠按钮等静态视觉属性\n   - 状态样式：不同状态下的样式配置\n   - 动画配置：Combo 的动画效果配置\n\n> 注意：主题中的样式配置仅支持静态值，不支持回调函数形式的动态配置。如需动态样式，请使用图的配置项。\n\n## 内置主题\n\nG6 默认提供两种内置主题：\n\n### 亮色主题（默认）\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SPCES62UzzAAAAAAAAAAAAAAemJ7AQ/original\" alt=\"亮色主题\" />\n\n<details><summary>查看亮色主题完整配置项</summary>\n\n```js\nconst lightTheme = {\n  background: '#ffffff',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#000000',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#000000',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#000000',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#000000',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fillOpacity: 0.25,\n        iconOpacity: 0.85,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.06,\n        fill: '#1B324F',\n        fillOpacity: 0.06,\n        iconFill: '#1B324F',\n        iconOpacity: 0.25,\n        labelFill: '#000000',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.06,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#99ADD1',\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#99ADD1',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#99ADD1',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#1B324F',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#d9d9d9',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#ffffff',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#99ADD1',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99ADD1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#ffffff',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#000000',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99ADD1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d9d9d9',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#d9d9d9',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n### 暗色主题\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*qTlLSoAbaXYAAAAAAAAAAAAAemJ7AQ/original\" alt=\"暗色主题\" />\n\n<details><summary>查看暗色主题完整配置项</summary>\n\n```js\nconst darkTheme = {\n  background: '#000000',\n  node: {\n    palette: {\n      type: 'group',\n      color: [\n        '#1783FF',\n        '#00C9C9',\n        '#F08F56',\n        '#D580FF',\n        '#7863FF',\n        '#DB9D0D',\n        '#60C42D',\n        '#FF80CA',\n        '#2491B3',\n        '#17C76F',\n      ],\n    },\n    style: {\n      donutOpacity: 1,\n      badgeBackgroundOpacity: 1,\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgePadding: [0, 4],\n      badgePalette: ['#7E92B5', '#F4664A', '#FFBE3A'],\n      fill: '#1783ff',\n      fillOpacity: 1,\n      halo: false,\n      iconFill: '#fff',\n      iconOpacity: 1,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelFill: '#ffffff',\n      labelFillOpacity: 0.85,\n      labelLineHeight: 16,\n      labelPadding: [0, 2],\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelOffsetY: 2,\n      lineWidth: 0,\n      portFill: '#1783ff',\n      portLineWidth: 1,\n      portStroke: '#d0e4ff',\n      portStrokeOpacity: 0.65,\n      size: 32,\n      stroke: '#d0e4ff',\n      strokeOpacity: 1,\n      zIndex: 2,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloLineWidth: 24,\n        haloStrokeOpacity: 0.45,\n        labelFontSize: 12,\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n      },\n      active: {\n        halo: true,\n        haloLineWidth: 12,\n        haloStrokeOpacity: 0.25,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 4,\n        stroke: '#d0e4ff',\n        strokeOpacity: 0.85,\n      },\n      inactive: {\n        badgeBackgroundOpacity: 0.45,\n        donutOpacity: 0.45,\n        fillOpacity: 0.45,\n        iconOpacity: 0.45,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.45,\n        strokeOpacity: 0.45,\n      },\n      disabled: {\n        badgeBackgroundOpacity: 0.25,\n        donutOpacity: 0.25,\n        fill: '#D0E4FF',\n        fillOpacity: 0.25,\n        iconFill: '#D0E4FF',\n        iconOpacity: 0.25,\n        labelFill: '#ffffff',\n        labelFillOpacity: 0.25,\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'node-expand',\n      collapse: 'node-collapse',\n      update: [{ fields: ['x', 'y', 'fill', 'stroke'] }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n  edge: {\n    palette: {\n      type: 'group',\n      color: [\n        '#637088',\n        '#0F55A6',\n        '#008383',\n        '#9C5D38',\n        '#8B53A6',\n        '#4E40A6',\n        '#8F6608',\n        '#3E801D',\n        '#A65383',\n        '#175E75',\n        '#0F8248',\n      ],\n    },\n    style: {\n      badgeBackgroundFill: '#637088',\n      badgeFill: '#fff',\n      badgeFontSize: 8,\n      badgeOffsetX: 10,\n      fillOpacity: 1,\n      halo: false,\n      haloLineWidth: 12,\n      haloStrokeOpacity: 1,\n      increasedLineWidthForHitTesting: 2,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [4, 4, 4, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      labelPlacement: 'center',\n      labelTextBaseline: 'middle',\n      lineWidth: 1,\n      stroke: '#637088',\n      strokeOpacity: 1,\n      zIndex: 1,\n    },\n    state: {\n      selected: {\n        halo: true,\n        haloStrokeOpacity: 0.25,\n        labelFontSize: 14,\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      active: {\n        halo: true,\n        haloStrokeOpacity: 0.15,\n      },\n      highlight: {\n        labelFontWeight: 'bold',\n        lineWidth: 3,\n      },\n      inactive: {\n        stroke: '#D0E4FF',\n        fillOpacity: 0.08,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.08,\n        badgeBackgroundOpacity: 0.25,\n      },\n      disabled: {\n        stroke: '#637088',\n        fillOpacity: 0.45,\n        strokeOpacity: 0.45,\n        labelOpacity: 0.25,\n        badgeBackgroundOpacity: 0.45,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      expand: 'path-in',\n      collapse: 'path-out',\n      show: 'fade',\n      hide: 'fade',\n      update: [{ fields: ['sourceNode', 'targetNode'] }, { fields: ['stroke'], shape: 'key' }],\n      translate: [{ fields: ['sourceNode', 'targetNode'] }],\n    },\n  },\n  combo: {\n    style: {\n      collapsedMarkerFill: '#000000',\n      collapsedMarkerFontSize: 12,\n      collapsedMarkerFillOpacity: 1,\n      collapsedSize: 32,\n      collapsedFillOpacity: 1,\n      fill: '#fdfdfd',\n      halo: false,\n      haloLineWidth: 12,\n      haloStroke: '#99add1',\n      haloStrokeOpacity: 0.25,\n      labelBackground: false,\n      labelBackgroundFill: '#000000',\n      labelBackgroundLineWidth: 0,\n      labelBackgroundOpacity: 0.75,\n      labelBackgroundPadding: [2, 4, 2, 4],\n      labelFill: '#ffffff',\n      labelFontSize: 12,\n      labelFontWeight: 400,\n      labelOpacity: 1,\n      lineDash: 0,\n      lineWidth: 1,\n      fillOpacity: 0.04,\n      strokeOpacity: 1,\n      padding: 10,\n      stroke: '#99add1',\n    },\n    state: {\n      selected: {\n        halo: true,\n        labelFontSize: 14,\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      active: {\n        halo: true,\n      },\n      highlight: {\n        labelFontWeight: 700,\n        lineWidth: 4,\n      },\n      inactive: {\n        fillOpacity: 0.65,\n        labelOpacity: 0.25,\n        strokeOpacity: 0.65,\n      },\n      disabled: {\n        fill: '#d0e4ff',\n        fillOpacity: 0.25,\n        labelOpacity: 0.25,\n        stroke: '#969696',\n        strokeOpacity: 0.25,\n      },\n    },\n    animation: {\n      enter: 'fade',\n      exit: 'fade',\n      show: 'fade',\n      hide: 'fade',\n      expand: 'combo-expand',\n      collapse: 'combo-collapse',\n      update: [{ fields: ['x', 'y'] }, { fields: ['fill', 'stroke', 'lineWidth'], shape: 'key' }],\n      translate: [{ fields: ['x', 'y'] }],\n    },\n  },\n};\n```\n\n</details>\n\n## 使用主题\n\n### 配置主题\n\n在创建图时通过 `theme` 选项指定要使用的主题：\n\n```javascript\nconst graph = new Graph({\n  theme: 'light', // 或 'dark'\n  // ... 其他配置\n});\n```\n\n### 切换主题\n\n创建图后，可以通过 `setTheme` 方法动态切换主题：\n\n```javascript\n// 切换到暗色主题\ngraph.setTheme('dark');\n\n// 获取当前主题\nconst currentTheme = graph.getTheme(); // 'dark'\n```\n\n## 样式优先级\n\n在 G6 中，元素的最终样式由多个层级的样式合并而成，按优先级从低到高排序：\n\n**⭐️ 主题默认样式** < 调色板样式 < 数据样式 < 图的默认样式 < **⭐️ 主题状态样式** < 图的状态样式\n\n详细说明：\n\n1. **主题默认样式**：主题系统提供的基础样式\n2. **调色板样式**：基于主题调色板配置的自动着色样式\n3. **数据样式**：在数据中定义的样式\n4. **图的默认样式**：通过图的配置项设置的样式\n5. **主题状态样式**：主题中定义的状态样式\n6. **图的状态样式**：通过图的配置项设置的状态样式\n\n更多关于自定义主题的内容，请参考[自定义主题](/manual/theme/custom-theme)。\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/palette.en.md) -->\n---\ntitle: Palette\norder: 3\n---\n\n## Overview\n\nA palette refers to a set of predefined color collections that help users more conveniently select colors. In G6, a palette is a common option that allows users to configure the colors of elements such as nodes, edges, and links through the palette.\n\nPalettes are divided into two types: `discrete palette` and `continuous palette`.\n\nA discrete palette is an array of colors used to map discrete values within elements to different colors, such as the type of nodes, the relationship of edges, etc. Below is a simple example of a discrete palette:\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\nA continuous palette is an interpolator that takes a value between 0 and 1 and returns the corresponding color. It is used to map continuous values within elements to different colors, such as the degree of nodes, the weight of edges, etc. Below is a simple example of a continuous palette:\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## Register Palette\n\nYou can directly use the built-in palettes, but if you want to use other palettes, you need to register them first:\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=note}\n\nDuring the process of registering a palette, there is no distinction made between discrete and continuous palettes. It is necessary to ensure the consistency between the palette type and the data type when using the palette.\n:::\n\n### Built-in Palettes\n\nCurrently, G6 has 5 sets of commonly used discrete palettes that users can directly utilize:\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## Configure Palette\n\nCurrently, the configuration of palettes is mainly focused on elements, taking nodes as an example:\n\n### Discrete Palette\n\n1. Default Configuration: By directly setting the value of `palette` to the name of the palette, each node will be assigned a different color by default\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral is the Palette Name\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> When the number of elements exceeds the number of colors in the palette, the colors in the palette will be reused in a cyclic manner.\n\n2. Standard Configuration: The attributes for configuring a discrete palette include: `type: 'group'`, `field`, `color`, `invert`.\n\nAmong them, `type: 'group'` explicitly specifies that the current palette type is a discrete palette; `field` designates the field for grouping in the element data; `color` is the name of the palette; `invert` indicates whether to invert the palette.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\nIn the data, `node-1` and `node-4` belong to category A, `node-2` and `node-5` belong to category B, `node-3` and `node-6` belong to category C.\n\nConfigure the color of the nodes in such a way that nodes of the same category have the same color:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // Specify the palette type as a categorical palette.\n      field: 'category', // Specify the grouping field in the data.\n      color: 'tableau', // Use a Tableau-like palette.\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### Continuous Palette\n\nA continuous palette only supports standard configuration methods, with configuration properties including: `type: 'value'`, `field`, `color`, `invert`.\n\nGiven a set of example data:\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\nNow, create an interpolator that maps the maximum value to red (`rgb(255, 0, 0)`) and the minimum value to black (`rgb(0, 0, 0)`):\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\nConfigure the following so that the color of the nodes is mapped to different colors based on the value of the `value` field in the data:\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // Specify the palette type as a continuous palette\n      field: 'value', // Specify the numerical field in the data\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // Use an interpolator\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=note}\n\nThe built-in continuous palette does not support specifying a value range. If there is a need for more complex color mapping, it can be customized within the style mapping.\n:::\n\n## Custom Palette\n\nIf the built-in palette does not meet your requirements, you can customize the palette. For details, please refer to [Custom Palette](/en/manual/custom-extension/palette).\n\n## Priority\n\nThe palette generates styles based on the type of element. For nodes and combos, the color is mapped to the `fill` attribute; for edges, the color is mapped to the `stroke` attribute.\n\nIf both a palette and a style mapping are configured, the style mapping will override the palette colors. In the following example, the color of the nodes is always red:\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n\n\n<!-- Skill/Rule: Theme Skill (packages/site/docs/manual/theme/palette.zh.md) -->\n---\ntitle: 色板\norder: 3\n---\n\n## 概述\n\n色板(Palette)是指一组预定义的颜色集合，用于帮助用户更方便的选择颜色。在 G6 中，色板是一种常见的配置项，用户可以通过色板来配置节点、边、连线等元素的颜色。\n\n色板分为`离散色板`和`连续色板`两种类型。\n\n离散色板是一组颜色数组，用于将元素中的离散值映射到不同的颜色上，例如节点的类型、边的关系等。下面是一个简单的离散色板示例：\n\n```typescript\n['#5B8FF9', '#61DDAA', '#F6BD16', '#F6903D', '#F08BB4'];\n```\n\n连续色板是一个插值器，输入 0~1 的值，返回对应的颜色，用于将元素中的连续值映射到不同的颜色上，例如节点的度数、边的权重等。下面是一个简单的连续色板示例：\n\n```typescript\n(value: number) => `rgb(${value * 255}, 0, 0)`;\n```\n\n## 注册色板\n\n你可以直接使用内置色板，如果想使用其他色板，需要先进行注册：\n\n```typescript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { CustomPalette } from 'package-name/or/path-to-your-custom-palette';\n\nregister(ExtensionCategory.PALETTE, 'custom-palette', CustomPalette);\n```\n\n:::warning{title=注意}\n在注册色板过程中并不会区分离散色板和连续色板，使用色板过程中需要自行保证色板类型和数据类型的一致性。\n:::\n\n### 内置色板\n\n目前 G6 内置了 5 套常用的离散色板，用户可以直接使用：\n\n- spectral\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(158, 1, 66);\"></div><div style=\"background: rgb(213, 62, 79);\"></div><div style=\"background: rgb(244, 109, 67);\"></div><div style=\"background: rgb(253, 174, 97);\"></div><div style=\"background: rgb(254, 224, 139);\"></div><div style=\"background: rgb(255, 255, 191);\"></div><div style=\"background: rgb(230, 245, 152);\"></div><div style=\"background: rgb(171, 221, 164);\"></div><div style=\"background: rgb(102, 194, 165);\"></div><div style=\"background: rgb(50, 136, 189);\"></div><div style=\"background: rgb(94, 79, 162);\"></div></div>\n\n- tableau\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(78, 121, 167);\"></div><div style=\"background: rgb(242, 142, 44);\"></div><div style=\"background: rgb(225, 87, 89);\"></div><div style=\"background: rgb(118, 183, 178);\"></div><div style=\"background: rgb(89, 161, 79);\"></div><div style=\"background: rgb(237, 201, 73);\"></div><div style=\"background: rgb(175, 122, 161);\"></div><div style=\"background: rgb(255, 157, 167);\"></div><div style=\"background: rgb(156, 117, 95);\"></div><div style=\"background: rgb(186, 176, 171);\"></div></div>\n\n- oranges\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(255, 245, 235);\"></div><div style=\"background: rgb(254, 230, 206);\"></div><div style=\"background: rgb(253, 208, 162);\"></div><div style=\"background: rgb(253, 174, 107);\"></div><div style=\"background: rgb(253, 141, 60);\"></div><div style=\"background: rgb(241, 105, 19);\"></div><div style=\"background: rgb(217, 72, 1);\"></div><div style=\"background: rgb(166, 54, 3);\"></div><div style=\"background: rgb(127, 39, 4);\"></div></div>\n\n- greens\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 252, 245);\"></div><div style=\"background: rgb(229, 245, 224);\"></div><div style=\"background: rgb(199, 233, 192);\"></div><div style=\"background: rgb(161, 217, 155);\"></div><div style=\"background: rgb(116, 196, 118);\"></div><div style=\"background: rgb(65, 171, 93);\"></div><div style=\"background: rgb(35, 139, 69);\"></div><div style=\"background: rgb(0, 109, 44);\"></div><div style=\"background: rgb(0, 68, 27);\"></div></div>\n\n- blues\n\n<div style=\"display: flex; width: 600px; height: 20px;\"><style>div{flex-grow:1}</style><div style=\"background: rgb(247, 251, 255);\"></div><div style=\"background: rgb(222, 235, 247);\"></div><div style=\"background: rgb(198, 219, 239);\"></div><div style=\"background: rgb(158, 202, 225);\"></div><div style=\"background: rgb(107, 174, 214);\"></div><div style=\"background: rgb(66, 146, 198);\"></div><div style=\"background: rgb(33, 113, 181);\"></div><div style=\"background: rgb(8, 81, 156);\"></div><div style=\"background: rgb(8, 48, 107);\"></div></div>\n\n## 配置色板\n\n目前开放色板配置的地方主要以元素为主，以节点为例：\n\n### 离散色板\n\n1. 默认配置，直接配置 `palette` 的值为色板名，会默认为每个节点分配不同的颜色\n\n```typescript\n{\n  node: {\n    palette: 'spectral', // spectral 为色板名\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/default-config.md\"></embed>\n\n> 当元素数量超过色板颜色数量时，会循环使用色板中的颜色\n\n2. 标准配置，离散色板配置属性包括：`type: 'group'`，`field`，`color`，`invert`\n\n其中 `type: 'group'` 显式指定了当前色板类型为离散色板；`field` 指定元素数据中的分组字段；`color` 为色板名；`invert` 为是否反转色板。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-2\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-3\", \"data\": { \"category\": \"C\" } },\n    { \"id\": \"node-4\", \"data\": { \"category\": \"A\" } },\n    { \"id\": \"node-5\", \"data\": { \"category\": \"B\" } },\n    { \"id\": \"node-6\", \"data\": { \"category\": \"C\" } }\n  ]\n}\n```\n\n数据中 `node-1`，`node-4` 属于 A 类别，`node-2`，`node-5` 属于 B 类别，`node-3`，`node-6` 属于 C 类别。\n\n通过以下方式配置节点的颜色，使得同类别的节点颜色相同：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'group', // 指定色板类型为分类色板\n      field: 'category', // 指定数据中的分组字段\n      color: 'tableau', // 使用 tableau 色板\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/standard-config.md\"></embed>\n\n### 连续色板\n\n连续色板只支持标准方式配置，配置属性包括：`type: 'value'`，`field`，`color`，`invert`。\n\n给定一组示例数据：\n\n```json\n{\n  \"nodes\": [\n    { \"id\": \"node-1\", \"data\": { \"value\": 0 } },\n    { \"id\": \"node-2\", \"data\": { \"value\": 20 } },\n    { \"id\": \"node-3\", \"data\": { \"value\": 40 } },\n    { \"id\": \"node-4\", \"data\": { \"value\": 60 } },\n    { \"id\": \"node-5\", \"data\": { \"value\": 80 } },\n    { \"id\": \"node-6\", \"data\": { \"value\": 100 } }\n  ]\n}\n```\n\n现在创建一个插值器，将最大值映射为红色(`rgb(255, 0, 0)`)，最小值映射为黑色(`rgb(0, 0, 0)`)：\n\n```typescript\n(value) => `rgb(${value * 255}, 0, 0)`;\n```\n\n通过以下配置使得节点的颜色根据数据中的 `value` 字段的值映射到不同的颜色：\n\n```typescript\n{\n  node: {\n    palette: {\n      type: 'value', // 指定色板类型为连续色板\n      field: 'value', // 指定数据中的数值字段\n      color: (value) => `rgb(${value * 255}, 0, 0)`, // 使用插值器\n    }\n  }\n}\n```\n\n<embed src=\"@/common/manual/core-concept/palette/continuous-palette.md\"></embed>\n\n:::warning{title=注意}\n内置连续色板不支持指定值域范围，如果有更复杂的颜色映射需求，可以在样式映射中自定义\n:::\n\n## 自定义色板\n\n如果内置色板无法满足需求，可以自定义色板，具体请参考[自定义色板](/manual/theme/custom-palette)。\n\n## 优先级\n\n色板会基于元素类型生成样式，对于节点和组合，会将颜色映射到 `fill` 属性；对于边，会将颜色映射到 `stroke` 属性。\n\n如果同时配置了色板和样式映射，样式映射会覆盖色板颜色。下面的例子中，节点的颜色始终为红色：\n\n```typescript\n{\n  node: {\n    style: {\n      fill: 'red',\n    },\n    palette: 'spectral',\n  }\n}\n```\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/custom-transform.en.md) -->\n---\ntitle: Custom Transform\norder: 4\n---\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/custom-transform.zh.md) -->\n---\ntitle: 自定义数据处理\norder: 4\n---\n\n## 概述\n\n自定义数据处理允许用户在业务实现过程中，把额外的数据处理封装起来，在渲染前或者布局后对数据进行进一步处理。用户通过自定义数据处理，实现部分数据处理解耦，更好地进行管理、编排代码以及提高代码可维护性。\n\n## 开始前\n\n用户在进行自定义数据处理前，需要仔细阅读并掌握数据处理器的 [实现原理和执行时机](/manual/transform/overview#实现原理) 。\n\n## 代码示例\n\n接下来将讲述两个可能的业务场景，并通过自定义数据处理来实现：\n\n### 不展示游离节点\n\n- **需求**\n\n  游离节点，即没有连线的节点，画布渲染时不展示游离节点\n\n- **实现**\n\n  ```typescript\n  import type { DrawData, DrawContext } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory } from '@antv/g6';\n\n  class HideFreeNode extends BaseTransform {\n    public beforeDraw(input: DrawData, context: DrawContext): DrawData {\n      const { model } = this.context;\n      const { add, update, remove } = input;\n\n      add.nodes.forEach((nodeData, nodeId) => {\n        // 获取节点的相关连线\n        const edges = model.getRelatedEdgesData(nodeId);\n        // 没有任何连线的的节点则从add里面移除，添加到remove里面\n        if (!edges.length) {\n          add.nodes.delete(nodeId);\n          remove.nodes.set(nodeId, nodeData);\n        }\n      });\n\n      return input;\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/hide-free-node.md\"></embed>\n\n- **说明**\n\n  示例中总共有6个节点，id为1-6，id为4的节点没有连线，因此被移除了。\n\n  通过 `getRelatedEdgesData` 获取节点的相关连线，没有则把该节点放到 `remove.nodes` 里面去，并从 `add.nodes` 里面移除。\n\n### 环形布局径向label\n\n- **需求**\n\n  使用 [环形布局](/manual/layout/circular-layout) 时，节点 label 的也需要像内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 一样实现径向展示（但 PlaceRadialLabels 只支持径向布局，环形布局不是径向布局）\n\n- **实现**\n\n  ```typescript\n  import type { RuntimeContext, DrawContext, Point, TransformArray, Vector2, Vector3 } from '@antv/g6';\n  import { Graph, BaseTransform, register, ExtensionCategory, BaseTransformOptions } from '@antv/g6';\n\n  // 目前circular布局没有暴露方法可以获取布局中心，这里简单处理先固定一个，配置circular布局时center与这里保持一致即可\n  const circularCenter = [300, 300];\n\n  // 下面的函数 G6 没有暴露出来，先自行声明\n  function subtract(a: Vector2 | Vector3, b: Vector2 | Vector3): Vector2 | Vector3 {\n    return a.map((v, i) => v - b[i]) as Vector2 | Vector3;\n  }\n  function rad(a: Vector2 | Vector3): number {\n    const [x, y] = a;\n    if (!x && !y) return 0;\n    return Math.atan2(y, x);\n  }\n  function rad2deg(rad: number): number {\n    return rad * (180 / Math.PI);\n  }\n\n  interface CircularRadialLabelsOptions extends BaseTransformOptions {\n    offset?: number; // 偏移量\n  }\n\n  class CircularRadialLabels extends BaseTransform<CircularRadialLabelsOptions> {\n    static defaultOptions = {\n      offset: 5,\n    };\n    constructor(context: RuntimeContext, options: CircularRadialLabelsOptions) {\n      super(context, Object.assign({}, CircularRadialLabels.defaultOptions, options));\n    }\n    get center(): Point {\n      return circularCenter;\n    }\n    public afterLayout() {\n      const { graph, model } = this.context;\n      const data = model.getData();\n      data.nodes?.forEach((datum) => {\n        const radian = rad(subtract([datum.style.x, datum.style.y], this.center));\n        const isLeft = Math.abs(radian) > Math.PI / 2;\n        const isLeaf = !datum.children || datum.children.length === 0;\n        const nodeId = datum.id;\n        const node = this.context.element?.getElement(nodeId);\n        if (!node || !node.isVisible()) return;\n\n        const nodeHalfWidth = graph.getElementRenderStyle(nodeId).size / 2;\n        const offset = (isLeaf ? 1 : -1) * (nodeHalfWidth + this.options.offset);\n\n        const labelTransform: TransformArray = [\n          ['translate', offset * Math.cos(radian), offset * Math.sin(radian)],\n          ['rotate', isLeft ? rad2deg(radian) + 180 : rad2deg(radian)],\n        ];\n\n        model.updateNodeData([\n          {\n            id: datum.id,\n            style: {\n              labelTextAlign: isLeft === isLeaf ? 'right' : 'left',\n              labelTextBaseline: 'middle',\n              labelTransform,\n            },\n          },\n        ]);\n      });\n\n      graph.draw();\n    }\n  }\n  ```\n\n  <embed src=\"@/common/manual/custom-extension/transform/circular-radial-labels.md\"></embed>\n\n- **说明**\n  上面的实现基本是参考内置数据处理器 [PlaceRadialLabels](/manual/transform/place-radial-labels) 来实现的，区别是这里的实现是通过拿到布局中心来计算偏移和旋转，具体可参考 PlaceRadialLabels 的 [源码](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/place-radial-labels.ts)\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/MapNodeSize.en.md) -->\n---\ntitle: MapNodeSize\norder: 1\n---\n\nIn graph visualization, the size of a node is usually used to convey the importance or influence of the node. By adjusting the size of the node based on the centrality of the node, we can more intuitively show the importance of each node in the network, helping users better understand and analyze complex network structures.\n\n## Options\n\n### centrality\n\n> [NodeCentralityOptions](#nodecentralityoptions) _\\| ((graphData:_ [GraphData](/manual/core-concept/data#图数据graphdata)_) =>_ _Map**&lt;**string, number>)_ **Default:** `type: 'eigenvector'`\n\nThe method of measuring the node centrality\n\n- `'degree'`: Degree centrality, measures centrality by the degree (number of connected edges) of a node. Nodes with high degree centrality usually have more direct connections and may play important roles in the network\n- `'betweenness'`: Betweenness centrality, measures centrality by the number of times a node appears in all shortest paths. Nodes with high betweenness centrality usually act as bridges in the network, controlling the flow of information\n- `'closeness'`: Closeness centrality, measures centrality by the reciprocal of the average shortest path length from a node to all other nodes. Nodes with high closeness centrality usually can reach other nodes in the network more quickly\n- `'eigenvector'`: Eigenvector centrality, measures centrality by the degree of connection between a node and other central nodes. Nodes with high eigenvector centrality usually connect to other important nodes\n- `'pagerank'`: PageRank centrality, measures centrality by the number of times a node is referenced by other nodes, commonly used in directed graphs. Nodes with high PageRank centrality usually have high influence in the network, similar to the page ranking algorithm\n- Custom centrality calculation method: `(graphData: GraphData) => Map<ID, number>`, where `graphData` is the graph data, and `Map<ID, number>` is the mapping from node ID to centrality value\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n### mapLabelSize\n\n> _boolean \\| [number, number]_ **Default:** `false`\n\nWhether to map label size synchronously\n\n### maxSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `80`\n\nThe maximum size of the node\n\n### minSize\n\n> _number \\| [number, number] \\| Float32Array \\| [number, number, number]_ **Default:** `20`\n\nThe minimum size of the node\n\n### scale\n\n> _'linear' \\| 'log' \\| 'pow' \\| 'sqrt' \\| ((value: number, domain: [number, number], range: [number, number]) => number)_ **Default:** `'log'`\n\nScale type\n\n- `'linear'`: Linear scale, maps a value from one range to another range linearly, commonly used for cases where the difference in centrality values is small\n\n- `'log'`: Logarithmic scale, maps a value from one range to another range logarithmically, commonly used for cases where the difference in centrality values is large\n\n- `'pow'`: Power-law scale, maps a value from one range to another range using power law, commonly used for cases where the difference in centrality values is large\n\n- `'sqrt'`: Square root scale, maps a value from one range to another range using square root, commonly used for cases where the difference in centrality values is large\n\n- Custom scale: `(value: number, domain: [number, number], range: [number, number]) => number`，where `value` is the value to be mapped, `domain` is the input range, and `range` is the output range\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/MapNodeSize.zh.md) -->\n---\ntitle: 动态调整节点大小 MapNodeSize\norder: 1\n---\n\n## 概述\n\n在图可视化中，节点的大小通常用于传达节点的重要性或影响力。通过根据节点中心性调整节点的大小，我们可以更直观地展示网络中各个节点的重要性，从而帮助用户更好地理解和分析复杂的网络结构。\n\n## 使用场景\n\n需要通过节点大小来突出节点的重要性和影响力时，可使用此数据处理。\n\n以下为常见的场景：\n\n- **社交网络分析**：比如分析社交媒体平台中用户的活跃度与影响力，通过节点大小突出高互动用户。\n\n- **金融风险传导网络**：比如识别金融系统中承担关键资金流转职能的机构，预防系统性风险。\n\n- **交通枢纽规划**：比如优化城市地铁网络设计，识别换乘压力点。\n\n## 配置项\n\n| 属性         | 描述                                                       | 类型                                                                                                                               | 默认值               | 必选 |\n| ------------ | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---- |\n| type         | 数据处理类型                                               | map-node-size                                                                                                                      | -                    | ✓    |\n| centrality   | 节点中心性的度量方法，[配置项](#centrality)                | [NodeCentralityOptions](#nodecentralityoptions) \\| ((graphData: [GraphData](/manual/data#图数据graphdata)) => Map<string, number>) | `{ type: 'degree' }` |      |\n| mapLabelSize | 是否同步调整标签大小                                       | boolean \\| [number, number]                                                                                                        | false                |      |\n| maxSize      | 节点最大尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 80                   |      |\n| minSize      | 节点最小尺寸                                               | number \\| [number, number] \\| [number, number, number]                                                                             | 20                   |      |\n| scale        | 插值函数，用于将节点中心性映射到节点大小，[配置项](#scale) | `linear` \\| `log` \\| `pow` \\| `sqrt` \\| ((value: number, domain: [number, number], range: [number, number]) => number)             | `log`                |      |\n\n### centrality\n\n节点中心性的度量方法\n\n- `'degree'`：度中心性，通过节点的度数（连接的边的数量）来衡量其重要性。度中心性高的节点通常具有较多的直接连接，在网络中可能扮演着重要的角色\n- `'betweenness'`：介数中心性，通过节点在所有最短路径中出现的次数来衡量其重要性。介数中心性高的节点通常在网络中起到桥梁作用，控制着信息的流动\n- `'closeness'`：接近中心性，通过节点到其他所有节点的最短路径长度总和的倒数来衡量其重要性。接近中心性高的节点通常能够更快地到达网络中的其他节点\n- `'eigenvector'`：特征向量中心性，通过节点与其他中心节点的连接程度来衡量其重要性。特征向量中心性高的节点通常连接着其他重要节点\n- `'pagerank'`：PageRank 中心性，通过节点被其他节点引用的次数来衡量其重要性，常用于有向图。PageRank 中心性高的节点通常在网络中具有较高的影响力，类似于网页排名算法\n- 自定义中心性计算方法：`(graphData: GraphData) => Map<ID, number>`，其中 `graphData` 为图数据，`Map<ID, number>` 为节点 ID 到中心性值的映射\n\n**示例：**\n\n```typescript {6-9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n        direction: 'both',\n      },\n    },\n  ],\n});\n```\n\n效果如下（可切换度量方法查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-centrality.md\"></embed>\n\n#### NodeCentralityOptions\n\n```typescript\ntype NodeCentralityOptions =\n  | { type: 'degree'; direction?: 'in' | 'out' | 'both' }\n  | { type: 'betweenness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'closeness'; directed?: boolean; weightPropertyName?: string }\n  | { type: 'eigenvector'; directed?: boolean }\n  | { type: 'pagerank'; epsilon?: number; linkProb?: number };\n```\n\n`direction`：表示统计哪些方向的边，`in` -入边、 `out` -出边、 `both` -入边和出边都考虑进去\n\n`directed`：是否为有向图\n\n`weightPropertyName`：边的权重属性名\n\n`epsilon`：PageRank 算法的收敛容差\n\n`linkProb`：PageRank 算法的阻尼系数，指任意时刻，用户访问到某节点后继续访问该节点链接的下一个节点的概率，经验值 0.85\n\n### scale\n\n- `'linear'`：线性插值函数，将一个值从一个范围线性映射到另一个范围，常用于处理中心性值的差异较小的情况\n- `'log'`：对数插值函数，将一个值从一个范围对数映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'pow'`：幂律插值函数，将一个值从一个范围幂律映射到另一个范围，常用于处理中心性值的差异较大的情况\n- `'sqrt'`：平方根插值函数，将一个值从一个范围平方根映射到另一个范围，常用于处理中心性值的差异较大的情况\n- 自定义插值函数：`(value: number, domain: [number, number], range: [number, number]) => number`，其中 `value` 为需要映射的值，`domain` 为输入值的范围，`range` 为输出值的范围\n\n**示例：**\n\n```typescript {9}\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'map-node-size',\n      centrality: {\n        type: 'degree',\n      },\n      scale: 'linear',\n    },\n  ],\n});\n```\n\n效果如下（该示例为基于度中心性 `degree` ，可切换插值函数查看不同效果，示例中节点 label 为`${节点 id } - ${节点大小}`）：\n\n<embed src=\"@/common/api/transforms/map-node-size-scale.md\"></embed>\n\n## 实际案例\n\n- [场景案例：独角兽和他们的投资者](/examples/feature/default/#unicorns-investors)\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/overview.en.md) -->\n---\ntitle: Data Transformation Overview\norder: 0\n---\n\n## Overview\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/overview.zh.md) -->\n---\ntitle: 数据处理总览\norder: 0\n---\n\n## 什么是数据处理\n\n数据处理（ `transform` ），也叫数据转换器，是 G6 提供的支持在 **渲染前( `beforeDraw` )** 或者 **布局后( `afterLayout` )** 对绘制数据进行转化处理的机制，用户可以通过数据处理很方便地对数据处理逻辑进行封装解耦。\n\n## 实现原理\n\n### 基类\n\n所有的数据处理器都是基于 [BaseTransform](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/base-transform.ts) 这个基类进行实现，里面定义了两个基类方法 `beforeDraw` 和 `afterLayout` ：\n\n```typescript\nexport abstract class BaseTransform<T extends BaseTransformOptions = BaseTransformOptions> extends BaseExtension<T> {\n  public beforeDraw(data: DrawData, context: DrawContext): DrawData {\n    return data;\n  }\n\n  public afterLayout(type: 'pre', data: DrawData): void;\n  public afterLayout(type: 'post', data?: undefined): void;\n  public afterLayout(type: 'pre' | 'post', data?: DrawData) {}\n}\n```\n\n以下是这两个方法里核心的参数类型说明：\n\n- **DrawData**\n\n  ```typescript\n  type ProcedureData = {\n    nodes: Map<ID, NodeData>;\n    edges: Map<ID, EdgeData>;\n    combos: Map<ID, ComboData>;\n  };\n\n  type DrawData = {\n    add: ProcedureData; // 本次渲染需要新增的元素\n    update: ProcedureData; // 本次渲染需要更新的元素\n    remove: ProcedureData; // 本次渲染需要移除的元素\n  };\n  ```\n\n- **pre | post**\n\n  pre：绘制前进行的布局（只会在首次布局触发）\n\n  post：完成绘制后进行的布局\n\n### 执行时机\n\n- **beforeDraw**\n\n  下面是每次渲染时数据处理的执行流程/时机：\n\n  <img width=\"300px\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Pb3kRI2yHo8AAAAAAAAAAAAAemJ7AQ/original\"/>\n\n  **详细说明：**\n\n  1. G6 在每次渲染前计算出 `add`、`update`、`remove`，分别对应为需要新增、更新、移除的元素，以下简称为 `DrawData`\n  2. 此时数据处理介入，按配置顺序执行每个数据处理的 `beforeDraw` 方法，参数则为 `DrawData`\n  3. 数据处理器中，对 `DrawData` 里面的元素数据进行改动，即可以按需对 `add`、`update`、`remove` 里面的元素数据进行修改、移除或者插入元素数据等，最终把改动后的 `DrawData` 返回给渲染主体逻辑\n  4. 在执行数据处理后，执行对应的新增、更新、移除元素的操作，完成渲染\n\n:::info{title=提示}\n触发渲染的场景分为主动和被动，列举如下：\n\n- **主动：** 用户主动调用 `graph.render()` 、 `graph.draw()` 或者在自定义插件、交互等实例里面通过上下文拿到元素控制器（ [ElementController](https://github.com/antvis/G6/blob/v5/packages/g6/src/runtime/element.ts) ）实例调用 `this.context.element.draw()`，等（ `graph.render()` 和 `graph.draw()` 也是调用元素控制器的 `draw` 方法）\n- **被动：** 部分内置交互和插件有触发渲染，布局执行后也有触发渲染更新元素位置，等\n\n:::\n\n- **afterLayout**：在执行完布局计算并开始更新节点位置后，执行数据处理\n\n## 内置数据处理\n\n- **G6 提供给用户的内置数据处理如下：**\n\n各数据处理详细配置可参考 [内置数据处理文档](/manual/transform/map-node-size)。\n\n| 数据处理名称                                        | 注册类型                 | 功能描述                                             | 执行时机   |\n| --------------------------------------------------- | ------------------------ | ---------------------------------------------------- | ---------- |\n| [动态调整节点大小](/manual/transform/map-node-size) | `map-node-size`          | 根据节点中心性调整节点的大小                         | beforeDraw |\n| [径向标签](/manual/transform/place-radial-labels)   | `place-radial-labels`    | 根据径向布局自动调整节点标签样式，包括位置和旋转角度 | afterDraw  |\n| [平行边](/manual/transform/process-parallel-edges)  | `process-parallel-edges` | 处理平行边，即多条边共享同一源节点和目标节点         | beforeDraw |\n\n- **G6 内嵌的数据处理如下：**\n\n除了提供给用户选用的数据处理外， G6 也封装并使用了以下数据处理机制来实现基础功能。以下数据处理不开放给用户配置使用，默认必带（列举出来供用户有需要时点击查看并参考源码）：\n\n| 数据处理名称                                                                                                            | 注册类型                | 功能描述                                                                                                                                                      | 执行时机   |\n| ----------------------------------------------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| [调整combo绘制顺序](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/arrange-draw-order.ts)              | `arrange-draw-order`    | combo 嵌套时，优先绘制子 combo                                                                                                                                | beforeDraw |\n| [处理组合的展开收起](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-combo.ts)          | `collapse-expand-combo` | 收起时，移除 combo 内部元素、销毁内部边，外部边则连到收起的 combo 上；<br />展开时，反之；                                                                    | beforeDraw |\n| [处理（树图）节点的收起和展开](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/collapse-expand-node.ts) | `collapse-expand-node`  | 绘制前，处理（树图）节点的收起和展开                                                                                                                          | beforeDraw |\n| [获取边的实际端点](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/get-edge-actual-ends.ts)             | `get-edge-actual-ends`  | 配合`collapse-expand-combo`实现收起时，combo 外部连到内部节点的边改为连到收起的 combo 上（`collapse-expand-combo`只是在收起时判断并标记了这些边需要更新端点） | beforeDraw |\n| [更新节点、combo相关边](https://github.com/antvis/G6/blob/v5/packages/g6/src/transforms/update-related-edge.ts)         | `update-related-edges`  | 如果更新了节点/combo，则把连接的边也一起更新了                                                                                                                | beforeDraw |\n\n:::warning{title=注意}\n\n上面 G6 为实现自身基础功能使用的数据处理仅供参考，不可改动。如有需要在这些数据处理基础上做特殊处理，可通过 [自定义数据处理](#自定义数据处理) 实现。\n\n:::\n\n## 配置方式\n\n### 基本配置\n\n在图实例初始化时，通过 `transforms` 数组指定需要的数据处理：\n\n```javascript\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n### 配置数据处理参数\n\n对于需要自定义参数的数据处理，可以使用 `object` 形式配置属性：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    'place-radial-labels',\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges-1',\n      mode: 'bundle',\n      distance: 30,\n    },\n  ],\n});\n```\n\n### 动态更新数据处理\n\nG6 支持在图实例运行期间动态管理数据处理：\n\n- 可以通过 [setTransforms](/api/transform#graphsettransformstransforms) 方法调整数据处理器：\n\n```javascript\n// 添加新的数据处理器\ngraph.setTransforms((transforms) => [...transforms, 'place-radial-labels']);\n\n// 移除数据处理器\ngraph.setTransforms((transforms) => transforms.filter((t) => t !== 'place-radial-labels'));\n```\n\n- 可以通过 [updateTransform](/api/transform#graphupdatetransformtransform) 方法更新数据处理的配置：\n\n```javascript\n// 更新单个数据处理器\ngraph.updateTransform({\n  key: 'process-parallel-edges-1',\n  distance: 100,\n});\n```\n\n:::warning{title=注意}\n使用`updateTransform`方法时，需要在初始化时为数据处理指定唯一的`key`。\n:::\n\n### 卸载数据处理\n\n使用 [setTransforms](/api/transform#graphsettransformstransforms) 方法同样可以卸载数据处理，将数据处理配置列表置为空即可：\n\n```javascript\n// 卸载所有数据处理器\ngraph.setTransforms([]);\n```\n\n## 自定义数据处理\n\n当内置数据处理器无法满足需求时，你可以：\n\n- 继承和扩展现有数据处理\n- 创建全新的自定义数据处理\n\n自定义数据处理需要先注册后使用。详细教程请参考 [自定义数据处理](/manual/transform/custom-transform) 文档。\n\n```javascript\nimport { register, ExtensionCategory } from '@antv/g6';\nimport { MyCustomTransform } from './my-custom-transform';\n\n// 注册自定义数据处理器\nregister(ExtensionCategory.TRANSFORM, 'my-custom-transform', MyCustomTransform);\n\n// 使用自定义数据处理\nconst graph = new Graph({\n  transforms: ['my-custom-transform'],\n});\n```\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/PlaceRadialLabels.en.md) -->\n---\ntitle: PlaceRadialLabels\norder: 3\n---\n\n## Options\n\n### offset\n\n> _number_\n\nOffset\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/PlaceRadialLabels.zh.md) -->\n---\ntitle: 径向标签 PlaceRadialLabels\norder: 2\n---\n\n**参考示例**：\n\n- [径向生态树](/examples/scene-case/tree-graph/#radial-dendrogram)\n- [径向紧凑树](/examples/scene-case/tree-graph/#radial-compact-tree)\n\n## 配置项\n\n### type\n\n> _`place-radial-labels` \\| string_\n\n此数据处理已内置，你可以通过 `type: 'place-radial-labels'` 来使用它。\n\n### offset\n\n> _number_\n\n偏移量\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/ProcessParallelEdges.en.md) -->\n---\ntitle: ProcessParallelEdges\norder: 3\n---\n\nParallel Edges refer to multiple edges existing between two nodes in a graph structure. These edges share the same source and target nodes but may represent different relationships or attributes. To avoid edge overlap and confusion, two methods are provided for handling parallel edges: (1) Bundle Mode: Bundles parallel edges together and separates them from other edges by altering their curvature; (2) Merge Mode: Merges parallel edges into a single aggregated edge.\n\n## Options\n\n### distance\n\n> _number_\n\nThe distance between edges, only valid for bundling mode\n\n### edges\n\n> _string[]_\n\nThe edges to be handled, all edges by default\n\n### <Badge type=\"success\">Required</Badge> mode\n\n> _'bundle' \\| 'merge'_ **Default:** `'bundle'`\n\nProcessing mode\n\n- '`merge`': Merge parallel edges into one edge which is suitable for cases where parallel edges do not need to be distinguished\n\n- '`bundle`': Each edge will be bundled with all other parallel edges and separated from them by varying the curvature. If the number of parallel edges in a group is odd, the central edge will be drawn as a straight line, and the others will be drawn as curves\n\n### style\n\n> _PathStyleProps_ _\\| ((prev:_ [EdgeData](/api/graph/option#edgedata)_[]) =>_ _PathStyleProps)_\n\nThe style of the merged edge, only valid for merging mode\n\n\n<!-- Skill/Rule: Transform Skill (packages/site/docs/manual/transform/ProcessParallelEdges.zh.md) -->\n---\ntitle: 平行边 ProcessParallelEdges\norder: 3\n---\n\n## 概述\n\n平行边（Parallel Edges）是指在图结构中，两个节点之间存在多条边。这些边共享相同的源节点和目标节点，但可能代表不同的关系或属性。为了避免边的重叠和混淆，提供了两种处理平行边的方式：\n\n- 捆绑模式（bundle）：将平行边捆绑在一起，通过改变曲率与其他边分开\n- 合并模式（merge）：将平行边合并为一条聚合\n\n## 使用场景\n\n下面为常见使用场景举例：\n\n- 双向数据流，比如客户端发送请求，服务端返回响应\n\n- 多依赖关系，即一个节点通过多种方式依赖另一个节点，比如微服务架构中，服务 A 调用服务 B的两个不同 API\n- 多链路，比如高可用架构中，主链路（实线，状态正常）与备份链路（灰色虚线，状态待机）同时展示\n\n## 基本用法\n\n**1. 快速配置（静态）**\n\n使用字符串形式直接声明，这种方式简洁但仅支持默认配置，且配置后不可动态修改：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: ['process-parallel-edges'],\n});\n```\n\n**2. 对象配置（推荐）**\n\n使用对象形式进行配置，支持自定义参数，且可以在运行时动态更新配置：\n\n```javascript\nconst graph = new Graph({\n  // 其他配置...\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      key: 'process-parallel-edges',\n      mode: 'bundle', // 默认就是捆绑模式了\n      distance: 30, // 配置捆绑模式下边之间的距离为30\n    },\n  ],\n});\n```\n\n## 配置项\n\n| 属性     | 描述                                               | 类型                                                                                    | 默认值                  | 必选 |\n| -------- | -------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------- | ---- |\n| type     | 数据处理类型                                       | process-parallel-edges                                                                  | -                       | ✓    |\n| distance | 边之间的距离，仅在捆绑模式下有效                   | number                                                                                  | 15                      |      |\n| edges    | 考虑要处理的边，默认为全部边                       | string[]                                                                                | -                       |      |\n| mode     | 处理模式，[配置项](#mode)                          | `'bundle'`                                                                              | `'merge'` \\| `'bundle'` |      |\n| style    | 合并边的样式，仅在合并模式下有效，[配置项](#style) | PathStyleProps \\| ((prev: [EdgeData](/manual/data#边数据edgedata)[]) => PathStyleProps) | -                       |      |\n\n### mode\n\n提供了两种处理模式：\n\n- `'merge'`: 将平行边合并为一条边，适用于不需要区分平行边的情况，[示例](#合并模式)\n\n`merge` 使用的是内置的直线（ [`line`](/manual/element/edge/Line) ）来展示合并边。\n\n- `'bundle'`: 每条边都会与其他所有平行边捆绑在一起，并通过改变曲率与其他边分开。如果一组平行边的数量是奇数，那么中心的边将被绘制为直线，其他的边将被绘制为曲线，[示例](#捆绑模式)\n\n`bundle` 使用的是内置的二次贝塞尔曲线（ [`quadratic`](/manual/element/edge/Quadratic) ）来实现，数据处理过程会强制把每个 `edgeDatum.type` 改为 `quadratic`，并计算每条线的曲率。\n\n:::warning{title=注意}\n\n禁止在创建 Graph 实例时配置 `edge.type` 即默认的边类型，因为它的优先级比 `edgeDatum.type` 要高，会导致 `bundle` 模式的处理无法生效。\n\n:::\n\n### style\n\n合并边的样式，仅在合并模式下有效\n\n#### PathStyleProps\n\n下表列出了常用的属性，更多属性请参考 [PathStyleProps](https://g.antv.antgroup.com/api/basic/path#pathstyleprops)。\n\n| 属性           | 描述                      | 类型                          | 默认值    | 必选 |\n| -------------- | ------------------------- | ----------------------------- | --------- | ---- |\n| fill           | 填充色                    | string                        | `#1783FF` |\n| fillOpacity    | 填充色透明度              | number \\| string              | 1         |\n| lineCap        | 描边端点样式              | `round` \\| `square` \\| `butt` | `butt`    |\n| lineDash       | 描边虚线样式              | number[]                      | -         |\n| lineDashOffset | 描边虚线偏移量            | number                        | -         |\n| lineJoin       | 描边连接处样式            | `round` \\| `bevel` \\| `miter` | `miter`   |\n| lineWidth      | 描边宽度                  | number                        | 1         |\n| opacity        | 透明度                    | number \\| string              | 1         |\n| shadowBlur     | 阴影模糊度                | number                        | -         |\n| shadowColor    | 阴影颜色                  | string                        | -         |\n| shadowOffsetX  | 阴影在 x 轴方向上的偏移量 | number \\| string              | -         |\n| shadowOffsetY  | 阴影在 y 轴方向上的偏移量 | number \\| string              | -         |\n| shadowType     | 阴影类型                  | `inner` \\| `outer`            | `outer`   |\n| stroke         | 描边色                    | string                        | `#000`    |\n| strokeOpacity  | 描边色透明度              | number \\| string              | 1         |\n| visibility     | 图形是否可见              | `visible` \\| `hidden`         | `visible` |\n\n## 代码示例\n\n### 捆绑模式\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'C' },\n    { source: 'C', target: 'A' },\n    ...Array.from({ length: 10 }).map((_, i) => ({\n      id: `edge:A-B${i}`,\n      source: 'A',\n      target: 'B',\n      data: {\n        label: `A->B:${i}`,\n      },\n    })),\n    ...Array.from({ length: 5 }).map((_, i) => ({\n      id: `edge:B-C${i}`,\n      source: 'B',\n      target: 'C',\n      data: {\n        label: `B->C:${i}`,\n      },\n    })),\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      ports: [{ placement: 'center' }],\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n    },\n  },\n  behaviors: ['drag-element'],\n  transforms: ['process-parallel-edges'],\n});\n\ngraph.render();\n```\n\n### 合并模式\n\n下面是一个简单的合并模式的例子，需要注意：\n\n- 不需要合并（即两个节点间只有一条边）的边，合并样式不会在这条边上生效，比如例子中的 **A->C**\n- 合并样式实际上是赋值给 `datum.style` ，也就是优先级会比实例化 Graph 时配置的默认样式低（ `edge.style` ），所以例子中合并样式的 `startArrow` 没有生效\n\n```js | ob { inject: true }\nimport { Graph } from '@antv/g6';\n\nconst data = {\n  nodes: [\n    { id: 'A', style: { x: 50, y: 350 } },\n    { id: 'B', style: { x: 250, y: 150 } },\n    { id: 'C', style: { x: 450, y: 350 } },\n  ],\n  edges: [\n    { source: 'A', target: 'B' },\n    { source: 'B', target: 'A' },\n    { id: 'B-C:1', source: 'B', target: 'C' },\n    { id: 'B-C:2', source: 'B', target: 'C' },\n    { source: 'A', target: 'C' },\n  ],\n};\n\nconst graph = new Graph({\n  container: 'container',\n  autoFit: 'center',\n  data,\n  node: {\n    style: {\n      labelText: (d) => d.id,\n    },\n  },\n  edge: {\n    style: {\n      labelText: (d) => d?.data?.label || `${d.source}->${d.target}`,\n      startArrow: false,\n    },\n  },\n  transforms: [\n    {\n      type: 'process-parallel-edges',\n      mode: 'merge',\n      style: {\n        halo: true,\n        haloOpacity: 0.2,\n        haloStroke: 'red',\n        startArrow: true,\n      },\n    },\n  ],\n});\n\ngraph.render();\n```\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/feature.en.md) -->\n---\ntitle: Feature\norder: 1\n---\n\n## 🏖️ Brand New Design Specification for Graphs\n\nG6 version 5.0 has redesigned the Options specification. While ensuring comprehensive capabilities, it optimizes the options structure to be more intuitive and easier to understand.\n\nYou only need to quickly grasp the basic [core concepts](/en/manual/graph/graph) to get started with G6 quickly and achieve graph visualization without delay.\n\n**😰 The 4.0 Options** had a complex nested structure and was less semantically capable\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 The 5.0 Options** has a clear structure and is easy to understand\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 Brand New API Design\n\nG6 5.0 features a cleaner, easy-to-use API design that is more in line with modern front-end frameworks.\n\n## 🌲 Merging Graphs with Tree Graphs\n\nTree graphs are essentially a type of directed acyclic graph. G6 5.0 has integrated the design of graphs and tree graphs, reducing the cost of understanding and usage.\n\nNow, you can directly use `Graph` to instantiate and draw tree graphs in G6, without the need to use `TreeGraph`. You simply need to specify the layout as a tree graph layout.\n\nAdditionally, G6 provides the `treeToGraphData` utility method to help you quickly convert tree graph data into graph data.\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 Multi-Renderer Support\n\nG6 5.0 employs the next-generation @antv/g rendering engine, which has been newly designed. It offers support for multiple renderers such as `Canvas`, `SVG`, and `WebGL`. Additionally, it supports the mixed use of different renderers on layered canvases.\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... other configurations\n  // Use the WebGL renderer\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 High-Performance Layouts\n\nG6 5.0 has adopted a brand-new layout engine, with some layouts implemented in Rust, providing higher performance for layout calculations. Additionally, there is support for WebGPU acceleration in certain layouts.\n\n> 🚀 To utilize high-performance layouts, you will need to install the `@antv/layout-wasm` package\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... other configurations\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... Other Layout Configurations\n  },\n});\n```\n\n## 🎨 Multiple Themes Mechanism\n\nG6 5.0 comes with two built-in themes: light and dark, and allows for flexible customization based on the use case. For details, please refer to [Custom Theme](/en/manual/custom-extension/theme).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D Large Graphs\n\nG6 5.0 provides 3D rendering, layout, interaction capabilities, and can be used by import 3d elements, renderer, and behaviors from `@antv/g6-extension-3D` registration, see: [Using 3D](/manual/further-reading/3d).\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 Plugin Optimization and Enhancement\n\nG6 5.0 has optimized and enhanced existing plugins, decoupling Graph from plugins, and providing richer capabilities while optimizing configurations.\n\nPlease visit [Plugin](/en/api/plugins/bubble-sets) to experience the capabilities of more plugins.\n\n## 💼 Optimized Package Size\n\nThanks to the well-modularized design and extension registration mechanism of G6 5.0, modules that are not used will not be packaged into the final build file, reducing the package size.\n\nCompared to 4.0, the UMD package size has been reduced from 1.8 MB to 0.96 MB, a reduction of nearly 50%.\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/feature.zh.md) -->\n---\ntitle: 新版本特性\norder: 1\n---\n\n## 🏖️ 全新设计图配置范式\n\nG6 5.0 重新设计了图配置范式，在保证能力完善的基础上，优化配置项结构，更加直观、易于理解。\n\n仅需快速了解基本[核心概念](/manual/graph/graph)，即可快速上手 G6，快速实现图可视化。\n\n**😰 4.0 配置项** 嵌套结构复杂，语义化能力较弱\n\n```typescript\n{\n  defaultNode: {\n    size: 30,\n    style: {\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n    },\n    labelCfg: {\n      style: {\n        fill: '#fff',\n      }\n    }\n  },\n  nodeStateStyles: {\n    hover: {\n      fill: 'lightsteelblue'\n    }\n  },\n  modes: {\n    default: ['zoom-canvas', 'drag-canvas', 'drag-node'],\n  },\n}\n```\n\n**😄 5.0 配置项** 结构清晰，易于理解\n\n```typescript\n{\n  node: {\n    style: {\n      size: 30,\n      fill: 'steelblue',\n      stroke: '#666',\n      lineWidth: 1\n      labelFill: '#fff',\n    },\n    state: {\n      hover: {\n        fill: 'lightsteelblue'\n      }\n    }\n  },\n  behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],\n}\n```\n\n## 🔨 全新 API 设计\n\nG6 5.0 采用了更加简洁、易用的 API 设计，更加符合现代前端框架的设计风格。\n\n## 🌲 合并图与树图\n\n树图本质上是一种单向无环图，G6 5.0 融合了图与树图的设计，降低了理解和使用成本。\n\n现在，你可以在 G6 中直接使用 `Graph` 来实例化绘制树图，而不需要再使用 `TreeGraph`，仅需指定布局为树图布局即可。\n\n此外，G6 提供了 `treeToGraphData` 工具方法，帮助你快速将树图数据转换为图数据。\n\n<embed src=\"@/common/manual/feature/treeToGraphData.md\"></embed>\n\n## 🌆 多渲染器支持\n\nG6 5.0 采用了新一代设计的 @antv/g 渲染引擎，提供了 `Canvas` `SVG` `WebGL` 多种渲染器支持，并且分层画布支持不同渲染器的混合使用。\n\n```typescript\nimport { Renderer } from '@antv/g-webgl';\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  // ... 其他配置\n  // 使用 WebGL 渲染器\n  renderer: () => new Renderer(),\n});\n```\n\n## 🚀 高性能布局\n\nG6 5.0 采用了全新布局引擎，部分布局提供 Rust 实现，提供了更高性能的布局计算。另有布局支持 WebGPU 加速。\n\n> 🚀 高性能布局需要安装 `@antv/layout-wasm` 包\n\n```typescript\nimport { ForceAtlas2Layout, initThreads, supportsThreads } from '@antv/layout-wasm';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'forceatlas2-wasm', ForceAtlas2Layout);\n\nconst supported = await supportsThreads();\nconst threads = await initThreads(supported);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'forceatlas2-wasm',\n    threads,\n    // ... 其他布局配置\n  },\n});\n```\n\n> GPU 加速布局需要安装 `@antv/layout-gpu` 包\n\n```typescript\nimport { FruchtermanLayout } from '@antv/layout-gpu';\nimport { Graph, register, ExtensionCategory } from '@antv/g6';\n\nregister(ExtensionCategory.LAYOUT, 'fruchterman-gpu', FruchtermanLayout);\n\nconst graph = new Graph({\n  // ... 其他配置\n  layout: {\n    type: 'fruchterman-gpu',\n    // ... 其他布局配置\n  },\n});\n```\n\n## 🎨 多主题机制\n\nG6 5.0 内置了亮色、暗色两套主题，并可基于使用场景进行灵活定制，具体可参考[自定义主题](/manual/theme/custom-theme)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*gASzQbsbAaIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 🌍 3D 大图\n\nG6 5.0 提供了 3D 大图渲染、布局、交互能力，从 `@antv/g6-extension-3d` 中引入 3D 元素、渲染器、交互等注册即可使用，详见：[使用 3D](/manual/further-reading/3d)。\n\n<image width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ZQoEQLKazPIAAAAAAAAAAAAADmJ7AQ/original\"></image>\n\n## 💪 插件优化增强\n\nG6 5.0 对现有插件进行了优化增强，解除了 Graph 与插件之间的耦合，并优化配置的同时提供了更加丰富了能力。\n\n敬请前往[插件](/manual/plugin/overview)体验更多插件的能力。\n\n## 💼 优化包体积\n\n得益于 G6 5.0 良好的模块化的设计以及扩展注册机制，对于未使用的模块，不会被打包到最终的构建文件中，减小了包体积。\n\n与 4.0 相比，UMD 包体积从 1.8 MB 减小到 0.96 MB，减小了近 50%。\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/upgrade-to-5-1.en.md) -->\n---\ntitle: Upgrade from 5.0 to 5.1 (Layout)\norder: 7\n---\n\nThis page focuses on layout documentation changes introduced in G6 `5.1`. Starting from `5.1`, layout pages prioritize the field naming aligned with `@antv/layout`; common `5.0` layout writeups are collected here for migration reference.\n\n## What Changed\n\n- Since `5.1`, layout docs prioritize shared `@antv/layout` fields such as `width`, `height`, `center`, `enableWorker`, `node`, and `edge`\n- Individual layout pages mainly keep the recommended `5.1` writeup\n- If you are migrating an existing `5.0` project, use this page to map old field names to the new documentation style\n\n## D3Force: center force to shortcut fields\n\nIn `5.0` documentation, the center force was commonly written inside `center`:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is the shortcut fields:\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` maps to `centerX`\n- `center.y` maps to `centerY`\n- `center.strength` maps to `centerStrength`\n\nFor the full field description, see [D3Force Layout](/en/manual/layout/d3-force-layout).\n\n## ComboCombined: innerLayout / outerLayout to layout\n\nIn `5.0` documentation, the inner combo layout and the outer layout were commonly configured separately:\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\nIn `5.1` documentation, the recommended form is a single `layout` entry that returns different configurations for different levels based on `comboId`:\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- When `comboId` has a value, it refers to the layout inside a combo\n- When `comboId` is empty, it refers to the outermost layout\n- Multiple layout choices are unified under the `layout` entry\n\nFor the `5.1` recommended form, see [ComboCombined Layout](/en/manual/layout/combo-combined-layout).\n\n## Migration Suggestion\n\n1. Identify the matching layout type from your existing `5.0` project\n2. Map the old fields to the recommended `5.1` documentation style\n3. Return to the specific layout page to verify shared fields and defaults\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/upgrade-to-5-1.zh.md) -->\n---\ntitle: 从 5.0 升级到 5.1（布局）\norder: 7\n---\n\n本文档聚焦 G6 `5.1` 中布局文档的写法调整。`5.1` 的布局页面会优先展示与 `@antv/layout` 对齐后的字段；`5.0` 中常见的布局写法统一收敛到本文档中，便于迁移时对照。\n\n## 总体变化\n\n- `5.1` 起，布局文档会优先展示 `@antv/layout` 的公共字段，例如 `width` `height` `center` `enableWorker` `node` `edge`\n- 各布局页主要保留 `5.1` 推荐写法，`5.0` 中常见写法请以本文档为准\n- 迁移时，建议先按旧项目中的字段定位，再映射到 `5.1` 文档里的推荐配置\n\n## D3Force：center force 改为快捷字段\n\n`5.0` 文档中，常见把中心力写在 `center` 中：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    center: {\n      x: 250,\n      y: 150,\n      strength: 0.8,\n    },\n  },\n}\n```\n\n`5.1` 文档中推荐写成更直接的快捷字段：\n\n```typescript\n{\n  layout: {\n    type: 'd3-force',\n    centerX: 250,\n    centerY: 150,\n    centerStrength: 0.8,\n  },\n}\n```\n\n- `center.x` 对应 `centerX`\n- `center.y` 对应 `centerY`\n- `center.strength` 对应 `centerStrength`\n\n如果你需要继续对照完整字段说明，可查看 [D3Force 布局](/manual/layout/d3-force-layout)。\n\n## ComboCombined：innerLayout / outerLayout 收敛为 layout\n\n`5.0` 文档中，常见分别配置 Combo 内部布局和最外层布局：\n\n```typescript\nimport { ConcentricLayout, ForceLayout } from '@antv/layout';\n\n{\n  layout: {\n    type: 'combo-combined',\n    innerLayout: new ConcentricLayout({\n      sortBy: 'id',\n    }),\n    outerLayout: new ForceLayout({\n      gravity: 1,\n    }),\n  },\n}\n```\n\n`5.1` 文档中推荐使用单个 `layout` 字段，根据 `comboId` 为不同层级返回布局配置：\n\n```typescript\n{\n  layout: {\n    type: 'combo-combined',\n    layout: (comboId) =>\n      comboId\n        ? { type: 'concentric', sortBy: 'id' }\n        : { type: 'force', gravity: 1 },\n  },\n}\n```\n\n- `comboId` 有值时，表示当前为 Combo 内部层级\n- `comboId` 为空时，表示当前为最外层布局\n- 多层布局选择统一收敛到 `layout` 入口\n\n如果你需要查看 `5.1` 推荐写法，可查看 [ComboCombined 布局](/manual/layout/combo-combined-layout)。\n\n## 迁移建议\n\n1. 先按旧项目中的布局类型定位到本文档对应条目\n2. 再把 `5.0` 字段映射成 `5.1` 文档里的推荐写法\n3. 最后回到具体布局页，核对公共字段和默认值\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/upgrade.en.md) -->\n---\ntitle: Upgrade To 5.0\norder: 6\n---\n\nThis document will guide you through the process of upgrading from G6 version `4.x` to `5.x`. If you are using version `3.x`, please upgrade to version `4.x` first.\n\n## Preparation Before Upgrade\n\n1. Please ensure that your current git branch is clean and there is no uncommitted code.\n2. Refer to the [Installation](./getting-started/installation) document to install version `5.x` and remove the dependencies for version `4.x`.\n\n## Start Upgrade\n\n### Data\n\nThe data format in the new version has changed as follows:\n\n1. All style attributes in `nodes`, `edges`, and `combos` need to be placed within `style`, and data attributes should be stored in `data`:\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // The label is a non-stylistic attribute, placed in the data, and can be accessed in the style mapping function\n    // The `size` is a stylistic attribute, placed within the `style`\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\nSince we have redesigned and implemented the elements, please refer to the corresponding documentation to modify the new element options:\n\n- [Node](/en/api/elements/nodes/base-node)\n- [Edge](/en/api/elements/edges/base-edge)\n- [Combo](/en/api/elements/combos/base-combo)\n\n2. If you need to specify the element type in the data, you can use the `type` attribute:\n\n```typescript\n{\n  nodes: [\n    // Specify the node type as rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### Options\n\n<Badge type=\"warning\">Change</Badge> **fitView / fitCenter / fitViewPadding**\n\n- The `fitView` and `fitCenter` options have been merged into `autoFit`.\n- To use `fitView`, you can configure it as `autoFit: 'view'`\n- To use `fitCenter`, you can configure it as `autoFit: 'center'`\n- You can also pass an object for full configuration:\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- The `fitViewPadding` has been changed to `padding`.\n\n<Badge type=\"error\">Removed</Badge> **linkCenter**\n\nIn version 5.x, the edge connection mechanism will attempt to connect to nodes/Combos in the following order:\n\n1. Connect Port\n2. Outline\n3. Center\n\n<Badge type=\"error\">Removed</Badge> **groupByTypes**\n\n<Badge type=\"error\">Removed</Badge> **autoPaint**\n\nPlease manually call the `render` or `draw` method to perform rendering.\n\n<Badge type=\"warning\">Changed</Badge> **modes**\n\nIn version 5.x, interaction modes have been removed. You can switch the currently enabled behaviors by setting `behaviors`.\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">Change</Badge> **defaultNode / defaultEdge / defaultCombo**\n\nThe element styles have been moved to `[element].style`, for example, `defaultNode` has been changed to `node.style`:\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\nElement state styles have been moved to `[element].state`, for example, `nodeStateStyles` has been changed to `node.stateStyles`:\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **animate / animateCfg**\n\n- The `animate` options has been changed to `animation`\n- `animate` and `animateCfg` have been merged into `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **minZoom / maxZoom**\n\n- The `minZoom` and `maxZoom` options have been merged into `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">Change</Badge> **renderer**\n\nG6 5.x supports multi-layer canvases and defaults to using the `canvas` renderer.\n\nThe `renderer` no longer supports the string type and has been changed to a callback function:\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **enabledStack / maxStep**\n\nThe built-in undo and redo functionality has been removed in version 5.x. For related capabilities, please use a plugin to implement.\n\n### API\n\n<Badge type=\"warning\">Change</Badge> **data / save / read / changeData**\n\nVersion 5.x offers a completely new data API. For details, see [Data API](/en/api/data).\n\n- The `data` and `changeData` methods from 4.x are replaced by `setData` in 5.x.\n- The `save` method from 4.x is replaced by `getData` in 5.x.\n- The `read` method from 4.x is replaced by `setData` + `render` in 5.x.\n\n<Badge type=\"warning\">Change</Badge> **get / set**\n\nTo access Graph options, please use `getOptions` or the `getXxx` API, such as `getZoomRange`, `getBehaviors`, etc. The `set` method is analogous.\n\n<Badge type=\"warning\">Change</Badge> **getContainer**\n\nDirect API to obtain the container is not currently supported, but you can obtain it through `graph.getCanvas().getContainer()`.\n\n> In most cases, you do not need to directly manipulate the container.\n\n<Badge type=\"error\">Removed</Badge> **getGroup**\n\n<Badge type=\"warning\">Change</Badge> **getMinZoom / getMaxZoom**\n\nUse `getZoomRange` to obtain the values.\n\n<Badge type=\"warning\">Change</Badge> **setMinZoom / setMaxZoom**\n\nUse the `setZoomRange` method to set the values.\n\n<Badge type=\"warning\">Change</Badge> **getWidth / getHeight**\n\nUse `getSize` to get the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **changeSize**\n\nUse `setSize` to set the dimensions.\n\n<Badge type=\"warning\">Change</Badge> **zoom**\n\nChanged to `zoomBy`.\n\n<Badge type=\"warning\">Change</Badge> **translate**\n\nChanged to `translateBy`.\n\n<Badge type=\"warning\">Change</Badge> **moveTo**\n\nChanged to `translateTo`.\n\n<Badge type=\"warning\">Change</Badge> **focusItem**\n\nChanged to `focusElement`.\n\n<Badge type=\"error\">Removed</Badge> **addItem / updateItem / removeItem**\n\nTo add or remove elements, use the methods `addData` / `updateData` / `removeData` to manipulate data.\n\n<Badge type=\"error\">Removed</Badge> **refreshItem**\n\n<Badge type=\"error\">Removed</Badge> **refreshPositions**\n\n<Badge type=\"error\">Removed</Badge> **updateCombo**\n\n<Badge type=\"error\">Removed</Badge> **updateCombos**\n\n<Badge type=\"error\">Removed</Badge> **updateComboTree**\n\n<Badge type=\"warning\">Change</Badge> **node / edge / combo**\n\nUse the `setNode` / `setEdge` / `setCombo` methods as alternatives.\n\n<Badge type=\"warning\">Change</Badge> **showItem / hideItem**\n\nUse the `setElementVisibility` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **getNodes / getEdges / getCombos / getComboChildren / getNeighbors / find / findById / findAll / findAllByState**\n\nIn version 5.x, direct retrieval of element instances is not supported.\n\n- To obtain element data, use the methods `getData`, `getNodeData`, `getEdgeData`, `getComboData`, which support searching by element ID.\n- To obtain child node data, use the `getChildrenData` method.\n- To obtain neighbor node data, use the `getNeighborNodesData` method.\n- To find element data based on state, use the `getElementDataByState` method.\n\n<Badge type=\"warning\">Change</Badge> **collapseCombo / expandCombo**\n\nUse the `collapseElement` / `expandElement` methods as alternatives.\n\n<Badge type=\"error\">Removed</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">Removed</Badge> **createCombo**\n\nCombos can now be added using the `addData` / `addComboData` methods.\n\n<Badge type=\"error\">Removed</Badge> **uncombo**\n\nCombos can now be removed using the `removeData` / `removeComboData` methods.\n\n<Badge type=\"warning\">Change</Badge> **setItemState**\n\nUse the `setElementState` method as an alternative.\n\n<Badge type=\"error\">Removed</Badge> **clearItemStates**\n\n- To clear all states of a single element: `graph.setElementState(id, [])`\n- To clear all states of multiple elements: `graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">Removed</Badge> **priorityState**\n\nWhen using `setElementState`, the state that appears later in the array has a higher priority.\n\n<Badge type=\"error\">Removed</Badge> **setMode**\n\nUse `setBehaviors` to set the current behaviors.\n\n<Badge type=\"error\">Removed</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">Change</Badge> **layout**\n\nDoes not support parameters. To configure the layout, please use `setLayout`.\n\n<Badge type=\"warning\">Change</Badge> **updateLayout**\n\nChanged to `setLayout`.\n\n<Badge type=\"error\">Removed</Badge> **destroyLayout**\n\n<Badge type=\"warning\">Change</Badge> **addBehaviors / removeBehaviors**\n\nReplaced with `setBehaviors`.\n\n<Badge type=\"error\">Removed</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- For multiple `Hull` instances, you need to configure multiple `hull` plugins in `plugins`, such as:\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- Operations to retrieve, update, and remove `Hull` are implemented through `setPlugins`, `updatePlugin`.\n\n<Badge>Not yet available</Badge> **getNodeDegree**\n\n<Badge>Not yet available</Badge> **getShortestPathMatrix**\n\n<Badge>Not yet available</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">Removed</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\nAll undo and redo related APIs should be called after obtaining the corresponding plugin, for example:\n\n```typescript\n// 'history' is the key configured for use with the plugin\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">Removed</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\nAnimation-related information is now emitted through events:\n\n- Animation start event: `beforeanimate`\n- Animation end event: `afteranimate`\n- To stop an animation:\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">Change</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x uses a different coordinate system than 4.x. For details, see [Coordinate](/en/manual/further-reading/coordinate).\n\n<Badge type=\"error\">Removed</Badge> **setTextWaterMarker / setImageWaterMarker**\n\nFor watermark functionality, please refer to the [Watermark](/en/api/plugins/watermark)plugin.\n\n<Badge type=\"warning\">Change</Badge> **toFullDataURL**\n\nReplaced with `toDataURL`, specify the parameter as: `mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">Removed</Badge> **downloadFullImage / downloadImage**\n\nOnly the capability to export as a `DataURL` is provided. If you need to download an image, please refer to the following example code:\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">Removed</Badge> **clear**\n\nUse `setData` + `draw` to clear data and the canvas.\n\n### Extension Registration\n\nUnlike G6 4.x, G6 5.x uses a unified extension registration function (register). You can refer to the [Extension Register](/en/manual/core-concept/extension#register-extension) to register G6 extensions.\n\nThe following G6 4.x registration functions have been deprecated:\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### Events\n\nCompared to G6 4.x, G6 5.x has the following differences in events:\n\n- The `mouse` and `touch` events have been removed and are unified under the `pointer` event.\n- The naming convention for lifecycle events is usually in the format of: `before/after` + `object/property` + `action`, for example: `beforeelementcreate` is triggered before an element is created.\n- The following events have been removed:\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- The following element change events have been removed, but you can still access them through `beforeelementupdate` and `afterelementupdate`:\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- The following events have been changed:\n  - The `graphstatechange` event has been changed to `beforeelementstatechange` / `afterelementstatechange`.\n  - The `viewportchange` event has been changed to `beforetransform` / `aftertransform`.\n\nFor a complete list of events, please refer to [Event](/en/api/reference/g6#event).\n\n\n<!-- Skill/Rule: Whats-new Skill (packages/site/docs/manual/whats-new/upgrade.zh.md) -->\n---\ntitle: 升级到 5.0\norder: 6\n---\n\n本文档将引导你从 G6 `4.x` 版本升级到 `5.x` 版本。如果你使用的是 `3.x` 版本，请先升级到 `4.x` 版本。\n\n## 升级前准备\n\n1. 请确保当前 git 分支是干净的，没有未提交的代码。\n2. 参考 [安装](/manual/getting-started/installation) 文档安装 `5.x` 版本，并移除 `4.x` 版本依赖。\n\n## 开始升级\n\n### 数据\n\n新版本的数据格式有所变化，具体如下：\n\n1. `nodes` `edges` `combos` 中所有样式属性都需要放在 `style` 中，`data` 中存放数据属性：\n\n```typescript\n// 4.x\nconst data = {\n  nodes: [\n    { id: 'node1', label: 'node1', size: 20 },\n    { id: 'node2', label: 'node2', size: 20 },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n\n// 5.x\nconst data = {\n  nodes: [\n    // label 为非样式属性，放在 data 中，可在样式映射函数中访问\n    // size 为样式属性，放在 style 中\n    { id: 'node1', data: { label: 'node1' }, style: { size: 20 } },\n    { id: 'node2', data: { label: 'node2' }, style: { size: 20 } },\n  ],\n  edges: [{ source: 'node1', target: 'node2' }],\n};\n```\n\n由于我们重新设计实现了元素，新的元素配置项请参考相应文档进行修改：\n\n- [Node](/manual/element/node/overview)\n- [Edge](/manual/element/edge/overview)\n- [Combo](/manual/element/combo/overview)\n\n2. 如果要在数据中指定元素类型，可以使用 `type` 属性：\n\n```typescript\n{\n  nodes: [\n    // 指定节点类型为 rect\n    { id: 'node1', type: 'rect' },\n  ];\n}\n```\n\n### 配置项\n\n<Badge type=\"warning\">变更</Badge> **fitView / fitCenter / fitViewPadding**\n\n- `fitView` 和 `fitCenter` 配置项已经合并为 `autoFit`\n- 若要使用 `fitView`，可以配置为 `autoFit: 'view'`\n- 若要使用 `fitCenter`，可以配置为 `autoFit: 'center'`\n- 也可以传入对象进行完整配置：\n\n```js\nautoFit: {\n  type: 'view',\n  options: {\n    // ...\n  }\n}\n```\n\n- `fitViewPadding` 已变更为 `padding`\n\n<Badge type=\"error\">移除</Badge> **linkCenter**\n\n5.x 的边连接机制会按照如下顺序依次尝试连接到节点/Combo：\n\n1. 连接桩\n2. 轮廓\n3. 中心\n\n<Badge type=\"error\">移除</Badge> **groupByTypes**\n\n<Badge type=\"error\">移除</Badge> **autoPaint**\n\n请手动调用 `render` 或 `draw` 方法进行绘制。\n\n<Badge type=\"warning\">变更</Badge> **modes**\n\n5.x 已经移除交互模式，你可以通过设置 `behaviors` 来切换当前启用的交互行为。\n\n```typescript\n// 4.x\n{\n  modes: {\n    default: ['drag-canvas', 'zoom-canvas'],\n    preview: ['drag-canvas'],\n  },\n}\n\ngraph.setMode('preview');\n```\n\n```typescript\n\n// 5.x\n{\n  behaviors: ['drag-canvas', 'zoom-canvas'],\n}\n\ngraph.setBehaviors(['drag-canvas']);\n\n```\n\n<Badge type=\"warning\">变更</Badge> **defaultNode / defaultEdge / defaultCombo**\n\n元素样式已移至 `[element].style` 中，如 `defaultNode` 变更为 `node.style`：\n\n```typescript\n// 4.x\n{\n  defaultNode: {\n    size: 20,\n    fill: 'red',\n  }\n}\n\n// 5.x\n{\n  node: {\n    style: {\n      size: 20,\n      fill: 'red',\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **nodeStateStyles / edgeStateStyles / comboStateStyle**\n\n元素状态样式已移至 `[element].state` 中，如 `nodeStateStyles` 变更为 `node.stateStyles`：\n\n```typescript\n// 4.x\n{\n  nodeStateStyles: {\n    selected: {\n      fill: 'red',\n    }\n  }\n}\n\n// 5.x\n{\n  node: {\n    state: {\n      selected: {\n        fill: 'red',\n      }\n    }\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **animate / animateCfg**\n\n- `animate` 配置项已变更为 `animation`\n- `animate` 和 `animateCfg` 已合并为 `animation`\n\n```typescript\n// 4.x\n{\n  animate: true,\n}\n\n// 5.x\n{\n  animation: true,\n}\n{\n  animation: {\n    duration: 500,\n    easing: 'easeLinear',\n  }\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **minZoom / maxZoom**\n\n`minZoom` 和 `maxZoom` 已合并为 `zoomRange`\n\n```typescript\n// 4.x\n{\n  minZoom: 0.5,\n  maxZoom: 2,\n}\n\n// 5.x\n{\n  zoomRange: [0.5, 2],\n}\n```\n\n<Badge type=\"warning\">变更</Badge> **renderer**\n\nG6 5.x 支持多层画布，默认使用 `canvas` 渲染。\n\nrenderer 不再支持字符串类型，变更为回调函数：\n\n```typescript\n// 4.x\nvar options = {\n  renderer: 'svg',\n};\n\n// 5.x\nimport { Renderer } from '@antv/g-svg';\n\n{\n  renderer: () => new Renderer(),\n}\n```\n\n<Badge type=\"error\">移除</Badge> **enabledStack / maxStep**\n\n5.x 已移除内置撤销重做功能，相关能力请使用插件实现。\n\n### API\n\n<Badge type=\"warning\">变更</Badge> **data / save / read / changeData**\n\n5.x 提供了全新的数据 API，详见 [数据 API](/api/data)。\n\n- 4.x `data` `changeData` 方法使用 5.x `setData` 替代\n- 4.x `save` 方法使用 5.x `getData` 替代\n- 4.x `read` 方法使用 5.x `setData` + `render` 替代\n\n<Badge type=\"warning\">变更</Badge> **get / set**\n\n若要访问 Graph options，请使用 `getOptions` 或者 `getXxx` API，例如 `getZoomRange` `getBehaviors` 等。 `set` 同理。\n\n<Badge type=\"warning\">变更</Badge> **getContainer**\n\n暂不支持直接获取容器的 API，但可以通过 `graph.getCanvas().getContainer()` 获取。\n\n> 绝大部分情况下，你都不需要直接操作容器。\n\n<Badge type=\"error\">移除</Badge> **getGroup**\n\n<Badge type=\"warning\">变更</Badge> **getMinZoom / getMaxZoom**\n\n使用 `getZoomRange` 获取。\n\n<Badge type=\"warning\">变更</Badge> **setMinZoom / setMaxZoom**\n\n使用 `setZoomRange` 方法设置。\n\n<Badge type=\"warning\">变更</Badge> **getWidth / getHeight**\n\n使用 `getSize` 获取。\n\n<Badge type=\"warning\">变更</Badge> **changeSize**\n\n使用 `setSize` 设置。\n\n<Badge type=\"warning\">变更</Badge> **zoom**\n\n变更为 `zoomBy`。\n\n<Badge type=\"warning\">变更</Badge> **translate**\n\n变更为 `translateBy`。\n\n<Badge type=\"warning\">变更</Badge> **moveTo**\n\n变更为 `translateTo`。\n\n<Badge type=\"warning\">变更</Badge> **focusItem**\n\n变更为 `focusElement`。\n\n<Badge type=\"error\">移除</Badge> **addItem / updateItem / removeItem**\n\n通过 `addData` / `updateData` / `removeData` 方法操作数据来添加或删除元素。\n\n<Badge type=\"error\">移除</Badge> **refreshItem**\n\n<Badge type=\"error\">移除</Badge> **refreshPositions**\n\n<Badge type=\"error\">移除</Badge> **updateCombo**\n\n<Badge type=\"error\">移除</Badge> **updateCombos**\n\n<Badge type=\"error\">移除</Badge> **updateComboTree**\n\n<Badge type=\"warning\">变更</Badge> **node / edge / combo**\n\n使用 `setNode` / `setEdge` / `setCombo` 方法替代。\n\n<Badge type=\"warning\">变更</Badge> **showItem / hideItem**\n\n使用 `setElementVisibility` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **getNodes / getEdges / getCombos / getComboChildren /getNeighbors /find /findById / findAll /findAllByState**\n\n5.x 不支持直接获取元素实例。\n\n- 若要获取元素数据，使用 `getData` `getNodeData` `getEdgeData` `getComboData` 方法，支持传入元素 id 进行查找。\n- 获取子节点数据，使用 `getChildrenData` 方法。\n- 获取邻居节点数据，使用 `getNeighborNodesData` 方法。\n- 基于状态查找元素数据，使用 `getElementDataByState`。\n\n<Badge type=\"warning\">变更</Badge> **collapseCombo / expandCombo**\n\n使用 `collapseElement` / `expandElement` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **collapseExpandCombo**\n\n<Badge type=\"error\">移除</Badge> **createCombo**\n\n通过 `addData` / `addComboData` 方法添加 Combo。\n\n<Badge type=\"error\">移除</Badge> **uncombo**\n\n通过 `removeData` / `removeComboData` 方法移除 Combo。\n\n<Badge type=\"warning\">变更</Badge> **setItemState**\n\n使用 `setElementState` 方法替代。\n\n<Badge type=\"error\">移除</Badge> **clearItemStates**\n\n- 清除单个元素所有状态：`graph.setElementState(id, [])`\n- 清除多个元素所有状态：`graph.setElementState({ id1: [], id2: [] })`\n\n<Badge type=\"error\">移除</Badge> **priorityState**\n\n`setElementState` 时状态数组中靠后的状态优先级更高。\n\n<Badge type=\"error\">移除</Badge> **setMode**\n\n使用 `setBehaviors` 来设置当前交互。\n\n<Badge type=\"error\">移除</Badge> **setCurrentMode**\n\n<Badge type=\"warning\">变更</Badge> **layout**\n\n不支持参数，如需配置布局，请使用 `setLayout`。\n\n<Badge type=\"warning\">变更</Badge> **updateLayout**\n\n变更为 `setLayout`。\n\n<Badge type=\"error\">移除</Badge> **destroyLayout**\n\n<Badge type=\"warning\">变更</Badge> **addBehaviors / removeBehaviors**\n\n使用 `setBehaviors` 替代。\n\n<Badge type=\"error\">移除</Badge> **createHull / getHulls / removeHull / removeHulls**\n\n- 多个 `Hull` 需在 `plugins` 中配置多个 `hull` 插件，如：\n\n```typescript\n{\n  plugins: ['hull', 'hull'],\n};\n```\n\n- `Hull` 的获取、更新、移除操作通过 `setPlugins`, `updatePlugin` 实现。\n\n<Badge>暂未提供</Badge> **getNodeDegree**\n\n<Badge>暂未提供</Badge> **getShortestPathMatrix**\n\n<Badge>暂未提供</Badge> **getAdjMatrix**\n\n<Badge type=\"error\">移除</Badge> **pushStack / getUndoStack / getRedoStack / getStackData / clearStack**\n\n所有撤销重做相关 API 请获取到对应插件后调用 API，例：\n\n```typescript\n// 'history' 为使用插件时配置的 key\nconst history = graph.getPluginInstance('history');\n\nhistory.redo();\n```\n\n<Badge type=\"error\">移除</Badge> **positionsAnimate / stopAnimate / isAnimating**\n\n动画相关信息通过事件抛出：\n\n- 动画开始事件：`beforeanimate`\n- 动画结束事件：`afteranimate`\n- 停止动画：\n\n```typescript\ngraph.on('beforeanimate', (event) => {\n  event.animation.stop();\n});\n```\n\n<Badge type=\"warning\">变更</Badge> **getPointByClient / getClientByPoint / getPointByCanvas / getCanvasByPoint / getGraphCenterPoint / getViewPortCenterPoint**\n\nG6 5.x 采用了与 4.x 不同的坐标系，详见 [坐标系](/manual/further-reading/coordinate)。\n\n<Badge type=\"error\">移除</Badge> **setTextWaterMarker / setImageWaterMarker**\n\n要使用水印功能，请参考 [水印](/manual/plugin/watermark)插件。\n\n<Badge type=\"warning\">变更</Badge> **toFullDataURL**\n\n使用 `toDataURL` 替代，指定参数为：`mode: 'overall'`\n\n```typescript\ngraph.toDataURL({ mode: 'overall' });\n```\n\n<Badge type=\"error\">移除</Badge> **downloadFullImage / downloadImage**\n\n仅提供导出为 `DataURL` 的能力，如需下载图片，请参考如下实例代码：\n\n```typescript\nasync function downloadImage() {\n  const dataURL = await graph.toDataURL();\n  const [head, content] = dataURL.split(',');\n  const contentType = head.match(/:(.*?);/)![1];\n\n  const bstr = atob(content);\n  let length = bstr.length;\n  const u8arr = new Uint8Array(length);\n\n  while (length--) {\n    u8arr[length] = bstr.charCodeAt(length);\n  }\n\n  const blob = new Blob([u8arr], { type: contentType });\n\n  const url = URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = 'graph.png';\n  a.click();\n}\n```\n\n<Badge type=\"error\">移除</Badge> **clear**\n\n使用 `setData` + `draw` 清空数据和画布。\n\n### 扩展注册\n\n与 G6 4.x 不同，G6 5.x 使用的统一的扩展注册函数(register)，你可以参考 [注册扩展](/manual/graph/extension#注册扩展) 来注册 G6 扩展。\n\n下列 G6 4.x 的注册函数已经废除：\n\n- registerNode\n- registerEdge\n- registerCombo\n- registerLayout\n- registerBehavior\n\n### 事件\n\n与 G6 4.x 相比，G6 5.x 的事件但存下如下差异：\n\n- 移除了 `mouse` 和 `touch` 事件，统一使用 `pointer` 事件\n- 生命周期事件名命名格式通常为： `before/after` + `对象/属性` + `操作`，例如：`beforeelementcreate` 表示在创建元素前触发\n- 下列事件已被移除：\n  - afteractivaterelations\n  - afteradditem\n  - aftercreateedge\n  - aftergraphrefresh\n  - aftergraphrefreshposition\n  - afteritemrefresh\n  - aftermodechange\n  - afterremoveitem\n  - afterupdateitem\n  - beforeadditem\n  - beforecreateedge\n  - beforegraphrefresh\n  - beforegraphrefreshposition\n  - beforeitemrefresh\n  - beforemodechange\n  - beforeremoveitem\n  - beforeupdateitem\n  - dragnodeend\n  - nodeselectchange\n  - stackchange\n  - tooltipchange\n- 下列元素变更事件被移除，但你仍可通过 `beforeelementupdate` 和 `afterelementupdate` 获取：\n  - afteritemstatechange\n  - afteritemstatesclear\n  - afteritemvisibilitychange\n  - beforeitemstatechange\n  - beforeitemstatesclear\n  - beforeitemvisibilitychange\n- 下列事件有所变更：\n  - graphstatechange 事件变更为 beforeelementstatechange / afterelementstatechange\n  - viewportchange 事件变更为 beforetransform / aftertransform\n\n完整的事件列表请参考 [事件](/api/event)。\n\n\n<!-- Skill/Rule: cli Documentation (packages/cli/README.md) -->\n# @antv/g6-cli\n\n`@antv/g6-cli` is a G6 template generation tool that comes with several templates.\n\nCurrently, it owns a built-in template called `extension`. This template handles the boilerplate setup, which encompasses a seamless local development environment, linting, code formatting, Jest for snapshot testing and bundling with Rollup etc.\n\n`@antv/g6-cli` i\n\n## Getting Started\n\nTo start using `@antv/g6-cli`, you'll first need to install it globally.\n\n```bash\nnpm i @antv/g6-cli -g\n```\n\nOnce installed, you can easily scaffold a new project:\n\n```bash\ncreate-g6\n```\n\nThen follow the prompts!\n\n![prompts](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*09BKQrIcZUMAAAAAAAAAAAAADmJ7AQ/original)\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a **G6 Extension** project, run:\n\n```bash\ncreate-g6 g6-extension-test --template extension\n```\n\n\n<!-- Skill/Rule: g6-extension-3d Documentation (packages/g6-extension-3d/README.md) -->\n## 3D extension for G6\n\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*lEL3TrCLnPsAAAAAAAAAAAAADmJ7AQ/original\" />\n<img width=\"300\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yFa5RKilu6kAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension package provides 3D elements, behaviors and plugins for G6.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-3d\n```\n\n2. Import and Register\n\n> Where renderer, elements and lighting are necessary\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { DragCanvas3D, Light, Line3D, Sphere, renderer } from '@antv/g6-extension-3d';\n\n// 3d light plugin\nregister(ExtensionCategory.PLUGIN, '3d-light', Light);\n// sphere node element\nregister(ExtensionCategory.NODE, 'sphere', Sphere);\n// line edge element\nregister(ExtensionCategory.EDGE, 'line3d', Line3D);\n// drag canvas in 3d scene\nregister(ExtensionCategory.BEHAVIOR, 'drag-canvas-3d', DragCanvas3D);\n// camera setting plugin\nregister(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting);\n```\n\n3. Use\n\n```js\nimport { Graph } from '@antv/g6';\n\nconst graph = new Graph({\n  container: 'container',\n  renderer, // use 3d renderer\n  data: {\n    // your data\n  },\n  node: {\n    type: 'sphere', // use sphere node\n  },\n  edge: {\n    type: 'line3d', // use 3d line edge\n  },\n  behaviors: ['drag-canvas-3d'],\n  plugins: [\n    // set camera configs, see: https://g.antv.antgroup.com/en/api/camera/intro\n    {\n      type: 'camera-setting',\n      projectionMode: 'perspective',\n      near: 0.1,\n      far: 1000,\n      fov: 45,\n      aspect: 1,\n    },\n    // add directional light\n    {\n      type: '3d-light',\n      directional: {\n        direction: [0, 0, 1],\n      },\n    },\n  ],\n});\n```\n\n## Resources\n\n- [Lite Solar System](https://g6.antv.antgroup.com/en/examples/feature/default/#lite-solar-system)\n- [3D Node](https://g6.antv.antgroup.com/en/examples/element/node/#3d-node)\n\n\n<!-- Skill/Rule: g6-extension-react Documentation (packages/g6-extension-react/README.md) -->\n## React extension for G6\n\n<img width=\"500\" src=\"https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rWSiT6dnwfcAAAAAAAAAAAAADmJ7AQ/original\" />\n\nThis extension allows you to define G6 node by React component and JSX syntax.\n\n## Usage\n\n1. Install\n\n```bash\nnpm install @antv/g6-extension-react\n```\n\n2. Import and Register\n\n```js\nimport { ExtensionCategory, register } from '@antv/g6';\nimport { ReactNode } from '@antv/g6-extension-react';\n\nregister(ExtensionCategory.NODE, 'react', ReactNode);\n```\n\n3. Define Node\n\nReact Node:\n\n```jsx\nconst ReactNode = () => {\n  return <div>node</div>;\n};\n```\n\nG Node:\n\n```jsx\nimport { Group, Rect, Text } from '@antv/g6-extension-react';\n\nconst GNode = () => {\n  return <Group>\n    <Rect width={100} height={100}></Rect>\n    <Text text={\"node\"} />\n  <Group>\n};\n```\n\n4. Use\n\nUse ReactNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'react',\n    style: {\n      component: () => <ReactNode />,\n    },\n  },\n});\n```\n\nUse GNode:\n\n```jsx\nconst graph = new Graph({\n  // ... other options\n  node: {\n    type: 'g',\n    style: {\n      component: () => <GNode />,\n    },\n  },\n});\n```\n\n## Q&A\n\n1. Difference between ReactNode and GNode\n\nReactNode is a React component, while GNode support jsx syntax but can only use G tag node.\n\n## Resources\n\n- [React node](https://g6.antv.antgroup.com/examples/element/custom-node/#react-node)\n- [G node with JSX syntax](https://g6.antv.antgroup.com/en/examples/element/custom-node/#react-g)\n\n\n<!-- Skill/Rule: g6-ssr Documentation (packages/g6-ssr/README.md) -->\n## SSR extension for G6 5.0\n\nThis extension package provides SSR support for G6 5.0, which supports canvas rendering in server side.\n\n## Usage\n\n### Install\n\n```bash\nnpm install @antv/g6-ssr\n```\n\n### Render in JavaScript API\n\n> For complete options, please refer to [G6 Graph Options](https://g6.antv.antgroup.com/api/graph/option)\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  imageType: 'png', // or 'jpeg'\n  data: {\n    // data\n  },\n  // other options\n});\n\ngraph.exportToFile('image');\n// -> image.png\n\ngraph.toBuffer();\n// -> get buffer\n```\n\n### Render in CLI\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./image\n```\n\n### Export SVG / PDF\n\nWhen render in JavaScript API, you can pass `outputType` option to export SVG or PDF.\n\n```js\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  data: {\n    // data\n  },\n  outputType: 'svg', // or 'pdf'\n  // other options\n});\n```\n\nWhen render in CLI, you can pass `-t` or `--type` option to export SVG or PDF.\n\n```bash\nnpx g6-ssr export -i [graph-options].json -o ./file -t pdf\n```\n\n### Register Custom G6 Extensions\n\nIf you need to register custom extensions of G6, please use the `registry` function exported from `@antv/g6-ssr`.\n\n```js\nimport { createGraph, registry } from '@antv/g6-ssr';\nimport { BaseNode, ExtensionCategory } from '@antv/g6';\n\nclass CustomNode extends BaseNode {\n  // custom node\n}\n\nregistry(ExtensionCategory.Node, 'custom-node', CustomNode);\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  node: {\n    type: 'custom-node',\n    // other options\n  },\n  // other options\n});\n```\n\n### Use Plugins\n\nWhen using G6-SSR, you can also use G render plugins. Here's how to use plugins in server-side rendering:\n\n```js\nimport { createGraph } from '@antv/g6-ssr';\nimport { Plugin as RoughCanvasPlugin } from '@antv/g-plugin-rough-canvas-renderer';\n\nconst graph = await createGraph({\n  width: 500,\n  height: 500,\n  renderPlugins: [new RoughCanvasPlugin()],\n  data: {\n    // data\n  },\n});\n```\n\n## License\n\nMIT\n\n\n<!-- Skill/Rule: hull Documentation (packages/g6/src/plugins/hull/hull/README.md) -->\n> Code copied from [hull-js](https://github.com/hull/hull-js), and fix the issue [[Bug]: hull.js Code Injection Vulnerability #6605](https://github.com/antvis/G6/issues/6605).\n\n\n</agent_rules>"}